This patch against 2.2.2 should allow root to rm autofs symlinks.
Please test it and let me know if it causes problems; since this is an
enhancement rather than a bugfix I need to make a pretty strong case
to let it past Linus at this time.

It also changes some of the error codes to be more posixly correct.
It turns out "permission denied" is EACCES, not EPERM (operation not
permitted), which is what I had used in most places.

        -hpa


diff -ur stock/linux-2.2.2/fs/autofs/root.c linux-2.2.2/fs/autofs/root.c
--- stock/linux-2.2.2/fs/autofs/root.c  Wed Feb 24 02:07:11 1999
+++ linux-2.2.2/fs/autofs/root.c        Wed Feb 24 01:54:35 1999
@@ -281,7 +281,7 @@
        autofs_say(dentry->d_name.name,dentry->d_name.len);
 
        if ( !autofs_oz_mode(sbi) )
-               return -EPERM;
+               return -EACCES;
 
        if ( dentry->d_name.len > NAME_MAX )
                return -ENAMETOOLONG;
@@ -349,17 +349,20 @@
        struct autofs_dir_ent *ent;
        unsigned int n;
 
-       if ( !autofs_oz_mode(sbi) )
-               return -EPERM;
+       /* This allows root to remove symlinks */
+       if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+               return -EACCES;
 
        ent = autofs_hash_lookup(dh, &dentry->d_name);
        if ( !ent )
                return -ENOENT;
 
        n = ent->ino - AUTOFS_FIRST_SYMLINK;
-       if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap) )
-               return -EINVAL; /* Not a symlink inode, can't unlink */
-       
+       if ( n >= AUTOFS_MAX_SYMLINKS )
+               return -EISDIR; /* It's a directory, dummy */
+       if ( !test_bit(n,sbi->symlink_bitmap) )
+               return -EINVAL; /* Nonexistent symlink?  Shouldn't happen */
+       
        dentry->d_time = (unsigned long)(struct autofs_dirhash *)NULL;
        autofs_hash_delete(ent);
        clear_bit(n,sbi->symlink_bitmap);
@@ -376,7 +379,7 @@
        struct autofs_dir_ent *ent;
 
        if ( !autofs_oz_mode(sbi) )
-               return -EPERM;
+               return -EACCES;
 
        ent = autofs_hash_lookup(dh, &dentry->d_name);
        if ( !ent )
@@ -405,7 +408,7 @@
        ino_t ino;
 
        if ( !autofs_oz_mode(sbi) )
-               return -EPERM;
+               return -EACCES;
 
        if ( dentry->d_name.len > NAME_MAX )
                return -ENAMETOOLONG;

Reply via email to