Whamcloud - gitweb
b=24226 SUID/SGID related processing
authornasf <yong.fan@whamcloud.com>
Tue, 1 Mar 2011 09:17:29 +0000 (17:17 +0800)
committerOleg Drokin <green@whamcloud.com>
Sat, 19 Mar 2011 04:00:36 +0000 (21:00 -0700)
1) remove SUID/SGID when writes/truncates file.
2) keep SUID/SGID for normal chmod without file data changed.

Issue: LU-65
Change-Id: I664f16c9bace1b0c011abcc7e2d103432886350e
Signed-off-by: nasf <yong.fan@whamcloud.com>
Reviewed-on: http://review.whamcloud.com/238
Tested-by: Hudson
Reviewed-by: Bobi Jam <bobijam@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/include/lu_object.h
lustre/llite/llite_lib.c
lustre/mdd/mdd_object.c
lustre/mdt/mdt_lib.c
lustre/tests/sanity.sh

index 10df803..2b9424f 100644 (file)
@@ -445,6 +445,8 @@ enum la_valid {
         LA_NLINK  = 1 << 10,
         LA_RDEV   = 1 << 11,
         LA_BLKSIZE = 1 << 12,
         LA_NLINK  = 1 << 10,
         LA_RDEV   = 1 << 11,
         LA_BLKSIZE = 1 << 12,
+        LA_KILL_SUID = 1 << 13,
+        LA_KILL_SGID = 1 << 14,
 };
 
 /**
 };
 
 /**
index 03fa724..69b7e69 100644 (file)
@@ -1318,16 +1318,25 @@ out:
 
 int ll_setattr(struct dentry *de, struct iattr *attr)
 {
 
 int ll_setattr(struct dentry *de, struct iattr *attr)
 {
+        int mode = de->d_inode->i_mode;
+
         if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) ==
         if ((attr->ia_valid & (ATTR_CTIME|ATTR_SIZE|ATTR_MODE)) ==
-            (ATTR_CTIME|ATTR_SIZE|ATTR_MODE))
+                              (ATTR_CTIME|ATTR_SIZE|ATTR_MODE))
                 attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
 
                 attr->ia_valid |= MDS_OPEN_OWNEROVERRIDE;
 
-        if ((de->d_inode->i_mode & S_ISUID) &&
+        if (((attr->ia_valid & (ATTR_MODE|ATTR_FORCE|ATTR_SIZE)) ==
+                               (ATTR_SIZE|ATTR_MODE)) &&
+            (((mode & S_ISUID) && !(attr->ia_mode & S_ISUID)) ||
+             (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) &&
+              !(attr->ia_mode & S_ISGID))))
+                attr->ia_valid |= ATTR_FORCE;
+
+        if ((mode & S_ISUID) &&
             !(attr->ia_mode & S_ISUID) &&
             !(attr->ia_valid & ATTR_KILL_SUID))
                 attr->ia_valid |= ATTR_KILL_SUID;
 
             !(attr->ia_mode & S_ISUID) &&
             !(attr->ia_valid & ATTR_KILL_SUID))
                 attr->ia_valid |= ATTR_KILL_SUID;
 
-        if (((de->d_inode->i_mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) &&
+        if (((mode & (S_ISGID|S_IXGRP)) == (S_ISGID|S_IXGRP)) &&
             !(attr->ia_mode & S_ISGID) &&
             !(attr->ia_valid & ATTR_KILL_SGID))
                 attr->ia_valid |= ATTR_KILL_SGID;
             !(attr->ia_mode & S_ISGID) &&
             !(attr->ia_valid & ATTR_KILL_SGID))
                 attr->ia_valid |= ATTR_KILL_SGID;
index 0b12f77..17089c7 100644 (file)
@@ -1084,12 +1084,30 @@ static int mdd_fix_attr(const struct lu_env *env, struct mdd_object *obj,
                 }
         }
 
                 }
         }
 
+        if (la->la_valid & LA_KILL_SUID) {
+                la->la_valid &= ~LA_KILL_SUID;
+                if ((tmp_la->la_mode & S_ISUID) &&
+                    !(la->la_valid & LA_MODE)) {
+                        la->la_mode = tmp_la->la_mode;
+                        la->la_valid |= LA_MODE;
+                }
+                la->la_mode &= ~S_ISUID;
+        }
+
+        if (la->la_valid & LA_KILL_SGID) {
+                la->la_valid &= ~LA_KILL_SGID;
+                if (((tmp_la->la_mode & (S_ISGID | S_IXGRP)) ==
+                                        (S_ISGID | S_IXGRP)) &&
+                    !(la->la_valid & LA_MODE)) {
+                        la->la_mode = tmp_la->la_mode;
+                        la->la_valid |= LA_MODE;
+                }
+                la->la_mode &= ~S_ISGID;
+        }
+
         /* Make sure a caller can chmod. */
         if (la->la_valid & LA_MODE) {
         /* Make sure a caller can chmod. */
         if (la->la_valid & LA_MODE) {
-                /* Bypass la_vaild == LA_MODE,
-                 * this is for changing file with SUID or SGID. */
-                if ((la->la_valid & ~LA_MODE) &&
-                    !(ma->ma_attr_flags & MDS_PERM_BYPASS) &&
+                if (!(ma->ma_attr_flags & MDS_PERM_BYPASS) &&
                     (uc->mu_fsuid != tmp_la->la_uid) &&
                     !mdd_capable(uc, CFS_CAP_FOWNER))
                         RETURN(-EPERM);
                     (uc->mu_fsuid != tmp_la->la_uid) &&
                     !mdd_capable(uc, CFS_CAP_FOWNER))
                         RETURN(-EPERM);
index 2a3b4a0..9e64d59 100644 (file)
@@ -742,10 +742,16 @@ static __u64 mdt_attr_valid_xlate(__u64 in, struct mdt_reint_record *rr,
         if (in & ATTR_ATTR_FLAG)
                 out |= LA_FLAGS;
 
         if (in & ATTR_ATTR_FLAG)
                 out |= LA_FLAGS;
 
+        if (in & ATTR_KILL_SUID)
+                out |= LA_KILL_SUID;
+
+        if (in & ATTR_KILL_SGID)
+                out |= LA_KILL_SGID;
+
         if (in & MDS_OPEN_OWNEROVERRIDE)
                 ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE;
 
         if (in & MDS_OPEN_OWNEROVERRIDE)
                 ma->ma_attr_flags |= MDS_OPEN_OWNEROVERRIDE;
 
-        if (in & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+        if (in & ATTR_FORCE)
                 ma->ma_attr_flags |= MDS_PERM_BYPASS;
 
         /*XXX need ATTR_RAW?*/
                 ma->ma_attr_flags |= MDS_PERM_BYPASS;
 
         /*XXX need ATTR_RAW?*/
index 8c80eac..17b9c9b 100644 (file)
@@ -3961,7 +3961,7 @@ test_71() {
 }
 run_test 71 "Running dbench on lustre (don't segment fault) ===="
 
 }
 run_test 71 "Running dbench on lustre (don't segment fault) ===="
 
-test_72() { # bug 5695 - Test that on 2.6 remove_suid works properly
+test_72a() { # bug 5695 - Test that on 2.6 remove_suid works properly
        check_kernel_version 43 || return 0
        [ "$RUNAS_ID" = "$UID" ] && skip_env "RUNAS_ID = UID = $UID -- skipping" && return
 
        check_kernel_version 43 || return 0
        [ "$RUNAS_ID" = "$UID" ] && skip_env "RUNAS_ID = UID = $UID -- skipping" && return
 
@@ -3984,7 +3984,35 @@ test_72() { # bug 5695 - Test that on 2.6 remove_suid works properly
        true
        rm -f $DIR/f72
 }
        true
        rm -f $DIR/f72
 }
-run_test 72 "Test that remove suid works properly (bug5695) ===="
+run_test 72a "Test that remove suid works properly (bug5695) ===="
+
+test_72b() { # bug 24226 -- keep mode setting when size is not changing
+       local perm
+
+       [ "$RUNAS_ID" = "$UID" ] && \
+               skip_env "RUNAS_ID = UID = $UID -- skipping" && return
+       [ "$RUNAS_ID" -eq 0 ] && \
+               skip_env "RUNAS_ID = 0 -- skipping" && return
+
+       # Check that testing environment is properly set up. Skip if not
+       FAIL_ON_ERROR=false check_runas_id_ret $RUNAS_ID $RUNAS_ID $RUNAS || {
+               skip_env "User $RUNAS_ID does not exist - skipping"
+               return 0
+       }
+       touch $DIR/${tfile}-f{g,u}
+       mkdir $DIR/${tfile}-d{g,u}
+       chmod 770 $DIR/${tfile}-{f,d}{g,u}
+       chmod g+s $DIR/${tfile}-{f,d}g
+       chmod u+s $DIR/${tfile}-{f,d}u
+       for perm in 777 2777 4777; do
+               $RUNAS chmod $perm $DIR/${tfile}-fg && error "S/gid file allowed improper chmod to $perm"
+               $RUNAS chmod $perm $DIR/${tfile}-fu && error "S/uid file allowed improper chmod to $perm"
+               $RUNAS chmod $perm $DIR/${tfile}-dg && error "S/gid dir allowed improper chmod to $perm"
+               $RUNAS chmod $perm $DIR/${tfile}-du && error "S/uid dir allowed improper chmod to $perm"
+       done
+       true
+}
+run_test 72b "Test that we keep mode setting if without file data changed (bug 24226)"
 
 # bug 3462 - multiple simultaneous MDC requests
 test_73() {
 
 # bug 3462 - multiple simultaneous MDC requests
 test_73() {