[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)