Whamcloud - gitweb
LU-13168 tests: verify truncated xattr is handled 34/38434/5
authorAndreas Dilger <adilger@whamcloud.com>
Thu, 30 Apr 2020 22:20:01 +0000 (16:20 -0600)
committerOleg Drokin <green@whamcloud.com>
Thu, 14 May 2020 05:39:30 +0000 (05:39 +0000)
Verify that a truncated trusted.lov xattr is handled properly,
for both plain and PFL layouts.

Add a test case that verifies this is fixed for both layout types.

Fixes: f2d06d3c76 ("LU-12911 llite: Don't access lov_md fields before size check")
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: I11d420c7fdc2362f64689a545b95c76e893ebbe5
Reviewed-on: https://review.whamcloud.com/38434
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Sebastien Buisson <sbuisson@ddn.com>
Reviewed-by: Emoly Liu <emoly@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/llite/xattr.c
lustre/tests/sanity.sh

index 829584d..c1535bd 100644 (file)
@@ -213,7 +213,7 @@ static int get_hsm_state(struct inode *inode, u32 *hus_states)
        return rc;
 }
 
-static int ll_adjust_lum(struct inode *inode, struct lov_user_md *lump)
+static int ll_adjust_lum(struct inode *inode, struct lov_user_md *lump, size_t size)
 {
        struct lov_comp_md_v1 *comp_v1 = (struct lov_comp_md_v1 *)lump;
        struct lov_user_md *v1 = lump;
@@ -228,7 +228,12 @@ static int ll_adjust_lum(struct inode *inode, struct lov_user_md *lump)
                return 0;
 
        if (lump->lmm_magic == LOV_USER_MAGIC_COMP_V1) {
+               if (size < sizeof(*comp_v1))
+                       return -ERANGE;
+
                entry_count = comp_v1->lcm_entry_count;
+               if (size < offsetof(typeof(*comp_v1), lcm_entries[entry_count]))
+                       return -ERANGE;
                is_composite = true;
        }
 
@@ -236,6 +241,10 @@ static int ll_adjust_lum(struct inode *inode, struct lov_user_md *lump)
                if (lump->lmm_magic == LOV_USER_MAGIC_COMP_V1) {
                        void *ptr = comp_v1;
 
+                       if (comp_v1->lcm_entries[i].lcme_offset + sizeof(*v1) >
+                           size)
+                               return -ERANGE;
+
                        ptr += comp_v1->lcm_entries[i].lcme_offset;
                        v1 = (struct lov_user_md *)ptr;
                }
@@ -289,7 +298,7 @@ static int ll_setstripe_ea(struct dentry *dentry, struct lov_user_md *lump,
                 */
                return -ERANGE;
        }
-       rc = ll_adjust_lum(inode, lump);
+       rc = ll_adjust_lum(inode, lump, size);
        if (rc)
                return rc;
 
index c44f731..fb540aa 100755 (executable)
@@ -9525,36 +9525,54 @@ test_102a() {
 }
 run_test 102a "user xattr test =================================="
 
+check_102b_layout() {
+       local layout="$*"
+       local testfile=$DIR/$tfile
+
+       echo "test layout '$layout'"
+       $LFS setstripe $layout $testfile || error "setstripe failed"
+       $LFS getstripe -y $testfile
+
+       echo "get/set/list trusted.lov xattr ..." # b=10930
+       local value=$(getfattr -n trusted.lov -e hex $testfile | grep trusted)
+       [[ "$value" =~ "trusted.lov" ]] ||
+               error "can't get trusted.lov from $testfile"
+       local stripe_count_orig=$($LFS getstripe -c $testfile) ||
+               error "getstripe failed"
+
+       $MCREATE $testfile.2 || error "mcreate $testfile.2 failed"
+
+       value=$(cut -d= -f2 <<<$value)
+       # LU-13168: truncated xattr should fail if short lov_user_md header
+       [ $CLIENT_VERSION -lt $(version_code 2.13.53) ] &&
+               lens="${#value}" || lens="$(seq 4 2 ${#value})"
+       for len in $lens; do
+               echo "setfattr $len $testfile.2"
+               setfattr -n trusted.lov -v ${value:0:$len} $testfile.2 &&
+                       [ $len -lt 66 ] && error "short xattr len=$len worked"
+       done
+       local stripe_size=$($LFS getstripe -S $testfile.2)
+       local stripe_count=$($LFS getstripe -c $testfile.2)
+       [[ $stripe_size -eq 65536 ]] ||
+               error "stripe size $stripe_size != 65536"
+       [[ $stripe_count -eq $stripe_count_orig ]] ||
+               error "stripe count $stripe_count != $stripe_count_orig"
+       rm $testfile $testfile.2
+}
+
 test_102b() {
        [ -z "$(which setfattr 2>/dev/null)" ] &&
                skip_env "could not find setfattr"
        [[ $OSTCOUNT -lt 2 ]] && skip_env "needs >= 2 OSTs"
 
-       # b10930: get/set/list trusted.lov xattr
-       echo "get/set/list trusted.lov xattr ..."
-       local testfile=$DIR/$tfile
-       $LFS setstripe -S 65536 -i 1 -c $OSTCOUNT $testfile ||
-               error "setstripe failed"
-       local STRIPECOUNT=$($LFS getstripe -c $testfile) ||
-               error "getstripe failed"
-       getfattr -d -m "^trusted" $testfile 2>/dev/null | grep "trusted.lov" ||
-               error "can't get trusted.lov from $testfile"
+       # check plain layout
+       check_102b_layout -S 65536 -i 1 -c $OSTCOUNT
 
-       local testfile2=${testfile}2
-       local value=$(getfattr -n trusted.lov $testfile 2>/dev/null |
-                       grep "trusted.lov" | sed -e 's/[^=]\+=//')
+       # and also check composite layout
+       check_102b_layout -E 1M -S 65536 -i 1 -c $OSTCOUNT -Eeof -S4M
 
-       $MCREATE $testfile2
-       setfattr -n trusted.lov -v $value $testfile2
-       local stripe_size=$($LFS getstripe -S $testfile2)
-       local stripe_count=$($LFS getstripe -c $testfile2)
-       [[ $stripe_size -eq 65536 ]] ||
-               error "stripe size $stripe_size != 65536"
-       [[ $stripe_count -eq $STRIPECOUNT ]] ||
-               error "stripe count $stripe_count != $STRIPECOUNT"
-       rm -f $DIR/$tfile
 }
-run_test 102b "getfattr/setfattr for trusted.lov EAs ============"
+run_test 102b "getfattr/setfattr for trusted.lov EAs"
 
 test_102c() {
        [ -z "$(which setfattr 2>/dev/null)" ] &&