From 8078330f6bfbf4131389e16577568a259f65adf2 Mon Sep 17 00:00:00 2001 From: Jian Yu Date: Tue, 23 Feb 2021 09:26:37 -0800 Subject: [PATCH] LU-14385 utils: add range check to strtoul() in lfs.c Most of the strtoul() functions called in lfs.c did not check the range of the return value. This patch fixes those issues. Lustre-change: https://review.whamcloud.com/41726 Lustre-commit: c8b1f4d886b71e1439eb8d521f282dbdf366ec26 Test-Parameters: trivial Change-Id: If1eb64750507b5fa4e22abe710e475e2f0032b4d Signed-off-by: Jian Yu Reviewed-by: John L. Hammond Reviewed-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/46264 Tested-by: jenkins Tested-by: Maloo --- lustre/utils/lfs.c | 138 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 28 deletions(-) diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index ca44fca..d0af817 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -3568,15 +3568,22 @@ static int lfs_setstripe_internal(int argc, char **argv, case LFS_COMP_NO_VERIFY_OPT: mirror_flags |= MF_NO_VERIFY; break; - case LFS_MIRROR_ID_OPT: - mirror_id = strtoul(optarg, &end, 0); - if (*end != '\0' || mirror_id == 0) { + case LFS_MIRROR_ID_OPT: { + unsigned long int id; + + errno = 0; + id = strtoul(optarg, &end, 0); + if (errno != 0 || *end != '\0' || id == 0 || + id > UINT16_MAX) { fprintf(stderr, "%s %s: invalid mirror ID '%s'\n", progname, argv[0], optarg); goto usage_error; } + + mirror_id = (__u16)id; break; + } case LFS_LAYOUT_FLAGS_OPT: { uint32_t neg_flags; @@ -3642,6 +3649,11 @@ static int lfs_setstripe_internal(int argc, char **argv, optarg); return CMD_HELP; } + } else if (type >= UINT32_MAX) { + fprintf(stderr, + "%s %s: invalid foreign type '%s'\n", + progname, argv[0], optarg); + return CMD_HELP; } } foreign_mode = true; @@ -3682,8 +3694,11 @@ static int lfs_setstripe_internal(int argc, char **argv, lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING; /* fall through */ case 'c': + errno = 0; lsa.lsa_stripe_count = strtoul(optarg, &end, 0); - if (*end != '\0') { + if (errno != 0 || *end != '\0'|| + lsa.lsa_stripe_count < -1 || + lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) { fprintf(stderr, "%s %s: invalid stripe count '%s'\n", progname, argv[0], optarg); @@ -3871,8 +3886,11 @@ static int lfs_setstripe_internal(int argc, char **argv, } mirror_count = 1; if (optarg) { + errno = 0; mirror_count = strtoul(optarg, &end, 0); - if (*end != '\0' || mirror_count == 0) { + if (errno != 0 || *end != '\0' || + mirror_count == 0 || + mirror_count > LUSTRE_MIRROR_COUNT_MAX) { fprintf(stderr, "error: %s: bad mirror count: %s\n", progname, optarg); @@ -4825,8 +4843,10 @@ static int lfs_find(int argc, char **argv) optarg++; } + errno = 0; param.fp_comp_count = strtoul(optarg, &endptr, 0); - if (*endptr != '\0') { + if (errno != 0 || *endptr != '\0' || + param.fp_comp_count > UINT32_MAX) { fprintf(stderr, "error: bad component count '%s'\n", optarg); @@ -4899,8 +4919,10 @@ static int lfs_find(int argc, char **argv) optarg++; } + errno = 0; param.fp_stripe_count = strtoul(optarg, &endptr, 0); - if (*endptr != '\0') { + if (errno != 0 || *endptr != '\0' || + param.fp_stripe_count > LOV_MAX_STRIPE_COUNT) { fprintf(stderr, "error: bad stripe_count '%s'\n", optarg); @@ -4960,6 +4982,11 @@ static int lfs_find(int argc, char **argv) optarg); return CMD_HELP; } + } else if (type >= UINT32_MAX) { + fprintf(stderr, + "%s %s: invalid foreign type '%s'\n", + progname, argv[0], optarg); + return CMD_HELP; } } param.fp_foreign_type = type; @@ -5178,8 +5205,10 @@ static int lfs_find(int argc, char **argv) optarg++; } + errno = 0; param.fp_mirror_count = strtoul(optarg, &endptr, 0); - if (*endptr != '\0') { + if (errno != 0 || *endptr != '\0' || + param.fp_mirror_count > LUSTRE_MIRROR_COUNT_MAX) { fprintf(stderr, "error: bad mirror count '%s'\n", optarg); @@ -5391,8 +5420,10 @@ err_free: optarg++; } + errno = 0; param.fp_mdt_count = strtoul(optarg, &endptr, 0); - if (*endptr != '\0') { + if (errno != 0 || *endptr != '\0' || + param.fp_mdt_count >= UINT32_MAX) { fprintf(stderr, "error: bad mdt_count '%s'\n", optarg); ret = -1; @@ -5609,7 +5640,9 @@ static int lfs_getstripe_internal(int argc, char **argv, param->fp_max_depth = 0; } break; - case LFS_MIRROR_INDEX_OPT: + case LFS_MIRROR_INDEX_OPT: { + unsigned long int mirror_index; + if (optarg[0] == '+') { param->fp_mirror_index_sign = -1; optarg++; @@ -5618,14 +5651,19 @@ static int lfs_getstripe_internal(int argc, char **argv, optarg++; } - param->fp_mirror_index = strtoul(optarg, &end, 0); - if (*end != '\0' || (param->fp_mirror_index == 0 && + errno = 0; + mirror_index = strtoul(optarg, &end, 0); + if (errno != 0 || *end != '\0' || + mirror_index > UINT16_MAX || (mirror_index == 0 && param->fp_mirror_index_sign == 0 && neg_opt == 0)) { fprintf(stderr, "%s %s: invalid mirror index '%s'\n", progname, argv[0], optarg); return CMD_HELP; } + + param->fp_mirror_index = (__u16)mirror_index; + if (param->fp_mirror_id != 0) { fprintf(stderr, "%s %s: can't specify both mirror index and mirror ID\n", @@ -5635,7 +5673,10 @@ static int lfs_getstripe_internal(int argc, char **argv, param->fp_check_mirror_index = 1; param->fp_exclude_mirror_index = !!neg_opt; break; - case LFS_MIRROR_ID_OPT: + } + case LFS_MIRROR_ID_OPT: { + unsigned long int mirror_id; + if (optarg[0] == '+') { param->fp_mirror_id_sign = -1; optarg++; @@ -5644,14 +5685,19 @@ static int lfs_getstripe_internal(int argc, char **argv, optarg++; } - param->fp_mirror_id = strtoul(optarg, &end, 0); - if (*end != '\0' || (param->fp_mirror_id == 0 && + errno = 0; + mirror_id = strtoul(optarg, &end, 0); + if (errno != 0 || *end != '\0' || + mirror_id > UINT16_MAX || (mirror_id == 0 && param->fp_mirror_id_sign == 0 && neg_opt == 0)) { fprintf(stderr, "%s %s: invalid mirror ID '%s'\n", progname, argv[0], optarg); return CMD_HELP; } + + param->fp_mirror_id = (__u16)mirror_id; + if (param->fp_mirror_index != 0) { fprintf(stderr, "%s %s: can't specify both mirror index and mirror ID\n", @@ -5661,6 +5707,7 @@ static int lfs_getstripe_internal(int argc, char **argv, param->fp_check_mirror_id = 1; param->fp_exclude_mirror_id = !!neg_opt; break; + } case 'd': param->fp_max_depth = 0; break; @@ -6379,8 +6426,11 @@ static int lfs_setdirstripe(int argc, char **argv) break; case 'c': case 'T': + errno = 0; lsa.lsa_stripe_count = strtoul(optarg, &end, 0); - if (*end != '\0') { + if (errno != 0 || *end != '\0' || + lsa.lsa_stripe_count < -1 || + lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) { fprintf(stderr, "%s %s: invalid stripe count '%s'\n", progname, argv[0], optarg); @@ -6408,6 +6458,11 @@ static int lfs_setdirstripe(int argc, char **argv) optarg); return CMD_HELP; } + } else if (type >= UINT32_MAX) { + fprintf(stderr, + "%s %s: invalid foreign type '%s'\n", + progname, argv[0], optarg); + return CMD_HELP; } } foreign_mode = true; @@ -6772,8 +6827,10 @@ static int lfs_mv(int argc, char **argv) "warning: '-M' deprecated, use '--mdt-index' or '-m' instead\n"); #endif case 'm': + errno = 0; lmu.lum_stripe_offset = strtoul(optarg, &end, 0); - if (*end != '\0') { + if (errno != 0 || *end != '\0' || + lmu.lum_stripe_offset >= UINT32_MAX) { fprintf(stderr, "%s mv: bad MDT index '%s'\n", progname, optarg); return CMD_HELP; @@ -10386,15 +10443,22 @@ static inline int lfs_mirror_read(int argc, char **argv) char *end; switch (c) { - case 'N': - mirror_id = strtoul(optarg, &end, 0); - if (*end != '\0' || mirror_id == 0) { + case 'N': { + unsigned long int id; + + errno = 0; + id = strtoul(optarg, &end, 0); + if (errno != 0 || *end != '\0' || id == 0 || + id > UINT16_MAX) { fprintf(stderr, "%s %s: invalid mirror ID '%s'\n", progname, argv[0], optarg); return rc; } + + mirror_id = (__u16)id; break; + } case 'o': outfile = optarg; break; @@ -10542,15 +10606,22 @@ static inline int lfs_mirror_write(int argc, char **argv) char *end; switch (c) { - case 'N': - mirror_id = strtoul(optarg, &end, 0); - if (*end != '\0' || mirror_id == 0) { + case 'N': { + unsigned long int id; + + errno = 0; + id = strtoul(optarg, &end, 0); + if (errno != 0 || *end != '\0' || id == 0 || + id > UINT16_MAX) { fprintf(stderr, "%s %s: invalid mirror ID '%s'\n", progname, argv[0], optarg); return rc; } + + mirror_id = (__u16)id; break; + } case 'i': inputfile = optarg; break; @@ -10766,15 +10837,22 @@ static inline int lfs_mirror_copy(int argc, char **argv) char *end; switch (c) { - case 'i': - read_mirror_id = strtoul(optarg, &end, 0); - if (*end != '\0' || read_mirror_id == 0) { + case 'i': { + unsigned long int id; + + errno = 0; + id = strtoul(optarg, &end, 0); + if (errno != 0 || *end != '\0' || id == 0 || + id > UINT16_MAX) { fprintf(stderr, "%s %s: invalid read mirror ID '%s'\n", progname, argv[0], optarg); return rc; } + + read_mirror_id = (__u16)id; break; + } case 'o': if (!strcmp(optarg, "-1")) { /* specify all other mirrors */ @@ -11747,8 +11825,10 @@ static int lfs_pcc_attach(int argc, char **argv) long_opts, NULL)) != -1) { switch (c) { case 'i': + errno = 0; attach_id = strtoul(optarg, &end, 0); - if (*end != '\0' || attach_id == 0) { + if (errno != 0 || *end != '\0' || + attach_id == 0 || attach_id > UINT32_MAX) { fprintf(stderr, "error: %s: bad attach ID '%s'\n", argv[0], optarg); @@ -11822,8 +11902,10 @@ static int lfs_pcc_attach_fid(int argc, char **argv) long_opts, NULL)) != -1) { switch (c) { case 'i': + errno = 0; attach_id = strtoul(optarg, &end, 0); - if (*end != '\0') { + if (errno != 0 || *end != '\0' || + attach_id > UINT32_MAX) { fprintf(stderr, "error: %s: bad attach ID '%s'\n", argv[0], optarg); -- 1.8.3.1