From b8f4a96b5ebd5cd35747b0a061277d02d46e7a4c Mon Sep 17 00:00:00 2001 From: Josh Samuelson Date: Mon, 8 Jan 2024 13:03:52 -0600 Subject: [PATCH] LU-17400 uapi: Fix incorrect snamelen return value The sname char array is limited by the struct changelog_rec.cr_namelen value and has no '\0' character allocated to it, so strlen() will overrun the char array till it finds the next '\0' char. This issue can be seen on the client side when "lfs changelog" is run and 08RENME record types are present. Pointer arithmetic was used between sname and name to avoid the GCC 11 warnings mentioned in 6331eadbd6. Added Andreas's safety/range check code to changelog_rec_sname. Fixes: 6331eadbd6 ("LU-15420 uapi: avoid gcc-11 -Werror=stringop-overread") Signed-off-by: Josh Samuelson Change-Id: Ie0817dfdd1d02e06b9399e66f1affaadb9e156c4 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53624 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Timothy Day Reviewed-by: Arshad Hussain Reviewed-by: James Simmons Reviewed-by: xinliang Reviewed-by: Oleg Drokin --- lustre/include/uapi/linux/lustre/lustre_user.h | 6 +++-- lustre/tests/sanity.sh | 36 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index 6b1f909..2f06da2 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -2091,15 +2091,17 @@ static inline char *changelog_rec_name(const struct changelog_rec *rec) static inline char *changelog_rec_sname(const struct changelog_rec *rec) { char *str = changelog_rec_name(rec); + char *end = str + NAME_MAX; /* NB: NAME_MAX use in CR_MAXSIZE */ - while (*str != '\0') + while (*str != '\0' && str <= end) str++; return str + 1; } static inline __kernel_size_t changelog_rec_snamelen(const struct changelog_rec *rec) { - return strlen(changelog_rec_sname(rec)); + return rec->cr_namelen - + (changelog_rec_sname(rec) - changelog_rec_name(rec)); } /** diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 153a951..d261fbb 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -18738,6 +18738,42 @@ test_160t() { } run_test 160t "changelog garbage collect on lack of space" +test_160u() { # LU-17400 + [ $PARALLEL == "yes" ] && skip "skip parallel run" + remote_mds_nodsh && skip "remote MDS with nodsh" + [ $MDS1_VERSION -ge $(version_code 2.2.0) ] || + skip "Need MDS version at least 2.2.0" + + cd $DIR || error "cd $DIR failed" + + # ensure changelog has a clean view if tests are run multiple times + [ -d rename ] && rm -rf rename + + changelog_register || error "changelog_register failed" + local cl_user="${CL_USERS[$SINGLEMDS]%% *}" + + changelog_users $SINGLEMDS | grep -q $cl_user || + error "User '$cl_user' not found in changelog_users" + + local longname1=$(str_repeat a 255) + + echo "creating simple directory tree" + mkdir -p rename/a || error "create of simple directory tree failed" + echo "creating rename/hw file" + echo "hello world" > rename/hw || error "create of rename/hw failed" + echo "creating very long named file" + touch rename/$longname1 || error "create of 'rename/$longname1' failed" + echo "move rename/hw to rename/a/a.hw" + mv rename/hw rename/a/a.hw || error "mv failed" + + RENME=($(changelog_dump | grep "RENME")) + #declare -p RENME # for debugging captured value with indexes + + [[ "${RENME[11]}" == "a.hw" && "${RENME[14]}" == "hw" ]] || + error "changelog rename record type name/sname error" +} +run_test 160u "changelog rename record type name and sname strings are correct" + test_161a() { [ $PARALLEL == "yes" ] && skip "skip parallel run" -- 1.8.3.1