[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

MiNT 1.09 security: f_delete() patch



Hi!

 Here's a patch which makes MiNT's f_delete() respect the sticky bit according
to the semantic how I understand it and hope it really is... Well, at least
it's better and/or a bit more secure than it is now... :-)

 It goes like this:

 If I haven't write permission to the parent directory, I loose. Otherwise,
if the sticky bit isn't set, I can delete anything regardless of its mode
or if it's mine at all. If the sticky bit is set, I can only delete a file
if it's mine, or if the whole directory is mine. In the last case I again can
delete every file in the directory.

 Well, look at the code if you like... :-)

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

--- orig/dosdir.c	Fri Nov 19 15:34:12 1993
+++ my/dosdir.c	Fri Dec 17 11:02:50 1993
@@ -716,36 +716,78 @@
 		release_cookie(&fc);
 		return xattr.attr;
 	}
 }
 
+/* tesche: this one respects the sticky bit
+ */
+
 long ARGS_ON_STACK
 f_delete(name)
 	const char *name;
 {
-	fcookie dir;
-	long r;
-	char temp1[PATH_MAX];
+	fcookie	dir, fc;
+	long	r;
+	char	temp1[PATH_MAX];
+	XATTR	dxattr, fxattr;
 
 	TRACE(("Fdelete(%s)", name));
 
-	r = path2cookie(name, temp1, &dir);
+/* first, get the directory cookie */
+	if ((r = path2cookie(name, temp1, &dir))) {
+		DEBUG(("Fdelete(%s): error %ld, perhaps path not found", name, r));
+		return r;
+	}
 
-	if (r) {
-		DEBUG(("Fdelete: error %ld", r));
+/* check for write permission on directory, sorry, can't use dir_access()
+ * here cause we may also need other bits of the XATTR structure
+ */
+	if ((r = (dir.fs->getxattr)(&dir, &dxattr))) {
+		DEBUG(("Fdelete(%s): can't get directory attributes", name));
+		release_cookie(&dir);
 		return r;
 	}
 
-/* check for write permission on directory */
-	r = dir_access(&dir, S_IWOTH);
-	if (r) {
-		DEBUG(("Fdelete(%s): write access to directory denied",name));
-	} else {
-/* BUG: we should check here for a read-only file */
-		r = (*dir.fs->remove)(&dir,temp1);
+	if (((dxattr.mode & S_IFMT) != S_IFDIR) || denyaccess(&dxattr, S_IWOTH)) {
+		DEBUG(("Fdelete(%s): write access to directory denied", name));
+		release_cookie(&dir);
+		return EACCDN;
+	}
+
+/* if sticky bit set and directory isn't ours, we need some more checks */
+	if ((dxattr.mode & S_ISVTX) && (curproc->euid != dxattr.uid)) {
+
+		if ((r = relpath2cookie(&dir, temp1, 0, &fc, 0))) {
+			DEBUG(("Fdelete(%s): error %ld, perhaps file not found", name, r));
+			release_cookie(&dir);
+			return r;
+		}
+
+/* check ownership of the file */
+		if ((r = (fc.fs->getxattr)(&fc, &fxattr))) {
+			DEBUG(("Fdelete(%s): can't get file attributes", name));
+			release_cookie(&fc);
+			release_cookie(&dir);
+			return r;
+		}
+
+		if (curproc->euid != fxattr.uid) {
+			DEBUG(("Fdelete(%s): write access to file denied", name));
+			release_cookie(&fc);
+			release_cookie(&dir);
+			return EACCDN;
+		}
+
+		release_cookie(&fc);
 	}
+
+/* actually delete the file */
+	if ((r = (*dir.fs->remove)(&dir,temp1)))
+		DEBUG(("Fdelete(%s): error %ld", name, r));
+
 	release_cookie(&dir);
+
 	return r;
 }
 
 long ARGS_ON_STACK
 f_rename(junk, old, new)