[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
MiNT 1.09 diffs: XATTR for biosfs & more
Hi there!
Here's finally the result of all my questions and/or discussions about the
bios filesystem and the XATTR structure. I consider them being serious ideas
and would like to have them officially included, that's why I tried to be so
carefully and wanted to discuss this first.
It's true that the datime() method would provide more security if you
couldn't directly access the bios_file structure via f->fc.index, but
removing this would cause a major rewrite of the biosfs code and might
end up in using a size-fixed list of bios_file's for which the fc.index
field isn't really more than an index, plus some more troubles like what
happens if you install an extra bios device but the internal datime() call
doesn't know about this bios number. Ah, well, plus some more, perhaps.
So I choose the other way round that every external device driver can
access this structure as described above and is fully responsible for time
updates or any other trash it might perhaps want to do. To minimize the
risk a bit, Dcntl() calls are now restricted to the superuser.
This shouldn't disturb you if you're using MiNT as a basis for MultiTOS,
since you'll never be anybody else but the superuser, but will hopefully
conform the ideas of most of the people using it for other purposes, like
a UN*X like system.
Since this also involves changes in the fasttext driver, I've chosen to put
the declaration of the bios_file into file.h, so that it can be easily
accessed by it or any other future device drivers.
There are actually some more security changes, so here comes a brief list:
file.h, biosfs.c, fasttext.c:
- added XATTR structure to bios files allowing them to have ownership, access
modes and timestamps like any(?) other file
- restricted Dcntl() calls to the superuser to be a bit more secure
- fixed a bug with links so that ls now works correct on them
mint.h, syscall.spp, bios.c:
- introduced a flag variable "in_dos", which allows bios calls to determine
if they derived from a gemdos call or not. most important application:
rwabs() is now only allowed if you're either the superuser or it was
a gemdos call, thus making it impossible(?) for any other user to
trash the filesystem
tosfs.c:
- changed the getxattr() call so that the "other user" bits are masked out, so
files will look like "rwxrwx---" and again only the superuser is
allowed to access TOS partitions. Is there a better way of protection?
- changed the chown() call to report the change was successfully, cause I
was getting really annoyed by mv's error messages
so long,
TeSche
--
PS: If the above written looks weird, then that's probably because it _is_.
WhoDunnIt: Torsten Scherer (Schiller, Tesche, ...)
Where: Faculty of Technology, University of Bielefeld, Germany
EMail: itschere@techfak.uni-bielefeld.de / tesche@hrz.uni-bielefeld.de
--- cut cut cut ---
diff -u4 orig/bios.c my/bios.c
--- orig/bios.c Fri Nov 19 15:33:56 1993
+++ my/bios.c Fri Nov 19 17:37:58 1993
@@ -80,8 +80,11 @@
/* variables for monitoring the keyboard */
IOREC_T *keyrec; /* keyboard i/o record pointer */
short kintr = 0; /* keyboard interrupt pending (see intr.s) */
+/* TeSche: flag to recognize GEMDOS operations */
+int in_dos;
+
/* Getmpb is not allowed under MiNT */
long ARGS_ON_STACK
getmpb(ptr)
@@ -305,8 +308,14 @@
long lrecno;
{
long r;
extern PROC *dlockproc[]; /* in dosdir.c */
+
+ /* TeSche: */
+ if (curproc->euid && !in_dos) {
+ DEBUG(("Rwabs by non-privileged process requested"));
+ return EACCDN;
+ }
if (dev >= 0 && dev < NUM_DRIVES && dlockproc[dev]) {
if (dlockproc[dev] != curproc) {
DEBUG(("Rwabs: device %c is locked", dev+'A'));
diff -u4 orig/biosfs.c my/biosfs.c
--- orig/biosfs.c Fri Nov 19 15:34:00 1993
+++ my/biosfs.c Mon Nov 29 09:13:20 1993
@@ -108,20 +108,8 @@
struct tty con_tty, aux_tty, midi_tty;
struct tty sccb_tty, scca_tty, ttmfp_tty;
-#define BNAME_MAX 13
-
-struct bios_file {
- char name[BNAME_MAX+1]; /* device name */
- DEVDRV *device; /* device driver for device */
- short private; /* extra info for device driver */
- ushort flags; /* flags for device open */
- struct tty *tty; /* tty structure (if appropriate) */
- struct bios_file *next;
- short lockpid; /* owner of the lock */
-};
-
struct bios_file BDEV[] = {
/* "real" bios devices present on all machines */
{"centr", &bios_ndevice, 0, 0, 0, 0},
@@ -166,16 +154,54 @@
*/
FILEPTR *defaultaux;
+/* ts: a xattr field used for the root directory, 'cause there's no
+ * bios_file structure for it.
+ */
+
+XATTR rxattr;
+
+/* ts: a small utility function to set up a xattr structure
+ */
+
+void set_xattr(XATTR *xp, ushort mode)
+{
+ xp->mode = mode;
+ xp->index = 0L;
+ xp->dev = 0;
+ xp->reserved1 = 0L;
+ xp->nlink = 1;
+ xp->uid = curproc->euid;
+ xp->gid = curproc->egid;
+ xp->size = 0L;
+ xp->blksize = 1L;
+ xp->nblocks = 0L;
+/* timestamp/datestamp are not yet initialized when the biosfs comes up */
+ xp->mtime = xp->atime = xp->ctime = Tgettime();
+ xp->mdate = xp->adate = xp->cdate = Tgetdate();
+/* root directory only */
+ if ((mode & S_IFMT) == S_IFDIR)
+ xp->attr = FA_DIR;
+ else
+ xp->attr = 0;
+ xp->reserved2 = 0;
+ xp->reserved3[0] = 0L;
+ xp->reserved3[1] = 0L;
+}
+
void
biosfs_init()
{
struct bios_file *b;
broot = BDEV;
+ set_xattr(&rxattr, S_IFDIR | DEFAULT_DIRMODE);
for (b = broot; b->name[0]; b++) {
+
+ set_xattr(&b->xattr, S_IFCHR | DEFAULT_MODE);
+
b->next = b+1;
/* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
* device 1
@@ -270,32 +296,25 @@
{
FILEPTR *f;
struct bios_file *b = (struct bios_file *)fc->index;
- xattr->index = fc->index;
- xattr->dev = fc->dev;
- xattr->nlink = 1;
- xattr->uid = xattr->gid = 0;
- xattr->size = xattr->nblocks = 0;
- xattr->blksize = 1;
- xattr->mtime = xattr->atime = xattr->ctime = timestamp;
- xattr->mdate = xattr->adate = xattr->cdate = datestamp;
- if (fc->index == 0) { /* root directory? */
- xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
- xattr->attr = FA_DIR;
- } else if (b->device == 0) { /* symbolic link? */
- xattr->mode = S_IFLNK | DEFAULT_DIRMODE;
- } else if (b->device == &fakedev &&
- (f = curproc->handle[b->private]) != 0)
- {
- /* u:\dev\stdin, u:\dev\stdout, etc. */
- (*f->fc.fs->getxattr) (&f->fc, xattr);
- xattr->index = fc->index;
- xattr->dev = fc->dev;
+ if (b == 0) {
+ /* root directory */
+ *xattr = rxattr;
+ xattr->index = fc->index;
+ xattr->dev = fc->dev;
+ } else if (b->device == &fakedev && (f = curproc->handle[b->private]) != 0) {
+ /* u:\dev\stdin, u:\dev\stdout, etc. */
+ (*f->fc.fs->getxattr) (&f->fc, xattr);
+ xattr->index = fc->index;
+ xattr->dev = fc->dev;
} else {
- xattr->mode = S_IFCHR | DEFAULT_MODE;
- xattr->attr = 0;
+ /* all the rest... */
+ *xattr = b->xattr;
+ xattr->index = fc->index;
+ xattr->dev = fc->dev;
}
+
return 0;
}
static long ARGS_ON_STACK
@@ -311,20 +330,48 @@
bios_chown(fc, uid, gid)
fcookie *fc;
int uid, gid;
{
- UNUSED(fc); UNUSED(uid);
- UNUSED(gid);
- return EINVFN;
+ struct bios_file *b = (struct bios_file *)fc->index;
+
+ if (!(curproc->euid)) {
+ if (!b) {
+ /* biosfs root directory */
+ rxattr.uid = uid;
+ rxattr.gid = gid;
+ } else {
+ /* any other entry */
+ b->xattr.uid = uid;
+ b->xattr.gid = gid;
+ }
+
+ return 0;
+ }
+
+ return EACCDN;
}
static long ARGS_ON_STACK
bios_chmode(fc, mode)
fcookie *fc;
unsigned mode;
{
- UNUSED(fc); UNUSED(mode);
- return EINVFN;
+ struct bios_file *b = (struct bios_file *)fc->index;
+
+ if (!b) {
+ /* root directory */
+ if (!curproc->euid || (curproc->euid == rxattr.uid)) {
+ rxattr.mode = (rxattr.mode & S_IFMT) | mode;
+ return 0;
+ }
+ } else {
+ if (!curproc->euid && (curproc->euid == b->xattr.uid)) {
+ b->xattr.mode = (b->xattr.mode & S_IFMT) | mode;
+ return 0;
+ }
+ }
+
+ return EACCDN;
}
long ARGS_ON_STACK
nomkdir(dir, name, mode)
@@ -363,8 +410,13 @@
if (!stricmp(b->name, name)) break;
}
if (!b) return EFILNF;
+/* don't allow removal of the device if we don't own it */
+ if (curproc->euid && (curproc->euid != b->xattr.uid)) {
+ return EACCDN;
+ }
+
/* don't allow removal of the basic system devices */
if (b >= BDEV && b <= bdevlast) {
return EACCDN;
}
@@ -551,13 +603,24 @@
{
struct bios_file *b;
UNUSED(dir);
+
+ /* TeSche: */
+ if (curproc->euid) {
+ DEBUG(("biosfs: device install by non-privileged process requested"));
+ if ((unsigned)cmd) == DEV_INSTALL)
+ return 0;
+ else
+ return EACCDN;
+ }
+
if ((unsigned)cmd == DEV_INSTALL) {
struct dev_descr *d = (struct dev_descr *)arg;
b = kmalloc(SIZEOF(struct bios_file));
if (!b) return 0;
+ set_xattr(&(b->xattr), S_IFCHR | DEFAULT_MODE);
strncpy(b->name, name, BNAME_MAX);
b->name[BNAME_MAX] = 0;
b->device = d->driver;
b->private = d->dinfo;
@@ -569,8 +632,9 @@
}
if ((unsigned)cmd == DEV_NEWTTY) {
b = kmalloc(SIZEOF(struct bios_file));
if (!b) return ENSMEM;
+ set_xattr(&(b->xattr), S_IFCHR | DEFAULT_MODE);
b->tty = kmalloc(SIZEOF(struct tty));
if (!b->tty) {
kfree(b);
return ENSMEM;
@@ -587,8 +651,9 @@
}
if ((unsigned)cmd == DEV_NEWBIOS) {
b = kmalloc(SIZEOF(struct bios_file));
if (!b) return ENSMEM;
+ set_xattr(&(b->xattr), S_IFCHR | DEFAULT_MODE);
strncpy(b->name, name, BNAME_MAX);
b->name[BNAME_MAX] = 0;
b->tty = 0;
b->device = &bios_ndevice;
@@ -609,27 +674,38 @@
long r;
fcookie fc;
r = bios_lookup(dir, name, &fc);
- if (r == 0) return EACCDN; /* file already exists */
- if (r != EFILNF) return r; /* some other error */
+ if (r == 0)
+ return EACCDN; /* file already exists */
+ if (r != EFILNF)
+ return r; /* some other error */
+
b = kmalloc(SIZEOF(struct bios_file));
- if (!b) return EACCDN;
+ if (!b)
+ return EACCDN;
strncpy(b->name, name, BNAME_MAX);
b->name[BNAME_MAX] = 0;
b->device = 0;
b->private = EINVFN;
b->flags = 0;
- b->tty = kmalloc((long)strlen(to)+1);
+
+ b->tty = kmalloc(strlen(to)+1);
if (!b->tty) {
kfree(b);
return EACCDN;
}
+
strcpy((char *)b->tty, to);
+
+ set_xattr(&b->xattr, S_IFLNK | DEFAULT_DIRMODE);
+ b->xattr.size = strlen(to)+1; /* this must include the \0 */
+
b->next = broot;
broot = b;
+
return 0;
}
static long ARGS_ON_STACK
@@ -639,10 +715,13 @@
int buflen;
{
struct bios_file *b = (struct bios_file *)fc->index;
- if (!b) return EINVFN;
- if (b->device) return EINVFN;
+ if (!b)
+ return EINVFN;
+
+ if (b->device)
+ return EINVFN;
strncpy(buf, (char *)b->tty, buflen);
if (strlen((char *)b->tty) >= buflen)
return ENAMETOOLONG;
@@ -783,18 +862,31 @@
long ARGS_ON_STACK
null_write(f, buf, bytes)
FILEPTR *f; const char *buf; long bytes;
{
- UNUSED(f); UNUSED(buf);
+ struct bios_file *b = (struct bios_file *)f->fc.index;
+
+ UNUSED(buf);
+ if (bytes > 0) {
+ b->xattr.mtime = timestamp;
+ b->xattr.mdate = datestamp;
+ }
+
return bytes;
}
long ARGS_ON_STACK
null_read(f, buf, bytes)
FILEPTR *f; char *buf; long bytes;
{
- UNUSED(f); UNUSED(buf);
- UNUSED(bytes);
+ struct bios_file *b = (struct bios_file *)f->fc.index;
+
+ UNUSED(buf);
+ if (bytes > 0) {
+ b->xattr.atime = timestamp;
+ b->xattr.adate = datestamp;
+ }
+
return 0;
}
long ARGS_ON_STACK
@@ -891,8 +983,9 @@
{
long *r;
long ret = 0;
int bdev = f->fc.aux;
+ struct bios_file *b = (struct bios_file *)f->fc.index;
r = (long *)buf;
/* Check for control characters on any newline output.
@@ -920,8 +1013,13 @@
}
#if 0
(void)checkkeys();
#endif
+ if (ret > 0) {
+ b->xattr.mtime = timestamp;
+ b->xattr.mdate = datestamp;
+ }
+
return ret;
}
static long ARGS_ON_STACK
@@ -929,8 +1027,9 @@
FILEPTR *f; char *buf; long bytes;
{
long *r, ret = 0;
int bdev = f->fc.aux;
+ struct bios_file *b = (struct bios_file *)f->fc.index;
r = (long *)buf;
if ((f->flags & O_NDELAY)) {
@@ -945,8 +1044,12 @@
*r++ = bconin(bdev) & 0x7fffffffL;
bytes -= 4; ret += 4;
}
}
+ if (ret > 0) {
+ b->xattr.atime = timestamp;
+ b->xattr.adate = datestamp;
+ }
return ret;
}
/*
@@ -960,8 +1063,9 @@
{
long ret = 0;
int bdev = f->fc.aux;
int c;
+ struct bios_file *b = (struct bios_file *)f->fc.index;
while (bytes > 0) {
if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
break;
@@ -972,8 +1076,12 @@
break;
bytes--; ret++;
}
+ if (ret > 0) {
+ b->xattr.mtime = timestamp;
+ b->xattr.mdate = datestamp;
+ }
return ret;
}
static long ARGS_ON_STACK
@@ -981,15 +1089,20 @@
FILEPTR *f; char *buf; long bytes;
{
long ret = 0;
int bdev = f->fc.aux;
+ struct bios_file *b = (struct bios_file *)f->fc.index;
while (bytes > 0) {
if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
break;
*buf++ = bconin(bdev) & 0xff;
bytes--; ret++;
}
+ if (ret > 0) {
+ b->xattr.atime = timestamp;
+ b->xattr.adate = datestamp;
+ }
return ret;
}
/*
@@ -1422,8 +1535,9 @@
{
long count = 0;
int mhead;
unsigned char *foo;
+ struct bios_file *b = (struct bios_file *)f->fc.index;
mhead = mousehead;
foo = &mousebuf[mhead];
@@ -1445,8 +1559,12 @@
count++;
--nbytes;
}
mousehead = mhead;
+ if (count > 0) {
+ b->xattr.atime = timestamp;
+ b->xattr.adate = datestamp;
+ }
return count;
}
static long ARGS_ON_STACK
diff -u4 orig/fasttext.c my/fasttext.c
--- orig/fasttext.c Fri Nov 19 15:34:18 1993
+++ my/fasttext.c Sat Nov 27 18:33:42 1993
@@ -1221,8 +1221,9 @@
static long ARGS_ON_STACK
screen_write(f, buf, bytes)
FILEPTR *f; const char *buf; long bytes;
{
+ struct bios_file *b = (struct bios_file *)f->fc.index;
SCREEN *v = current;
long *r;
long ret = 0;
int c;
@@ -1244,15 +1245,20 @@
else
v->hidecnt = 0;
curs_on(v);
v->flags &= ~CURS_UPD;
+ if (ret > 0) {
+ b->xattr.mtime = timestamp;
+ b->xattr.mdate = datestamp;
+ }
return ret;
}
static long ARGS_ON_STACK
screen_read(f, buf, bytes)
FILEPTR *f; char *buf; long bytes;
{
+ struct bios_file *b = (struct bios_file *)f->fc.index;
long *r, ret = 0;
r = (long *)buf;
@@ -1260,8 +1266,12 @@
if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
break;
*r++ = bconin(CONDEV) & 0x7fffffffL;
bytes -= 4; ret += 4;
+ }
+ if (ret > 0) {
+ b->xattr.atime = timestamp;
+ b->xattr.adate = datestamp;
}
return ret;
}
diff -u4 orig/file.h my/file.h
--- orig/file.h Fri Nov 19 15:34:20 1993
+++ my/file.h Sat Nov 27 18:32:28 1993
@@ -550,5 +550,20 @@
extern struct tty default_tty;
extern char follow_links[];
#endif
+/* internal bios file structure */
+
+#define BNAME_MAX 13
+
+struct bios_file {
+ char name[BNAME_MAX+1]; /* device name */
+ DEVDRV *device; /* device driver for device */
+ short private; /* extra info for device driver */
+ ushort flags; /* flags for device open */
+ struct tty *tty; /* tty structure (if appropriate) */
+ struct bios_file *next;
+ short lockpid; /* owner of the lock */
+ XATTR xattr; /* guess what... */
+};
+
#endif /* _filesys_h */
diff -u4 orig/mint.h my/mint.h
--- orig/mint.h Fri Nov 19 15:34:32 1993
+++ my/mint.h Fri Nov 19 17:01:02 1993
@@ -228,5 +228,7 @@
* load some inline functions, perhaps
*/
#include "inline.h"
+extern int in_dos; /* TeSche: see bios.c & syscall.spp */
+
#endif /* GENMAGIC */
diff -u4 orig/syscall.spp my/syscall.spp
--- orig/syscall.spp Fri Nov 19 15:34:44 1993
+++ my/syscall.spp Fri Nov 19 17:35:04 1993
@@ -66,10 +66,12 @@
XREF _bconbuf,_bconbsiz,_bconbdev
XREF _bflush
XREF _ubconstat,_do_bconin,_ubcostat,_kbshift
-
+ XREF _in_dos
+
_mint_dos:
+ move.w #1,_in_dos ; GEMDOS flag
clr.w -(sp) ; no frame format needed
; NOTE: FOR NOW, WE PRESERVE A0 ACROSS GEMDOS CALLS. THIS WILL CHANGE
; SOMEDAY, DON'T RELY ON IT!!!
move.l _curproc,d0 ; note: preserve all regs but d0
@@ -268,8 +270,9 @@
addq.w #2,sp ; pop function number off stack
move.l d0,a0
jsr (a0) ; go do the call
out:
+ clr.w _in_dos ; GEMDOS flag
move.l _curproc,a0
move.l d0,P_SYSCTXT+C_D0(a0) ; set d0 in the saved context
move.w P_SYSCTXT+C_SR(a0),d0 ; get saved status register
diff -u4 orig/tosfs.c my/tosfs.c
--- orig/tosfs.c Fri Nov 19 15:34:48 1993
+++ my/tosfs.c Wed Nov 24 09:01:06 1993
@@ -583,8 +583,13 @@
if (ti->attr & FA_EXEC) {
xattr->mode |= (S_IXUSR|S_IXGRP|S_IXOTH);
}
xattr->attr = ti->attr & 0xff;
+
+ xattr->mode &= ~S_IROTH;
+ xattr->mode &= ~S_IWOTH;
+ xattr->mode &= ~S_IXOTH;
+
return 0;
}
static long ARGS_ON_STACK
@@ -608,9 +613,10 @@
fcookie *dir;
int uid, gid;
{
UNUSED(dir); UNUSED(uid); UNUSED(gid);
- return EINVFN;
+/* ts: ignore errors */
+ return 0;
}
static long ARGS_ON_STACK
tos_chmode(fc, mode)