Hi,

On Thu, Sep 22, 2005 at 10:26:09AM -0700, Stephen Samuel (sic) wrote:
> as Knoppix, I can (for example) do:
> 
> echo *.debug /tmp/debug > /etc/syslog.conf
> 
> This isgnores the file permissions on syslog.conf.  Once the first change
> is made (and the file is now being fetched from the ramdrive), further
> writes fail unless I really do have proper permission.
> 
> This only seems to happen for files that exist and are sourced from
> the CD.

Right. In fact, for files on a readonly branch, the real file
permissions seem to never get checked. Instead, and the always returned
EROFS from permission() just gets ignored if the file is not on the
toplevel read-write branch, leading to the fact that anybody can write a
file before it is copied up and permissions are checked correctly from
thereon.

My solution is to reuse permission() without the filesystem RO check.
Also, I removed the part that ignores a (possibly corect in some cases)
EROFS returned from file permission checking (whenever that may happen).

I can't promise that the attached patch works correctly for all cases,
but at least now the testcases known to me behave correctly. Plus, it
seems to have accidentially fixed the
rm -f old_file_i_have_no_permission_to_remove
cat old_file_i_have_no_permission_to_remove
bug/oops.

Can anybody verify this?

With kind regards
-Klaus Knopper
--- unionfs-20050921-1517.orig/inode.c  2005-09-21 21:17:02.000000000 +0200
+++ unionfs-20050921-1517/inode.c       2005-09-22 21:22:42.000000000 +0200
@@ -824,6 +824,43 @@
        print_exit_location();
 }
 
+/* Basically copied from the kernel vfs permission() -KK */
+int inode_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+        int retval, submask;
+
+        if (mask & MAY_WRITE) {
+
+#if 0 /* Needs to be skipped, since we are only interested in the files 
permission, not in the file systems ro status */
+                umode_t mode = inode->i_mode;
+               /*
+                 * Nobody gets write access to a read-only fs.
+                 */
+                if (IS_RDONLY(inode) &&
+                    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+                        return -EROFS;
+#endif
+
+                /*
+                 * Nobody gets write access to an immutable file.
+                 */
+                if (IS_IMMUTABLE(inode))
+                        return -EACCES;
+        }
+
+
+        /* Ordinary permission routines do not understand MAY_APPEND. */
+        submask = mask & ~MAY_APPEND;
+        if (inode->i_op && inode->i_op->permission)
+                retval = inode->i_op->permission(inode, submask, nd);
+        else
+                retval = generic_permission(inode, submask, NULL);
+        if (retval)
+                return retval;
+
+        return security_inode_permission(inode, mask, nd);
+}
+
 static int unionfs_permission(struct inode *inode, int mask,
                              struct nameidata *nd)
 {
@@ -854,11 +891,9 @@
                 */
                if (!S_ISDIR(hidden_inode->i_mode) && (!is_file))
                        continue;
-               err = permission(hidden_inode, mask, nd);
-               /* If the leftmost branch is r/o we can't copyup.
-                * Otherwise we ignore EROFS. */
-               if (IS_COPYUP_ERR(err) && (bindex != 0))
-                       err = 0;
+
+               err = inode_permission(hidden_inode, mask, nd);
+
                /* The permissions are an intersection of the overall directory
                 * permissions, so we fail if one fails. */
                if (err)
_______________________________________________
unionfs mailing list
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs

Reply via email to