From 21d716e6c16424d9deb646456758ebbaa9c70fec Mon Sep 17 00:00:00 2001 From: Dmitry Eremin Date: Tue, 25 Feb 2014 22:34:13 +0400 Subject: [PATCH] LU-4629 libcfs: fix buffer overflow of string buffer Buffer overflow of string buffer due to non null terminated string. Use strlcpy() when it's justifiable. Use sizeof(var) instead of constants. Signed-off-by: Dmitry Eremin Change-Id: Ib8d5493898a292e3c764170d0a0870bee26b23a0 Reviewed-on: http://review.whamcloud.com/9389 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- libcfs/libcfs/autoMakefile.am | 4 +- libcfs/libcfs/debug.c | 10 +- libcfs/libcfs/hash.c | 3 +- libcfs/libcfs/posix/posix-debug.c | 17 ++-- libcfs/libcfs/upcall_cache.c | 4 +- libcfs/libcfs/user-prim.c | 26 ----- libcfs/libcfs/user-string.c | 67 +++++++++++++ libcfs/libcfs/util/parser.c | 44 +++++---- libcfs/libcfs/workitem.c | 2 +- lnet/klnds/socklnd/socklnd.c | 9 +- lnet/lnet/config.c | 109 ++++++++++---------- lnet/selftest/conrpc.c | 4 +- lnet/selftest/console.c | 5 +- lnet/utils/lst.c | 4 +- lnet/utils/lstclient.c | 3 +- lnet/utils/portals.c | 3 +- lustre/fid/fid_store.c | 3 +- lustre/include/lustre/lustre_user.h | 4 +- lustre/include/lustre_disk.h | 3 +- lustre/llite/dir.c | 2 +- lustre/lod/lod_lov.c | 4 +- lustre/lod/lod_object.c | 18 ++-- lustre/lod/lod_pool.c | 3 +- lustre/lov/lov_pool.c | 3 +- lustre/mdt/mdt_coordinator.c | 5 +- lustre/mgs/mgs_llog.c | 9 +- lustre/obdclass/dt_object.c | 7 +- lustre/obdclass/obd_mount.c | 10 +- lustre/ofd/ofd_io.c | 3 +- lustre/osd-zfs/osd_handler.c | 21 ++-- lustre/osd-zfs/osd_oi.c | 6 +- lustre/osp/lwp_dev.c | 4 +- lustre/ptlrpc/gss/gss_pipefs.c | 2 +- lustre/ptlrpc/gss/sec_gss.c | 34 +++---- lustre/ptlrpc/ptlrpcd.c | 2 +- lustre/ptlrpc/sec_config.c | 3 +- lustre/quota/qmt_dev.c | 9 +- lustre/target/tgt_lastrcvd.c | 6 +- lustre/tests/mpi/Makefile.am | 4 +- lustre/utils/Makefile.am | 9 +- lustre/utils/gss/gssd.c | 6 +- lustre/utils/gss/lgss_keyring.c | 4 +- lustre/utils/gss/svcgssd_proc.c | 1 + lustre/utils/l_getidentity.c | 22 +++-- lustre/utils/lfs.c | 21 +++- lustre/utils/lhsmtool_posix.c | 32 +++--- lustre/utils/libiam.c | 2 +- lustre/utils/liblustreapi.c | 191 ++++++++++++++++++++---------------- lustre/utils/liblustreapi_json.c | 12 ++- lustre/utils/ltrack_stats.c | 4 +- lustre/utils/lustre_rsync.c | 99 ++++++++++--------- lustre/utils/mount_utils.c | 2 +- lustre/utils/mount_utils_ldiskfs.c | 9 +- 53 files changed, 510 insertions(+), 383 deletions(-) create mode 100644 libcfs/libcfs/user-string.c diff --git a/libcfs/libcfs/autoMakefile.am b/libcfs/libcfs/autoMakefile.am index 2f6f9ab..82e903e 100644 --- a/libcfs/libcfs/autoMakefile.am +++ b/libcfs/libcfs/autoMakefile.am @@ -47,7 +47,7 @@ libcfs_a_SOURCES= posix/posix-debug.c user-prim.c user-lock.c user-tcpip.c \ prng.c user-bitops.c user-mem.c hash.c kernel_user_comm.c \ workitem.c fail.c libcfs_cpu.c libcfs_mem.c libcfs_lock.c \ posix/rbtree.c user-crypto.c posix/posix-crc32.c \ - posix/posix-adler.c posix/posix-proc.c heap.c + posix/posix-adler.c posix/posix-proc.c heap.c user-string.c if HAVE_PCLMULQDQ if NEED_PCLMULQDQ_CRC32 @@ -99,4 +99,4 @@ MOSTLYCLEANFILES := @MOSTLYCLEANFILES@ linux-*.c linux/*.o darwin/*.o libcfs EXTRA_DIST := $(libcfs-all-objs:%.o=%.c) Info.plist tracefile.h prng.c \ user-lock.c user-tcpip.c user-bitops.c user-prim.c workitem.c \ user-mem.c kernel_user_comm.c fail.c libcfs_cpu.c heap.c \ - libcfs_mem.c libcfs_lock.c linux/linux-tracefile.h + libcfs_mem.c libcfs_lock.c user-string.c linux/linux-tracefile.h diff --git a/libcfs/libcfs/debug.c b/libcfs/libcfs/debug.c index 0691471..4384e7a 100644 --- a/libcfs/libcfs/debug.c +++ b/libcfs/libcfs/debug.c @@ -300,11 +300,11 @@ int libcfs_debug_init(unsigned long bufsize) libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY; } - if (libcfs_debug_file_path != NULL) { - memset(libcfs_debug_file_path_arr, 0, PATH_MAX); - strncpy(libcfs_debug_file_path_arr, - libcfs_debug_file_path, PATH_MAX-1); - } + if (libcfs_debug_file_path != NULL) { + strlcpy(libcfs_debug_file_path_arr, + libcfs_debug_file_path, + sizeof(libcfs_debug_file_path_arr)); + } /* If libcfs_debug_mb is set to an invalid value or uninitialized * then just make the total buffers smp_num_cpus * TCD_MAX_PAGES */ diff --git a/libcfs/libcfs/hash.c b/libcfs/libcfs/hash.c index 0c4faf8..dda925c 100644 --- a/libcfs/libcfs/hash.c +++ b/libcfs/libcfs/hash.c @@ -1056,8 +1056,7 @@ cfs_hash_create(char *name, unsigned cur_bits, unsigned max_bits, if (hs == NULL) RETURN(NULL); - strncpy(hs->hs_name, name, len); - hs->hs_name[len - 1] = '\0'; + strlcpy(hs->hs_name, name, len); hs->hs_flags = flags; atomic_set(&hs->hs_refcount, 1); diff --git a/libcfs/libcfs/posix/posix-debug.c b/libcfs/libcfs/posix/posix-debug.c index 3de41f6..32ccdcc 100644 --- a/libcfs/libcfs/posix/posix-debug.c +++ b/libcfs/libcfs/posix/posix-debug.c @@ -100,16 +100,21 @@ int libcfs_debug_init(unsigned long bufsize) (unsigned int) strtol(debug_subsys, NULL, 0); debug_filename = getenv("LIBLUSTRE_DEBUG_BASE"); - if (debug_filename) - strncpy(libcfs_debug_file_path, debug_filename, - sizeof(libcfs_debug_file_path)); + if (debug_filename) { + strncpy(libcfs_debug_file_path, debug_filename, + sizeof(libcfs_debug_file_path)); + libcfs_debug_file_path[sizeof(libcfs_debug_file_path)-1] = '\0'; + } debug_filename = getenv("LIBLUSTRE_DEBUG_FILE"); - if (debug_filename) - strncpy(debug_file_name,debug_filename,sizeof(debug_file_name)); + if (debug_filename) { + strncpy(debug_file_name, debug_filename, + sizeof(debug_file_name)); + debug_file_name[sizeof(debug_file_name) - 1] = '\0'; + } if (debug_file_name[0] == '\0' && libcfs_debug_file_path[0] != '\0') - snprintf(debug_file_name, sizeof(debug_file_name) - 1, + snprintf(debug_file_name, sizeof(debug_file_name), "%s-%s-"CFS_TIME_T".log", libcfs_debug_file_path, source_nid, time(0)); diff --git a/libcfs/libcfs/upcall_cache.c b/libcfs/libcfs/upcall_cache.c index e481ed7..34bc7df 100644 --- a/libcfs/libcfs/upcall_cache.c +++ b/libcfs/libcfs/upcall_cache.c @@ -441,9 +441,9 @@ struct upcall_cache *upcall_cache_init(const char *name, const char *upcall, rwlock_init(&cache->uc_upcall_rwlock); for (i = 0; i < UC_CACHE_HASH_SIZE; i++) INIT_LIST_HEAD(&cache->uc_hashtable[i]); - strncpy(cache->uc_name, name, sizeof(cache->uc_name) - 1); + strlcpy(cache->uc_name, name, sizeof(cache->uc_name)); /* upcall pathname proc tunable */ - strncpy(cache->uc_upcall, upcall, sizeof(cache->uc_upcall) - 1); + strlcpy(cache->uc_upcall, upcall, sizeof(cache->uc_upcall)); cache->uc_entry_expire = 20 * 60; cache->uc_acquire_expire = 30; cache->uc_ops = ops; diff --git a/libcfs/libcfs/user-prim.c b/libcfs/libcfs/user-prim.c index f616e9d..a912c94 100644 --- a/libcfs/libcfs/user-prim.c +++ b/libcfs/libcfs/user-prim.c @@ -268,32 +268,6 @@ gid_t current_fsgid(void) return getgid(); } -#ifndef HAVE_STRLCPY /* not in glibc for RHEL 5.x, remove when obsolete */ -size_t strlcpy(char *tgt, const char *src, size_t tgt_len) -{ - int src_len = strlen(src); - - strncpy(tgt, src, tgt_len - 1); - tgt[tgt_len - 1] = '\0'; - - return src_len + 1; -} -#endif - -#ifndef HAVE_STRLCAT /* not in glibc for RHEL 5.x, remove when obsolete */ -size_t strlcat(char *tgt, const char *src, size_t size) -{ - size_t tgt_len = strlen(tgt); - - if (size > tgt_len) { - strncat(tgt, src, size - tgt_len - 1); - tgt[size - 1] = '\0'; - } - - return tgt_len + strlen(src); -} -#endif - /* Read the environment variable of current process specified by @key. */ int cfs_get_environ(const char *key, char *value, int *val_len) { diff --git a/libcfs/libcfs/user-string.c b/libcfs/libcfs/user-string.c new file mode 100644 index 0000000..6b725b5 --- /dev/null +++ b/libcfs/libcfs/user-string.c @@ -0,0 +1,67 @@ +/* + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.gnu.org/licenses/gpl-2.0.html + * + * GPL HEADER END + */ +/* + * Copyright (c) 2014 Intel Corporation. + */ +#ifndef __KERNEL__ + +#include + +/* + * According manual of strlcpy() and strlcat() the functions should return + * the total length of the string they tried to create. For strlcpy() that + * means the length of src. For strlcat() that means the initial length of + * dst plus the length of src. So, the function strnlen() cannot be used + * otherwise the return value will be wrong. + */ +#ifndef HAVE_STRLCPY /* not in glibc for RHEL 5.x, remove when obsolete */ +size_t strlcpy(char *dst, const char *src, size_t size) +{ + size_t ret = strlen(src); + + if (size) { + size_t len = (ret >= size) ? size - 1 : ret; + memcpy(dst, src, len); + dst[len] = '\0'; + } + return ret; +} +#endif + +#ifndef HAVE_STRLCAT /* not in glibc for RHEL 5.x, remove when obsolete */ +size_t strlcat(char *dst, const char *src, size_t size) +{ + size_t dsize = strlen(dst); + size_t len = strlen(src); + size_t ret = dsize + len; + + dst += dsize; + size -= dsize; + if (len >= size) + len = size-1; + memcpy(dst, src, len); + dst[len] = '\0'; + return ret; +} +#endif + +#endif /* __KERNEL__ */ diff --git a/libcfs/libcfs/util/parser.c b/libcfs/libcfs/util/parser.c index b40250ba..cca8e97 100644 --- a/libcfs/libcfs/util/parser.c +++ b/libcfs/libcfs/util/parser.c @@ -454,12 +454,20 @@ int Parser_help(int argc, char **argv) return 0; } - line[0]='\0'; - for ( i = 1 ; i < argc ; i++ ) { - if (strlen(argv[i]) > sizeof(line)-strlen(line)-1) + /* Joining command line arguments without space is not critical here + * because of this string is used for search a help topic and assume + * that only one argument will be (the name of topic). For example: + * lst > help ping run + * pingrun: Unknown command. */ + line[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(argv[i]) >= sizeof(line) - strlen(line)) return -E2BIG; - strncat(line, argv[i], sizeof(line)-strlen(line)-1); - } + /* The function strlcat() cannot be used here because of + * this function is used in LNet utils that is not linked + * with libcfs.a. */ + strncat(line, argv[i], sizeof(line) - strlen(line)); + } switch ( process(line, &next, top_level, &result, &prev) ) { case CMD_COMPLETE: @@ -535,18 +543,20 @@ char *Parser_getstr(const char *prompt, const char *deft, char *res, line = readline(theprompt); free(theprompt); - if ( line == NULL || *line == '\0' ) { - strncpy(res, deft, len); - } else { - strncpy(res, line, len); - } - - if ( line ) { - free(line); - return res; - } else { - return NULL; - } + /* The function strlcpy() cannot be used here because of + * this function is used in LNet utils that is not linked + * with libcfs.a. */ + if (line == NULL || *line == '\0') + strncpy(res, deft, len); + else + strncpy(res, line, len); + res[len - 1] = '\0'; + + if (line != NULL) { + free(line); + return res; + } + return NULL; } /* get integer from prompt, loop forever to get it */ diff --git a/libcfs/libcfs/workitem.c b/libcfs/libcfs/workitem.c index bcb4f39..722b25d 100644 --- a/libcfs/libcfs/workitem.c +++ b/libcfs/libcfs/workitem.c @@ -442,7 +442,7 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab, LIBCFS_FREE(sched, sizeof(*sched)); return -E2BIG; } - strncpy(sched->ws_name, name, sizeof(sched->ws_name)); + strlcpy(sched->ws_name, name, sizeof(sched->ws_name)); sched->ws_cptab = cptab; sched->ws_cpt = cpt; diff --git a/lnet/klnds/socklnd/socklnd.c b/lnet/klnds/socklnd/socklnd.c index e798cf8..36d4322 100644 --- a/lnet/klnds/socklnd/socklnd.c +++ b/lnet/klnds/socklnd/socklnd.c @@ -2649,8 +2649,8 @@ ksocknal_enumerate_interfaces(ksock_net_t *net) net->ksnn_interfaces[j].ksni_ipaddr = ip; net->ksnn_interfaces[j].ksni_netmask = mask; - strncpy(&net->ksnn_interfaces[j].ksni_name[0], - names[i], IFNAMSIZ); + strlcpy(net->ksnn_interfaces[j].ksni_name, + names[i], sizeof(net->ksnn_interfaces[j].ksni_name)); j++; } @@ -2833,8 +2833,9 @@ ksocknal_startup (lnet_ni_t *ni) goto fail_1; } - strncpy(&net->ksnn_interfaces[i].ksni_name[0], - ni->ni_interfaces[i], IFNAMSIZ); + strlcpy(net->ksnn_interfaces[i].ksni_name, + ni->ni_interfaces[i], + sizeof(net->ksnn_interfaces[i].ksni_name)); } net->ksnn_ninterfaces = i; } diff --git a/lnet/lnet/config.c b/lnet/lnet/config.c index 7e9c3b6..345dd26 100644 --- a/lnet/lnet/config.c +++ b/lnet/lnet/config.c @@ -53,19 +53,19 @@ lnet_syntax(char *name, char *str, int offset, int width) { static char dots[LNET_SINGLE_TEXTBUF_NOB]; static char dashes[LNET_SINGLE_TEXTBUF_NOB]; - + memset(dots, '.', sizeof(dots)); dots[sizeof(dots)-1] = 0; memset(dashes, '-', sizeof(dashes)); dashes[sizeof(dashes)-1] = 0; - + LCONSOLE_ERROR_MSG(0x10f, "Error parsing '%s=\"%s\"'\n", name, str); - LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n", + LCONSOLE_ERROR_MSG(0x110, "here...........%.*s..%.*s|%.*s|\n", (int)strlen(name), dots, offset, dots, (width < 1) ? 0 : width - 1, dashes); } -int +int lnet_issep (char c) { switch (c) { @@ -377,13 +377,12 @@ lnet_parse_networks(struct list_head *nilist, char *networks) return -EINVAL; } -struct lnet_text_buf * -lnet_new_text_buf (int str_len) +struct lnet_text_buf *lnet_new_text_buf(int str_len) { struct lnet_text_buf *ltb; - int nob; + int nob; - /* NB allocate space for the terminating 0 */ + /* NB allocate space for the terminating 0 */ nob = offsetof(struct lnet_text_buf, ltb_text[str_len + 1]); if (nob > LNET_SINGLE_TEXTBUF_NOB) { /* _way_ conservative for "route net gateway..." */ @@ -395,13 +394,13 @@ lnet_new_text_buf (int str_len) CERROR("Too many text buffers\n"); return NULL; } - + LIBCFS_ALLOC(ltb, nob); if (ltb == NULL) return NULL; ltb->ltb_size = nob; - ltb->ltb_text[0] = 0; + ltb->ltb_text[0] = 0; lnet_tbnob += nob; return ltb; } @@ -457,7 +456,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) /* skip leading whitespace */ while (cfs_iswhite(*str)) str++; - + /* scan for separator or comment */ for (sep = str; *sep != 0; sep++) if (lnet_issep(*sep) || *sep == '#') @@ -470,7 +469,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) lnet_free_text_bufs(&pending); return -1; } - + for (i = 0; i < nob; i++) if (cfs_iswhite(str[i])) ltb->ltb_text[i] = ' '; @@ -488,7 +487,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) sep++; } while (*sep != 0 && !lnet_issep(*sep)); } - + if (*sep == 0) break; @@ -501,7 +500,7 @@ lnet_str2tbs_sep(struct list_head *tbs, char *str) int lnet_expand1tb(struct list_head *list, - char *str, char *sep1, char *sep2, + char *str, char *sep1, char *sep2, char *item, int itemlen) { int len1 = (int)(sep1 - str); @@ -567,10 +566,10 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) if (lnet_expand1tb(&pending, str, sep, sep2, parsed, (int)(enditem - parsed)) != 0) goto failed; - + continue; } - + stride = 1; } @@ -578,27 +577,27 @@ lnet_str2tbs_expand(struct list_head *tbs, char *str) if (enditem != parsed + scanned) /* no trailing junk */ goto failed; - - if (hi < 0 || lo < 0 || stride < 0 || hi < lo || + + if (hi < 0 || lo < 0 || stride < 0 || hi < lo || (hi - lo) % stride != 0) goto failed; - + for (i = lo; i <= hi; i += stride) { snprintf(num, sizeof(num), "%d", i); nob = strlen(num); if (nob + 1 == sizeof(num)) goto failed; - - if (lnet_expand1tb(&pending, str, sep, sep2, + + if (lnet_expand1tb(&pending, str, sep, sep2, num, nob) != 0) goto failed; } } - + list_splice(&pending, tbs->prev); return 1; - + failed: lnet_free_text_bufs(&pending); return -1; @@ -609,7 +608,7 @@ lnet_parse_hops (char *str, unsigned int *hops) { int len = strlen(str); int nob = len; - + return (sscanf(str, "%u%n", hops, &nob) >= 1 && nob == len && *hops > 0 && *hops < 256); @@ -673,8 +672,8 @@ lnet_parse_route (char *str, int *im_a_router) INIT_LIST_HEAD(&nets); /* save a copy of the string for error messages */ - strncpy(cmd, str, sizeof(cmd) - 1); - cmd[sizeof(cmd) - 1] = 0; + strncpy(cmd, str, sizeof(cmd)); + cmd[sizeof(cmd) - 1] = '\0'; sep = str; for (;;) { @@ -695,7 +694,7 @@ lnet_parse_route (char *str, int *im_a_router) sep++; if (*sep != 0) *sep++ = 0; - + if (ntokens == 1) { tmp2 = &nets; /* expanding nets */ } else if (ntokens == 2 && @@ -705,7 +704,7 @@ lnet_parse_route (char *str, int *im_a_router) } else { tmp2 = &gateways; /* expanding gateways */ } - + ltb = lnet_new_text_buf(strlen(token)); if (ltb == NULL) goto out; @@ -713,7 +712,7 @@ lnet_parse_route (char *str, int *im_a_router) strcpy(ltb->ltb_text, token); tmp1 = <b->ltb_list; list_add_tail(tmp1, tmp2); - + while (tmp1 != tmp2) { ltb = list_entry(tmp1, struct lnet_text_buf, ltb_list); @@ -722,7 +721,7 @@ lnet_parse_route (char *str, int *im_a_router) goto token_error; tmp1 = tmp1->next; - + if (rc > 0) { /* expanded! */ list_del(<b->ltb_list); lnet_free_text_buf(ltb); @@ -782,7 +781,7 @@ lnet_parse_route (char *str, int *im_a_router) myrc = 0; goto out; - + token_error: lnet_syntax("routes", cmd, (int)(token - str), strlen(token)); out: @@ -875,15 +874,15 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) sep++; if (*sep == 0) break; - + token = sep++; - + /* scan for token end */ while (*sep != 0 && !cfs_iswhite(*sep)) sep++; if (*sep != 0) *sep++ = 0; - + if (ntokens++ == 0) { net = token; continue; @@ -900,10 +899,10 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip) matched |= (rc != 0); } - + if (!matched) return 0; - + strcpy(net_entry, net); /* replace with matched net */ return 1; } @@ -947,9 +946,9 @@ lnet_splitnets(char *source, struct list_head *nets) sep = strchr(tb->ltb_text, ','); bracket = strchr(tb->ltb_text, '('); - if (sep != NULL && - bracket != NULL && - bracket < sep) { + if (sep != NULL && + bracket != NULL && + bracket < sep) { /* netspec lists interfaces... */ offset2 = offset + (int)(bracket - tb->ltb_text); @@ -981,7 +980,7 @@ lnet_splitnets(char *source, struct list_head *nets) if (tb2 == tb) continue; - + if (net == lnet_netspec2net(tb2->ltb_text)) { /* duplicate network */ lnet_syntax("ip2nets", source, offset, @@ -994,11 +993,13 @@ lnet_splitnets(char *source, struct list_head *nets) return 0; offset += (int)(sep - tb->ltb_text); - tb2 = lnet_new_text_buf(strlen(sep)); - if (tb2 == NULL) - return -ENOMEM; + len = strlen(sep); + tb2 = lnet_new_text_buf(len); + if (tb2 == NULL) + return -ENOMEM; - strncpy(tb2->ltb_text, sep, strlen(sep)); + strncpy(tb2->ltb_text, sep, len); + tb2->ltb_text[len] = '\0'; list_add_tail(&tb2->ltb_list, nets); tb = tb2; @@ -1043,8 +1044,8 @@ lnet_match_networks (char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) tb = list_entry(raw_entries.next, struct lnet_text_buf, ltb_list); - strncpy(source, tb->ltb_text, sizeof(source)-1); - source[sizeof(source)-1] = 0; + strncpy(source, tb->ltb_text, sizeof(source)); + source[sizeof(source) - 1] = '\0'; /* replace ltb_text with the network(s) add on match */ rc = lnet_match_network_tokens(tb->ltb_text, ipaddrs, nip); @@ -1094,21 +1095,21 @@ lnet_match_networks (char **networksp, char *ip2nets, __u32 *ipaddrs, int nip) list_for_each_safe(t, t2, ¤t_nets) { tb = list_entry(t, struct lnet_text_buf, ltb_list); - + list_del(&tb->ltb_list); list_add_tail(&tb->ltb_list, &matched_nets); - len += snprintf(networks + len, sizeof(networks) - len, - "%s%s", (len == 0) ? "" : ",", - tb->ltb_text); - + len += snprintf(networks + len, sizeof(networks) - len, + "%s%s", (len == 0) ? "" : ",", + tb->ltb_text); + if (len >= sizeof(networks)) { CERROR("Too many matched networks\n"); rc = -E2BIG; goto out; } } - + count++; } @@ -1187,8 +1188,8 @@ lnet_ipaddr_enumerate (__u32 **ipaddrsp) CERROR("Can't allocate ipaddrs[%d]\n", nip); nip = -ENOMEM; } else { - memcpy(ipaddrs2, ipaddrs, - nip * sizeof(*ipaddrs)); + memcpy(ipaddrs2, ipaddrs, + nip * sizeof(*ipaddrs)); *ipaddrsp = ipaddrs2; rc = nip; } diff --git a/lnet/selftest/conrpc.c b/lnet/selftest/conrpc.c index 100b447..284f065 100644 --- a/lnet/selftest/conrpc.c +++ b/lnet/selftest/conrpc.c @@ -614,8 +614,8 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst; msrq->mksn_sid = console_session.ses_id; msrq->mksn_force = console_session.ses_force; - strncpy(msrq->mksn_name, console_session.ses_name, - strlen(console_session.ses_name)); + strlcpy(msrq->mksn_name, console_session.ses_name, + sizeof(msrq->mksn_name)); break; case LST_TRANS_SESEND: diff --git a/lnet/selftest/console.c b/lnet/selftest/console.c index 882d68b..34cf28f 100644 --- a/lnet/selftest/console.c +++ b/lnet/selftest/console.c @@ -1766,7 +1766,7 @@ lstcon_session_new(char *name, int key, unsigned feats, if (strlen(name) > sizeof(console_session.ses_name)-1) return -E2BIG; - strncpy(console_session.ses_name, name, + strlcpy(console_session.ses_name, name, sizeof(console_session.ses_name)); rc = lstcon_batch_add(LST_DEFAULT_BATCH); @@ -1990,7 +1990,8 @@ lstcon_acceptor_handle (srpc_server_rpc_t *rpc) if (grp->grp_userland == 0) grp->grp_userland = 1; - strcpy(jrep->join_session, console_session.ses_name); + strlcpy(jrep->join_session, console_session.ses_name, + sizeof(jrep->join_session)); jrep->join_timeout = console_session.ses_timeout; jrep->join_status = 0; diff --git a/lnet/utils/lst.c b/lnet/utils/lst.c index 7695866..64d1f3f 100644 --- a/lnet/utils/lst.c +++ b/lnet/utils/lst.c @@ -602,7 +602,7 @@ jt_lst_new_session(int argc, char **argv) if (rc != 0) snprintf(host, sizeof(host), "unknown_host"); - snprintf(buf, LST_NAME_SIZE, "%s@%s", user, host); + snprintf(buf, sizeof(buf), "%s@%s", user, host); name = buf; } else { @@ -648,7 +648,7 @@ jt_lst_show_session(int argc, char **argv) int key; int rc; - rc = lst_session_info_ioctl(name, LST_NAME_SIZE, &key, + rc = lst_session_info_ioctl(name, sizeof(name), &key, &feats, &sid, &ndinfo); if (rc != 0) { diff --git a/lnet/utils/lstclient.c b/lnet/utils/lstclient.c index 8bcda67..e19c4be 100644 --- a/lnet/utils/lstclient.c +++ b/lnet/utils/lstclient.c @@ -102,7 +102,8 @@ lstjn_join_session(char *ses, char *grp, unsigned feats) req = &rpc->crpc_reqstmsg.msg_body.join_reqst; req->join_sid = LST_INVALID_SID; - strncpy(req->join_group, grp, LST_NAME_SIZE); + strncpy(req->join_group, grp, sizeof(req->join_group)); + req->join_group[sizeof(req->join_group) - 1] = '\0'; sfw_post_rpc(rpc); diff --git a/lnet/utils/portals.c b/lnet/utils/portals.c index 2a8684c..7161f6b 100644 --- a/lnet/utils/portals.c +++ b/lnet/utils/portals.c @@ -152,8 +152,7 @@ ptl_ipaddr_2_str(__u32 ipaddr, char *str, size_t strsize, int lookup) net_ip = htonl (ipaddr); he = gethostbyaddr (&net_ip, sizeof (net_ip), AF_INET); if (he != NULL) { - strncpy(str, he->h_name, strsize - 1); - str[strsize - 1] = '\0'; + strlcpy(str, he->h_name, strsize); return (str); } } diff --git a/lustre/fid/fid_store.c b/lustre/fid/fid_store.c index 8e86091..9585732 100644 --- a/lustre/fid/fid_store.c +++ b/lustre/fid/fid_store.c @@ -95,8 +95,7 @@ int seq_update_cb_add(struct thandle *th, struct lu_server_seq *seq) dcb = &ccb->suc_cb; dcb->dcb_func = seq_update_cb; CFS_INIT_LIST_HEAD(&dcb->dcb_linkage); - strncpy(dcb->dcb_name, "seq_update_cb", MAX_COMMIT_CB_STR_LEN); - dcb->dcb_name[MAX_COMMIT_CB_STR_LEN - 1] = '\0'; + strlcpy(dcb->dcb_name, "seq_update_cb", sizeof(dcb->dcb_name)); rc = dt_trans_cb_add(th, dcb); if (rc) diff --git a/lustre/include/lustre/lustre_user.h b/lustre/include/lustre/lustre_user.h index e385612..6a828f3 100644 --- a/lustre/include/lustre/lustre_user.h +++ b/lustre/include/lustre/lustre_user.h @@ -498,8 +498,8 @@ static inline void obd_uuid2fsname(char *buf, char *uuid, int buflen) strncpy(buf, uuid, buflen - 1); buf[buflen - 1] = '\0'; p = strrchr(buf, '-'); - if (p) - *p = '\0'; + if (p != NULL) + *p = '\0'; } /* printf display format diff --git a/lustre/include/lustre_disk.h b/lustre/include/lustre_disk.h index 567e194..d66015d 100644 --- a/lustre/include/lustre_disk.h +++ b/lustre/include/lustre_disk.h @@ -208,7 +208,8 @@ static inline int server_make_name(__u32 flags, __u16 index, char *fs, /* The lmd is only used internally by Lustre; mount simply passes everything as string options */ -#define LMD_MAGIC 0xbdacbd03 +#define LMD_MAGIC 0xbdacbd03 +#define LMD_PARAMS_MAXLEN 4096 /* gleaned from the mount command - no persistent info here */ struct lustre_mount_data { diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index bfc75ea..48f8be8 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -386,7 +386,7 @@ static int ll_send_mgc_param(struct obd_export *mgc, char *string) if (!msp) return -ENOMEM; - strncpy(msp->mgs_param, string, MGS_PARAM_MAXLEN); + strlcpy(msp->mgs_param, string, sizeof(msp->mgs_param)); rc = obd_set_info_async(NULL, mgc, sizeof(KEY_SET_INFO), KEY_SET_INFO, sizeof(struct mgs_send_param), msp, NULL); if (rc) diff --git a/lustre/lod/lod_lov.c b/lustre/lod/lod_lov.c index 1a8f09a..394264b 100644 --- a/lustre/lod/lod_lov.c +++ b/lustre/lod/lod_lov.c @@ -676,8 +676,8 @@ int lod_store_def_striping(const struct lu_env *env, struct dt_object *dt, v3->lmm_stripe_count = cpu_to_le16(lo->ldo_def_stripenr); v3->lmm_stripe_offset = cpu_to_le16(lo->ldo_def_stripe_offset); v3->lmm_stripe_size = cpu_to_le32(lo->ldo_def_stripe_size); - if (lo->ldo_pool) - strncpy(v3->lmm_pool_name, lo->ldo_pool, + if (lo->ldo_pool != NULL) + strlcpy(v3->lmm_pool_name, lo->ldo_pool, sizeof(v3->lmm_pool_name)); info->lti_buf.lb_buf = v3; info->lti_buf.lb_len = sizeof(*v3); diff --git a/lustre/lod/lod_object.c b/lustre/lod/lod_object.c index 5674a36..18c8000 100644 --- a/lustre/lod/lod_object.c +++ b/lustre/lod/lod_object.c @@ -1476,9 +1476,9 @@ next: cpu_to_le16(lo->ldo_def_stripe_offset); v3->lmm_stripe_size = cpu_to_le32(lo->ldo_def_stripe_size); - if (lo->ldo_pool) - strncpy(v3->lmm_pool_name, lo->ldo_pool, - LOV_MAXPOOLNAME); + if (lo->ldo_pool != NULL) + strlcpy(v3->lmm_pool_name, lo->ldo_pool, + sizeof(v3->lmm_pool_name)); info->lti_buf.lb_buf = v3; info->lti_buf.lb_len = sizeof(*v3); @@ -1933,9 +1933,9 @@ static int lod_xattr_set_lmv(const struct lu_env *env, struct dt_object *dt, cpu_to_le16(lo->ldo_def_stripe_offset); v3->lmm_stripe_size = cpu_to_le32(lo->ldo_def_stripe_size); - if (lo->ldo_pool) - strncpy(v3->lmm_pool_name, lo->ldo_pool, - LOV_MAXPOOLNAME); + if (lo->ldo_pool != NULL) + strlcpy(v3->lmm_pool_name, lo->ldo_pool, + sizeof(v3->lmm_pool_name)); info->lti_buf.lb_buf = v3; info->lti_buf.lb_len = sizeof(*v3); @@ -2076,9 +2076,9 @@ int lod_dir_striping_create_internal(const struct lu_env *env, v3->lmm_stripe_count = cpu_to_le16(lo->ldo_def_stripenr); v3->lmm_stripe_offset = cpu_to_le16(lo->ldo_def_stripe_offset); v3->lmm_stripe_size = cpu_to_le32(lo->ldo_def_stripe_size); - if (lo->ldo_pool) - strncpy(v3->lmm_pool_name, lo->ldo_pool, - LOV_MAXPOOLNAME); + if (lo->ldo_pool != NULL) + strlcpy(v3->lmm_pool_name, lo->ldo_pool, + sizeof(v3->lmm_pool_name)); info->lti_buf.lb_buf = v3; info->lti_buf.lb_len = sizeof(*v3); diff --git a/lustre/lod/lod_pool.c b/lustre/lod/lod_pool.c index c8959a0..75011d9 100644 --- a/lustre/lod/lod_pool.c +++ b/lustre/lod/lod_pool.c @@ -441,8 +441,7 @@ int lod_pool_new(struct obd_device *obd, char *poolname) if (new_pool == NULL) RETURN(-ENOMEM); - strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME); - new_pool->pool_name[LOV_MAXPOOLNAME] = '\0'; + strlcpy(new_pool->pool_name, poolname, sizeof(new_pool->pool_name)); new_pool->pool_lobd = obd; /* ref count init to 1 because when created a pool is always used * up to deletion diff --git a/lustre/lov/lov_pool.c b/lustre/lov/lov_pool.c index 88cf76a..a33e90d 100644 --- a/lustre/lov/lov_pool.c +++ b/lustre/lov/lov_pool.c @@ -449,8 +449,7 @@ int lov_pool_new(struct obd_device *obd, char *poolname) if (new_pool == NULL) RETURN(-ENOMEM); - strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME); - new_pool->pool_name[LOV_MAXPOOLNAME] = '\0'; + strlcpy(new_pool->pool_name, poolname, sizeof(new_pool->pool_name)); new_pool->pool_lobd = obd; /* ref count init to 1 because when created a pool is always used * up to deletion diff --git a/lustre/mdt/mdt_coordinator.c b/lustre/mdt/mdt_coordinator.c index 1617eeb..0a43d93 100644 --- a/lustre/mdt/mdt_coordinator.c +++ b/lustre/mdt/mdt_coordinator.c @@ -227,9 +227,8 @@ static int mdt_coordinator_cb(const struct lu_env *env, RETURN(-ENOMEM); } hal->hal_version = HAL_VERSION; - strncpy(hal->hal_fsname, hsd->fs_name, - MTI_NAME_MAXLEN); - hal->hal_fsname[MTI_NAME_MAXLEN] = '\0'; + strlcpy(hal->hal_fsname, hsd->fs_name, + MTI_NAME_MAXLEN + 1); hal->hal_compound_id = larr->arr_compound_id; hal->hal_archive_id = larr->arr_archive_id; hal->hal_flags = larr->arr_flags; diff --git a/lustre/mgs/mgs_llog.c b/lustre/mgs/mgs_llog.c index aca72e3..161d386 100644 --- a/lustre/mgs/mgs_llog.c +++ b/lustre/mgs/mgs_llog.c @@ -1068,9 +1068,10 @@ static int mgs_replace_nids_log(const struct lu_env *env, if (!mrul) GOTO(out_close, rc = -ENOMEM); /* devname is only needed information to replace UUID records */ - strncpy(mrul->target.mti_svname, devname, MTI_NAME_MAXLEN); + strlcpy(mrul->target.mti_svname, devname, + sizeof(mrul->target.mti_svname)); /* parse nids later */ - strncpy(mrul->target.mti_params, nids, MTI_PARAM_MAXLEN); + strlcpy(mrul->target.mti_params, nids, sizeof(mrul->target.mti_params)); /* Copy records to this temporary llog */ mrul->temp_llh = orig_llh; @@ -3861,9 +3862,7 @@ int mgs_setparam(const struct lu_env *env, struct mgs_device *mgs, RETURN(-EINVAL); } else { /* assume devname is the fsname */ - memset(fsname, 0, MTI_NAME_MAXLEN); - strncpy(fsname, devname, MTI_NAME_MAXLEN); - fsname[MTI_NAME_MAXLEN - 1] = 0; + strlcpy(fsname, devname, MTI_NAME_MAXLEN); } CDEBUG(D_MGS, "setparam fs='%s' device='%s'\n", fsname, devname); diff --git a/lustre/obdclass/dt_object.c b/lustre/obdclass/dt_object.c index a941781..75f44f3 100644 --- a/lustre/obdclass/dt_object.c +++ b/lustre/obdclass/dt_object.c @@ -296,22 +296,21 @@ dt_store_resolve(const struct lu_env *env, struct dt_device *dt, struct dt_thread_info *info = dt_info(env); struct dt_find_hint *dfh = &info->dti_dfh; struct dt_object *obj; - char *local = info->dti_buf; int result; dfh->dfh_dt = dt; dfh->dfh_fid = fid; - strncpy(local, path, DT_MAX_PATH); - local[DT_MAX_PATH - 1] = '\0'; + strlcpy(info->dti_buf, path, sizeof(info->dti_buf)); result = dt->dd_ops->dt_root_get(env, dt, fid); if (result == 0) { obj = dt_locate(env, dt, fid); if (!IS_ERR(obj)) { dfh->dfh_o = obj; - result = dt_path_parser(env, local, dt_find_entry, dfh); + result = dt_path_parser(env, info->dti_buf, + dt_find_entry, dfh); if (result != 0) obj = ERR_PTR(result); else diff --git a/lustre/obdclass/obd_mount.c b/lustre/obdclass/obd_mount.c index bfa1c12..24f6c22 100644 --- a/lustre/obdclass/obd_mount.c +++ b/lustre/obdclass/obd_mount.c @@ -1066,7 +1066,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) } lmd->lmd_magic = LMD_MAGIC; - OBD_ALLOC(lmd->lmd_params, 4096); + OBD_ALLOC(lmd->lmd_params, LMD_PARAMS_MAXLEN); if (lmd->lmd_params == NULL) RETURN(-ENOMEM); lmd->lmd_params[0] = '\0'; @@ -1154,7 +1154,7 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) goto invalid; clear++; } else if (strncmp(s1, "param=", 6) == 0) { - int length; + size_t length, params_length; char *tail = strchr(s1 + 6, ','); if (tail == NULL) { length = strlen(s1); @@ -1170,8 +1170,12 @@ static int lmd_parse(char *options, struct lustre_mount_data *lmd) length = param_str - s1 - supplementary; } length -= 6; + params_length = strlen(lmd->lmd_params); + if (params_length + length + 1 >= LMD_PARAMS_MAXLEN) + RETURN(-E2BIG); strncat(lmd->lmd_params, s1 + 6, length); - strcat(lmd->lmd_params, " "); + lmd->lmd_params[params_length + length] = '\0'; + strlcat(lmd->lmd_params, " ", LMD_PARAMS_MAXLEN); s3 = s1 + 6 + length; clear++; } else if (strncmp(s1, "osd=", 4) == 0) { diff --git a/lustre/ofd/ofd_io.c b/lustre/ofd/ofd_io.c index 8c8835a..a4d7c17 100644 --- a/lustre/ofd/ofd_io.c +++ b/lustre/ofd/ofd_io.c @@ -808,8 +808,7 @@ static int ofd_soft_sync_cb_add(struct thandle *th, struct obd_export *exp) dcb = &ossc->ossc_cb; dcb->dcb_func = ofd_cb_soft_sync; CFS_INIT_LIST_HEAD(&dcb->dcb_linkage); - strncpy(dcb->dcb_name, "ofd_cb_soft_sync", MAX_COMMIT_CB_STR_LEN); - dcb->dcb_name[MAX_COMMIT_CB_STR_LEN - 1] = '\0'; + strlcpy(dcb->dcb_name, "ofd_cb_soft_sync", sizeof(dcb->dcb_name)); rc = dt_trans_cb_add(th, dcb); if (rc) { diff --git a/lustre/osd-zfs/osd_handler.c b/lustre/osd-zfs/osd_handler.c index 83b243d..05f51c7 100644 --- a/lustre/osd-zfs/osd_handler.c +++ b/lustre/osd-zfs/osd_handler.c @@ -516,7 +516,8 @@ static int osd_mount(const struct lu_env *env, struct osd_device *o, struct lustre_cfg *cfg) { struct dsl_dataset *ds; - char *dev = lustre_cfg_string(cfg, 1); + char *mntdev = lustre_cfg_string(cfg, 1); + char *svname = lustre_cfg_string(cfg, 4); dmu_buf_t *rootdb; dsl_pool_t *dp; int rc; @@ -525,12 +526,16 @@ static int osd_mount(const struct lu_env *env, if (o->od_objset.os != NULL) RETURN(0); - if (strlen(dev) >= sizeof(o->od_mntdev)) + if (mntdev == NULL || svname == NULL) + RETURN(-EINVAL); + + rc = strlcpy(o->od_mntdev, mntdev, sizeof(o->od_mntdev)); + if (rc >= sizeof(o->od_mntdev)) RETURN(-E2BIG); - strcpy(o->od_mntdev, dev); - strncpy(o->od_svname, lustre_cfg_string(cfg, 4), - sizeof(o->od_svname) - 1); + rc = strlcpy(o->od_svname, svname, sizeof(o->od_svname)); + if (rc >= sizeof(o->od_svname)) + RETURN(-E2BIG); if (server_name_is_ost(o->od_svname)) o->od_is_ost = 1; @@ -717,8 +722,10 @@ static struct lu_device *osd_device_fini(const struct lu_env *env, if (rc) CERROR("%s: dsl_prop_unregister xattr error %d\n", o->od_svname, rc); - arc_remove_prune_callback(o->arc_prune_cb); - o->arc_prune_cb = NULL; + if (o->arc_prune_cb != NULL) { + arc_remove_prune_callback(o->arc_prune_cb); + o->arc_prune_cb = NULL; + } osd_sync(env, lu2dt_dev(d)); txg_wait_callbacks(spa_get_dsl(dmu_objset_spa(o->od_objset.os))); } diff --git a/lustre/osd-zfs/osd_oi.c b/lustre/osd-zfs/osd_oi.c index 99bf185..b805643 100644 --- a/lustre/osd-zfs/osd_oi.c +++ b/lustre/osd-zfs/osd_oi.c @@ -127,7 +127,11 @@ osd_oi_lookup(const struct lu_env *env, struct osd_device *o, if (rc) return rc; - strncpy(oi->oi_name, name, OSD_OI_NAME_SIZE - 1); + rc = strlcpy(oi->oi_name, name, sizeof(oi->oi_name)); + if (rc >= sizeof(oi->oi_name)) + return -E2BIG; + + rc = 0; oi->oi_zapid = zde->zde_dnode; return rc; diff --git a/lustre/osp/lwp_dev.c b/lustre/osp/lwp_dev.c index c115ee6..48d654d 100644 --- a/lustre/osp/lwp_dev.c +++ b/lustre/osp/lwp_dev.c @@ -67,7 +67,7 @@ static int lwp_setup(const struct lu_env *env, struct lwp_device *lwp, char *ptr; class_uuid_t uuid; struct obd_import *imp; - int len = strlen(lwp_name); + int len = strlen(lwp_name) + 1; int rc; ENTRY; @@ -89,7 +89,7 @@ static int lwp_setup(const struct lu_env *env, struct lwp_device *lwp, strncpy(server_uuid, lwp_name, ptr - lwp_name); server_uuid[ptr - lwp_name] = '\0'; - strncat(server_uuid, "_UUID", len - 1); + strlcat(server_uuid, "_UUID", len); lustre_cfg_bufs_reset(bufs, lwp_name); lustre_cfg_bufs_set_string(bufs, 1, server_uuid); lustre_cfg_bufs_set_string(bufs, 2, nidstring); diff --git a/lustre/ptlrpc/gss/gss_pipefs.c b/lustre/ptlrpc/gss/gss_pipefs.c index dc4bb54..81c3635 100644 --- a/lustre/ptlrpc/gss/gss_pipefs.c +++ b/lustre/ptlrpc/gss/gss_pipefs.c @@ -1083,7 +1083,7 @@ int gss_ctx_refresh_pf(struct ptlrpc_cli_ctx *ctx) gmsg->gum_data.gum_gid = 0; /* not used for now */ gmsg->gum_data.gum_svc = import_to_gss_svc(imp); gmsg->gum_data.gum_nid = imp->imp_connection->c_peer.nid; - strncpy(gmsg->gum_data.gum_obd, imp->imp_obd->obd_name, + strlcpy(gmsg->gum_data.gum_obd, imp->imp_obd->obd_name, sizeof(gmsg->gum_data.gum_obd)); /* This only could happen when sysadmin set it dead/expired diff --git a/lustre/ptlrpc/gss/sec_gss.c b/lustre/ptlrpc/gss/sec_gss.c index 5c04d1c..a830b0d 100644 --- a/lustre/ptlrpc/gss/sec_gss.c +++ b/lustre/ptlrpc/gss/sec_gss.c @@ -624,24 +624,22 @@ int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred) void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize) { - buf[0] = '\0'; - - if (flags & PTLRPC_CTX_NEW) - strncat(buf, "new,", bufsize); - if (flags & PTLRPC_CTX_UPTODATE) - strncat(buf, "uptodate,", bufsize); - if (flags & PTLRPC_CTX_DEAD) - strncat(buf, "dead,", bufsize); - if (flags & PTLRPC_CTX_ERROR) - strncat(buf, "error,", bufsize); - if (flags & PTLRPC_CTX_CACHED) - strncat(buf, "cached,", bufsize); - if (flags & PTLRPC_CTX_ETERNAL) - strncat(buf, "eternal,", bufsize); - if (buf[0] == '\0') - strncat(buf, "-,", bufsize); - - buf[strlen(buf) - 1] = '\0'; + buf[0] = '\0'; + + if (flags & PTLRPC_CTX_NEW) + strlcat(buf, "new,", bufsize); + if (flags & PTLRPC_CTX_UPTODATE) + strlcat(buf, "uptodate,", bufsize); + if (flags & PTLRPC_CTX_DEAD) + strlcat(buf, "dead,", bufsize); + if (flags & PTLRPC_CTX_ERROR) + strlcat(buf, "error,", bufsize); + if (flags & PTLRPC_CTX_CACHED) + strlcat(buf, "cached,", bufsize); + if (flags & PTLRPC_CTX_ETERNAL) + strlcat(buf, "eternal,", bufsize); + if (buf[0] == '\0') + strlcat(buf, "-,", bufsize); } int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, diff --git a/lustre/ptlrpc/ptlrpcd.c b/lustre/ptlrpc/ptlrpcd.c index cd1f850..ad0ef6c 100644 --- a/lustre/ptlrpc/ptlrpcd.c +++ b/lustre/ptlrpc/ptlrpcd.c @@ -695,7 +695,7 @@ int ptlrpcd_start(int index, int max, const char *name, struct ptlrpcd_ctl *pc) init_completion(&pc->pc_starting); init_completion(&pc->pc_finishing); spin_lock_init(&pc->pc_lock); - strncpy(pc->pc_name, name, sizeof(pc->pc_name) - 1); + strlcpy(pc->pc_name, name, sizeof(pc->pc_name)); pc->pc_set = ptlrpc_prep_set(); if (pc->pc_set == NULL) GOTO(out, rc = -ENOMEM); diff --git a/lustre/ptlrpc/sec_config.c b/lustre/ptlrpc/sec_config.c index fad999f..30ac1ec 100644 --- a/lustre/ptlrpc/sec_config.c +++ b/lustre/ptlrpc/sec_config.c @@ -114,8 +114,7 @@ int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr) return 0; } - strncpy(buf, str, sizeof(buf)); - buf[sizeof(buf) - 1] = '\0'; + strlcpy(buf, str, sizeof(buf)); bulk = strchr(buf, '-'); if (bulk) diff --git a/lustre/quota/qmt_dev.c b/lustre/quota/qmt_dev.c index 0bd91e7..323e56e 100644 --- a/lustre/quota/qmt_dev.c +++ b/lustre/quota/qmt_dev.c @@ -202,12 +202,17 @@ static int qmt_device_init0(const struct lu_env *env, struct qmt_device *qmt, struct lu_device *ld = qmt2lu_dev(qmt); struct obd_device *obd, *mdt_obd; struct obd_type *type; + char *svname = lustre_cfg_string(cfg, 0); int rc; ENTRY; + if (svname == NULL) + RETURN(-EINVAL); + /* record who i am, it might be useful ... */ - strncpy(qmt->qmt_svname, lustre_cfg_string(cfg, 0), - sizeof(qmt->qmt_svname) - 1); + rc = strlcpy(qmt->qmt_svname, svname, sizeof(qmt->qmt_svname)); + if (rc >= sizeof(qmt->qmt_svname)) + RETURN(-E2BIG); /* look-up the obd_device associated with the qmt */ obd = class_name2obd(qmt->qmt_svname); diff --git a/lustre/target/tgt_lastrcvd.c b/lustre/target/tgt_lastrcvd.c index 76b1165..fa9ff1c 100644 --- a/lustre/target/tgt_lastrcvd.c +++ b/lustre/target/tgt_lastrcvd.c @@ -453,8 +453,7 @@ int tgt_last_commit_cb_add(struct thandle *th, struct lu_target *tgt, dcb = &ccb->llcc_cb; dcb->dcb_func = tgt_cb_last_committed; CFS_INIT_LIST_HEAD(&dcb->dcb_linkage); - strncpy(dcb->dcb_name, "tgt_cb_last_committed", MAX_COMMIT_CB_STR_LEN); - dcb->dcb_name[MAX_COMMIT_CB_STR_LEN - 1] = '\0'; + strlcpy(dcb->dcb_name, "tgt_cb_last_committed", sizeof(dcb->dcb_name)); rc = dt_trans_cb_add(th, dcb); if (rc) { @@ -516,8 +515,7 @@ int tgt_new_client_cb_add(struct thandle *th, struct obd_export *exp) dcb = &ccb->lncc_cb; dcb->dcb_func = tgt_cb_new_client; CFS_INIT_LIST_HEAD(&dcb->dcb_linkage); - strncpy(dcb->dcb_name, "tgt_cb_new_client", MAX_COMMIT_CB_STR_LEN); - dcb->dcb_name[MAX_COMMIT_CB_STR_LEN - 1] = '\0'; + strlcpy(dcb->dcb_name, "tgt_cb_new_client", sizeof(dcb->dcb_name)); rc = dt_trans_cb_add(th, dcb); if (rc) { diff --git a/lustre/tests/mpi/Makefile.am b/lustre/tests/mpi/Makefile.am index 9344098..c128459 100644 --- a/lustre/tests/mpi/Makefile.am +++ b/lustre/tests/mpi/Makefile.am @@ -14,7 +14,9 @@ write_append_truncate_SOURCES=write_append_truncate.c write_disjoint_SOURCES=write_disjoint.c createmany_mpi_SOURCES=createmany-mpi.c parallel_grouplock_SOURCES=parallel_grouplock.c lp_utils.c lp_utils.h + cascading_rw_SOURCES=cascading_rw.c lp_utils.c lp_utils.h -cascading_rw_LDADD=-L$(top_builddir)/lustre/utils -llustreapi +cascading_rw_LDADD=-L$(top_builddir)/lustre/utils -llustreapi $(LIBCFS) + mdsrate_SOURCES=mdsrate.c mdsrate_LDADD=-L$(top_builddir)/lustre/utils -llustreapi $(LIBCFS) diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index f737ddb..dde2048 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -86,11 +86,13 @@ llverfs_LDADD := $(EXT2FSLIB) $(E2PLIB) llverdev_LDADD := $(EXT2FSLIB) $(BLKIDLIB) +L_STRING := $(top_builddir)/libcfs/libcfs/user-string.c L_IOCTL := $(top_builddir)/libcfs/libcfs/util/l_ioctl.c L_KERNELCOMM := $(top_builddir)/libcfs/libcfs/kernel_user_comm.c liblustreapitmp_a_SOURCES = liblustreapi.c liblustreapi_hsm.c \ liblustreapi_nodemap.c lustreapi_internal.h \ - liblustreapi_json.c $(L_IOCTL) $(L_KERNELCOMM) + liblustreapi_json.c $(L_IOCTL) $(L_KERNELCOMM) \ + $(L_STRING) # build static and shared lib lustreapi liblustreapi.a : liblustreapitmp.a @@ -165,8 +167,8 @@ l_getidentity_DEPENDENCIES := $(LIBPTLCTL) ltrack_stats_SOURCES = ltrack_stats.c lhsmtool_posix_SOURCES = lhsmtool_posix.c -lhsmtool_posix_LDADD := liblustreapi.a $(PTHREAD_LIBS) -lhsmtool_posix_DEPENDENCIES := liblustreapi.a +lhsmtool_posix_LDADD := liblustreapi.a $(LIBPTLCTL) $(PTHREAD_LIBS) +lhsmtool_posix_DEPENDENCIES := liblustreapi.a $(LIBPTLCTL) wirecheck_SOURCES = wirecheck.c wirecheck_CPPFLAGS = -DCC="\"$(CC)\"" @@ -183,4 +185,3 @@ newwiretest: wirehdr.c wirecheck LANG=C ./wirecheck >> wiretest.c cp ../ptlrpc/wirehdr.c ../ptlrpc/wiretest.c LANG=C ./wirecheck >> ../ptlrpc/wiretest.c - diff --git a/lustre/utils/gss/gssd.c b/lustre/utils/gss/gssd.c index 6650648..39d75d8 100644 --- a/lustre/utils/gss/gssd.c +++ b/lustre/utils/gss/gssd.c @@ -192,17 +192,17 @@ main(int argc, char *argv[]) verbosity++; break; case 'p': - strncpy(pipefs_dir, optarg, sizeof(pipefs_dir)); + strlcpy(pipefs_dir, optarg, sizeof(pipefs_dir)); if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0') errx(1, "pipefs path name too long"); break; case 'k': - strncpy(keytabfile, optarg, sizeof(keytabfile)); + strlcpy(keytabfile, optarg, sizeof(keytabfile)); if (keytabfile[sizeof(keytabfile)-1] != '\0') errx(1, "keytab path name too long"); break; case 'd': - strncpy(ccachedir, optarg, sizeof(ccachedir)); + strlcpy(ccachedir, optarg, sizeof(ccachedir)); if (ccachedir[sizeof(ccachedir)-1] != '\0') errx(1, "ccachedir path name too long"); break; diff --git a/lustre/utils/gss/lgss_keyring.c b/lustre/utils/gss/lgss_keyring.c index 7e28ce2..15773c5 100644 --- a/lustre/utils/gss/lgss_keyring.c +++ b/lustre/utils/gss/lgss_keyring.c @@ -576,7 +576,7 @@ static int parse_callout_info(const char *coinfo, data[6], data[7]); uparam->kup_secid = strtol(data[0], NULL, 0); - strncpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech)); + strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech)); uparam->kup_uid = strtol(data[2], NULL, 0); uparam->kup_gid = strtol(data[3], NULL, 0); if (strchr(data[4], 'r')) @@ -587,7 +587,7 @@ static int parse_callout_info(const char *coinfo, uparam->kup_is_ost = 1; uparam->kup_svc = strtol(data[5], NULL, 0); uparam->kup_nid = strtoll(data[6], NULL, 0); - strncpy(uparam->kup_tgt, data[7], sizeof(uparam->kup_tgt)); + strlcpy(uparam->kup_tgt, data[7], sizeof(uparam->kup_tgt)); logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u " "is_root %d, is_mdt %d, is_ost %d, svc %d, nid 0x%llx, tgt %s\n", diff --git a/lustre/utils/gss/svcgssd_proc.c b/lustre/utils/gss/svcgssd_proc.c index 22f2f17..a0ffa52 100644 --- a/lustre/utils/gss/svcgssd_proc.c +++ b/lustre/utils/gss/svcgssd_proc.c @@ -328,6 +328,7 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, return -1; } memcpy(sname, name.value, name.length); + sname[name.length] = '\0'; gss_release_buffer(&min_stat, &name); if (lustre_svc == LUSTRE_GSS_SVC_MDS) diff --git a/lustre/utils/l_getidentity.c b/lustre/utils/l_getidentity.c index a15eaf9..8e718a5 100644 --- a/lustre/utils/l_getidentity.c +++ b/lustre/utils/l_getidentity.c @@ -128,8 +128,7 @@ int get_groups_local(struct identity_downcall_data *data, return -1; } - memset(pw_name, 0, namelen); - strncpy(pw_name, pw->pw_name, namelen - 1); + strlcpy(pw_name, pw->pw_name, namelen); groups = data->idd_groups; /* Allocate array of size maxgroups instead of handling two @@ -225,13 +224,18 @@ int parse_perm(__u32 *perm, __u32 *noperm, char *str) *noperm = 0; start = str; while (1) { - memset(name, 0, sizeof(name)); - end = strchr(start, ','); - if (!end) - end = str + strlen(str); - if (start >= end) - break; - strncpy(name, start, end - start); + size_t len; + memset(name, 0, sizeof(name)); + end = strchr(start, ','); + if (end == NULL) + end = str + strlen(str); + if (start >= end) + break; + len = end - start; + if (len >= sizeof(name)) + return -E2BIG; + strncpy(name, start, len); + name[len] = '\0'; for (pt = perm_types; pt->name; pt++) { if (!strcasecmp(name, pt->name)) { *perm |= pt->bit; diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 5f125f2..88bef78 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -351,7 +351,8 @@ static int lfs_migrate(char *name, unsigned long long stripe_size, __u64 migration_flags) { int fd, fdv; - char volatile_file[PATH_MAX]; + char volatile_file[PATH_MAX + + LUSTRE_VOLATILE_HDR_LEN + 4]; char parent[PATH_MAX]; char *ptr; int rc; @@ -427,7 +428,12 @@ static int lfs_migrate(char *name, unsigned long long stripe_size, else *ptr = '\0'; } - sprintf(volatile_file, "%s/%s::", parent, LUSTRE_VOLATILE_HDR); + rc = snprintf(volatile_file, sizeof(volatile_file), "%s/%s::", parent, + LUSTRE_VOLATILE_HDR); + if (rc >= sizeof(volatile_file)) { + rc = -E2BIG; + goto free; + } /* create, open a volatile file, use caching (ie no directio) */ /* exclusive create is not needed because volatile files cannot @@ -1735,7 +1741,10 @@ static int showdf(char *mntdir, struct obd_statfs *stat, double ratio = 0; char *suffix = "KMGTPEZY"; /* Note if we have >2^64 bytes/fs these buffers will need to be grown */ - char tbuf[20], ubuf[20], abuf[20], rbuf[20]; + char tbuf[3 * sizeof(__u64)]; + char ubuf[3 * sizeof(__u64)]; + char abuf[3 * sizeof(__u64)]; + char rbuf[3 * sizeof(__u64)]; if (!uuid || !stat) return -EINVAL; @@ -2869,7 +2878,7 @@ static int lfs_quota(int argc, char **argv) break; case 'o': valid = qctl.qc_valid = QC_UUID; - strncpy(obd_uuid, optarg, sizeof(qctl.obd_uuid)); + strlcpy(obd_uuid, optarg, sizeof(qctl.obd_uuid)); break; case 'i': valid = qctl.qc_valid = QC_MDTIDX; @@ -3281,6 +3290,10 @@ static int lfs_fid2path(int argc, char **argv) device = argv[optind++]; path = calloc(1, PATH_MAX); + if (path == NULL) { + fprintf(stderr, "error: Not enough memory\n"); + return -errno; + } rc = 0; while (optind < argc) { diff --git a/lustre/utils/lhsmtool_posix.c b/lustre/utils/lhsmtool_posix.c index 7650a8d..31e5486 100644 --- a/lustre/utils/lhsmtool_posix.c +++ b/lustre/utils/lhsmtool_posix.c @@ -366,6 +366,9 @@ static int ct_mkdir_p(const char *path) int rc; ptr = strdup(path); + if (ptr == NULL) + return -errno; + saved = ptr; while (*ptr == '/') ptr++; @@ -856,7 +859,7 @@ static int ct_archive(const struct hsm_action_item *hai, const long hal_flags) if (hai->hai_extent.length == -1) { /* whole file, write it to tmp location and atomically * replace old archived file */ - strncat(dst, "_tmp", sizeof(dst) - strlen(dst) - 1); + strlcat(dst, "_tmp", sizeof(dst)); /* we cannot rely on the same test because ct_copy_data() * updates hai_extent.length */ rename_needed = true; @@ -1202,7 +1205,7 @@ static int ct_remove(const struct hsm_action_item *hai, const long hal_flags) goto fini; } - strncat(dst, ".lov", sizeof(dst) - strlen(dst) - 1); + strlcat(dst, ".lov", sizeof(dst)); rc = unlink(dst); if (rc < 0) { rc = -errno; @@ -1529,8 +1532,8 @@ static int ct_rebind_one(const lustre_fid *old_fid, const lustre_fid *new_fid) return -errno; } /* rename lov file */ - strncat(src, ".lov", sizeof(src) - strlen(src) - 1); - strncat(dst, ".lov", sizeof(dst) - strlen(dst) - 1); + strlcat(src, ".lov", sizeof(src)); + strlcat(dst, ".lov", sizeof(dst)); if (rename(src, dst)) CT_ERROR(errno, "cannot rename '%s' to '%s'", src, dst); @@ -1690,21 +1693,28 @@ out: static int ct_max_sequence(void) { - int rc, i; - char path[PATH_MAX]; - __u64 seq = 0; - __u16 subseq; + int rc, i; + char path[PATH_MAX]; + __u64 seq = 0; + __u16 subseq; - strncpy(path, opt.o_hsm_root, sizeof(path)); + strlcpy(path, opt.o_hsm_root, sizeof(path)); /* FID sequence is stored in top-level directory names: * hsm_root/16bits (high weight)/16 bits/16 bits/16 bits (low weight). */ for (i = 0; i < 4; i++) { + size_t path_len; + rc = ct_dir_level_max(path, &subseq); if (rc != 0) return rc; seq |= ((__u64)subseq << ((3 - i) * 16)); - sprintf(path + strlen(path), "/%04x", subseq); + path_len = strlen(path); + rc = snprintf(path + path_len, sizeof(path) - path_len, + "/%04x", subseq); + if (rc >= (sizeof(path) - path_len)) + return -E2BIG; + path[sizeof(path) - 1] = '\0'; } printf("max_sequence: "LPX64"\n", seq); @@ -1870,7 +1880,7 @@ int main(int argc, char **argv) { int rc; - strncpy(cmd_name, basename(argv[0]), sizeof(cmd_name)); + strlcpy(cmd_name, basename(argv[0]), sizeof(cmd_name)); rc = ct_parseopts(argc, argv); if (rc < 0) { CT_WARN("try '%s --help' for more information", cmd_name); diff --git a/lustre/utils/libiam.c b/lustre/utils/libiam.c index 9b64c61..704601e 100644 --- a/lustre/utils/libiam.c +++ b/lustre/utils/libiam.c @@ -348,7 +348,7 @@ static char *iam_convert(int size, int need_convert, char *source) free(opt); } } else { - strncpy(ptr, source, size + 1); + strlcpy(ptr, source, size + 1); } return ptr; diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 57a14eb..7581054 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -426,63 +426,70 @@ static int get_param_obdvar(const char *fsname, const char *file_path, const char *obd_type, const char *param_name, char *value, unsigned int val_len) { - char devices[PATH_MAX + 1], dev[PATH_MAX + 1] = "*", fs[PATH_MAX + 1]; - FILE *fp = fopen(DEVICES_LIST, "r"); - int rc = 0; + char devices[PATH_MAX]; + char dev[PATH_MAX] = "*"; + char fs[PATH_MAX]; + FILE *fp = NULL; + int rc = 0; - if (!fsname && file_path) { - rc = llapi_search_fsname(file_path, fs); - if (rc) { - llapi_error(LLAPI_MSG_ERROR, rc, - "'%s' is not on a Lustre filesystem", - file_path); - if (fp != NULL) - fclose(fp); - return rc; - } - } else if (fsname) { - if (strlen(fsname) > sizeof(fs)-1) { - if (fp != NULL) - fclose(fp); - return -E2BIG; - } - strncpy(fs, fsname, sizeof(fs)); - } + fp = fopen(DEVICES_LIST, "r"); + if (fp == NULL) { + rc = -errno; + llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST); + GOTO(out, rc); + } - if (fp == NULL) { - rc = -errno; - llapi_error(LLAPI_MSG_ERROR, rc, "error: opening "DEVICES_LIST); - return rc; - } + if (fsname == NULL && file_path != NULL) { + rc = llapi_search_fsname(file_path, fs); + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "'%s' is not on a Lustre filesystem", + file_path); + GOTO(out, rc); + } + } else if (fsname != NULL) { + rc = strlcpy(fs, fsname, sizeof(fs)); + if (rc >= sizeof(fs)) + GOTO(out, rc = -E2BIG); + } - while (fgets(devices, sizeof(devices), fp) != NULL) { - char *bufp = devices, *tmp; + while (fgets(devices, sizeof(devices) - 1, fp) != NULL) { + char *bufp = devices, *tmp; - while (bufp[0] == ' ') - ++bufp; + devices[sizeof(devices) - 1] = '\0'; + while (bufp[0] == ' ') + ++bufp; - tmp = strstr(bufp, obd_type); - if (tmp) { - tmp += strlen(obd_type) + 1; - if (strcmp(tmp, fs)) - continue; - if (strlen(tmp) > sizeof(dev)-1) { - fclose(fp); - return -E2BIG; - } - strncpy(dev, tmp, sizeof(dev)); - tmp = strchr(dev, ' '); + tmp = strstr(bufp, obd_type); + if (tmp != NULL) { + tmp += strlen(obd_type) + 1; + if (strcmp(tmp, fs)) + continue; + rc = strlcpy(dev, tmp, sizeof(dev)); + if (rc >= sizeof(dev)) + GOTO(out, rc = -E2BIG); + tmp = strchr(dev, ' '); if (tmp != NULL) *tmp = '\0'; - break; - } - } + break; + } + } - if (dev[0] == '*' && strlen(fs)) - snprintf(dev, PATH_MAX, "%s-*", fs); - snprintf(devices, PATH_MAX, "%s/%s/%s", obd_type, dev, param_name); - fclose(fp); - return get_param(devices, value, val_len); + if (dev[0] == '*' && strlen(fs)) { + rc = snprintf(dev, sizeof(dev), "%s-*", fs); + if (rc >= sizeof(dev)) + GOTO(out, rc = -E2BIG); + } + rc = snprintf(devices, sizeof(devices), "%s/%s/%s", obd_type, dev, + param_name); + if (rc >= sizeof(devices)) + GOTO(out, rc = -E2BIG); + fclose(fp); + return get_param(devices, value, val_len); +out: + if (fp != NULL) + fclose(fp); + return rc; } /* @@ -708,7 +715,8 @@ retry_open: lum.lmm_stripe_count = stripe_count; lum.lmm_stripe_offset = stripe_offset; if (pool_name != NULL) { - strncpy(lum.lmm_pool_name, pool_name, LOV_MAXPOOLNAME); + strlcpy(lum.lmm_pool_name, pool_name, + sizeof(lum.lmm_pool_name)); } else { /* If no pool is specified at all, use V1 request */ lum.lmm_magic = LOV_USER_MAGIC_V1; @@ -792,7 +800,8 @@ int llapi_dir_set_default_lmv_stripe(const char *name, int stripe_offset, ": too large pool name: %s", name, pool_name); return -E2BIG; } - strncpy(lum.lum_pool_name, pool_name, strlen(pool_name)); + strncpy(lum.lum_pool_name, pool_name, + sizeof(lum.lum_pool_name)); } fd = open(name, O_DIRECTORY | O_RDONLY); @@ -1055,19 +1064,23 @@ int llapi_search_fsname(const char *pathname, char *fsname) path = realpath(pathname, NULL); if (path == NULL) { - char buf[PATH_MAX + 1], *ptr; - - buf[0] = 0; - if (pathname[0] != '/') { - /* Need an absolute path, but realpath() only works for - * pathnames that actually exist. We go through the - * extra hurdle of dirname(getcwd() + pathname) in - * case the relative pathname contains ".." in it. */ - if (getcwd(buf, sizeof(buf) - 1) == NULL) - return -errno; - strcat(buf, "/"); - } - strncat(buf, pathname, sizeof(buf) - strlen(buf)); + char buf[PATH_MAX], *ptr; + + buf[0] = '\0'; + if (pathname[0] != '/') { + /* Need an absolute path, but realpath() only works for + * pathnames that actually exist. We go through the + * extra hurdle of dirname(getcwd() + pathname) in + * case the relative pathname contains ".." in it. */ + if (getcwd(buf, sizeof(buf) - 2) == NULL) + return -errno; + rc = strlcat(buf, "/", sizeof(buf)); + if (rc >= sizeof(buf)) + return -E2BIG; + } + rc = strlcat(buf, pathname, sizeof(buf)); + if (rc >= sizeof(buf)) + return -E2BIG; path = realpath(buf, NULL); if (path == NULL) { ptr = strrchr(buf, '/'); @@ -1163,20 +1176,20 @@ static int poolpath(char *fsname, char *pathname, char *pool_pathname) int llapi_get_poolmembers(const char *poolname, char **members, int list_size, char *buffer, int buffer_size) { - char fsname[PATH_MAX + 1]; - char *pool, *tmp; - char pathname[PATH_MAX + 1]; - char path[PATH_MAX + 1]; - char buf[1024]; + char fsname[PATH_MAX]; + char *pool, *tmp; + char pathname[PATH_MAX]; + char path[PATH_MAX]; + char buf[1024]; FILE *fd; int rc = 0; int nb_entries = 0; int used = 0; /* name is FSNAME.POOLNAME */ - if (strlen(poolname) > PATH_MAX) - return -EOVERFLOW; - strcpy(fsname, poolname); + if (strlen(poolname) >= sizeof(fsname)) + return -EOVERFLOW; + strlcpy(fsname, poolname, sizeof(fsname)); pool = strchr(fsname, '.'); if (pool == NULL) return -EINVAL; @@ -1193,7 +1206,9 @@ int llapi_get_poolmembers(const char *poolname, char **members, } llapi_printf(LLAPI_MSG_NORMAL, "Pool: %s.%s\n", fsname, pool); - sprintf(path, "%s/%s", pathname, pool); + rc = snprintf(path, sizeof(path), "%s/%s", pathname, pool); + if (rc >= sizeof(path)) + return -EOVERFLOW; fd = fopen(path, "r"); if (fd == NULL) { rc = -errno; @@ -1207,6 +1222,7 @@ int llapi_get_poolmembers(const char *poolname, char **members, rc = -EOVERFLOW; break; } + buf[sizeof(buf) - 1] = '\0'; /* remove '\n' */ tmp = strchr(buf, '\n'); if (tmp != NULL) @@ -1351,8 +1367,14 @@ int llapi_poollist(const char *name) int obdcount, bufsize, rc, nb, i; char *poolname = NULL, *tmp = NULL, data[16]; - if (name[0] != '/') { - fsname = strdup(name); + if (name == NULL) + return -EINVAL; + + if (name[0] != '/') { + fsname = strdup(name); + if (fsname == NULL) + return -ENOMEM; + poolname = strchr(fsname, '.'); if (poolname) *poolname = '\0'; @@ -1513,7 +1535,7 @@ static int get_lmd_info(char *path, DIR *parent, DIR *dir, fname = (fname == NULL ? path : fname + 1); /* retrieve needed file info */ - strncpy((char *)lmd, fname, lumlen); + strlcpy((char *)lmd, fname, lumlen); ret = ioctl(dirfd(parent), IOC_MDC_GETFILEINFO, (void *)lmd); } @@ -1672,7 +1694,7 @@ static int param_callback(char *path, semantic_func_t sem_init, if (!buf) return -ENOMEM; - strncpy(buf, path, PATH_MAX + 1); + strlcpy(buf, path, PATH_MAX + 1); ret = common_param_init(param, buf); if (ret) goto out; @@ -2073,7 +2095,7 @@ static int clilovpath(const char *fsname, const char *const pathname, if (rc != 0) return rc; - strncpy(clilovpath, buffer, sizeof(buffer)); + strlcpy(clilovpath, buffer, sizeof(buffer)); return 0; } @@ -2181,10 +2203,10 @@ static int sattr_cache_get_defaults(const char *const fsname, if (rc) return rc; } else { - strncpy(fsname_buf, fsname, PATH_MAX); + strlcpy(fsname_buf, fsname, sizeof(fsname_buf)); } - if (strncmp(fsname_buf, cache.fsname, PATH_MAX) != 0) { + if (strncmp(fsname_buf, cache.fsname, sizeof(fsname_buf) - 1) != 0) { /* * Ensure all 3 sattrs (count, size, and offset) are * successfully retrieved and stored in tmp before writing to @@ -2198,7 +2220,7 @@ static int sattr_cache_get_defaults(const char *const fsname, cache.stripecount = tmp[0]; cache.stripesize = tmp[1]; cache.stripeoffset = tmp[2]; - strncpy(cache.fsname, fsname_buf, PATH_MAX); + strlcpy(cache.fsname, fsname_buf, sizeof(cache.fsname)); } if (scount) @@ -2498,8 +2520,7 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) struct lov_user_ost_data_v1 *objects; struct lov_user_md_v3 *lmmv3 = (void *)¶m->lmd->lmd_lmm; - strncpy(pool_name, lmmv3->lmm_pool_name, LOV_MAXPOOLNAME); - pool_name[LOV_MAXPOOLNAME] = '\0'; + strlcpy(pool_name, lmmv3->lmm_pool_name, sizeof(pool_name)); objects = lmmv3->lmm_objects; lov_dump_user_lmm_v1v3(¶m->lmd->lmd_lmm, pool_name, objects, path, is_dir, @@ -2513,7 +2534,7 @@ void llapi_lov_dump_user_lmm(struct find_param *param, char *path, int is_dir) struct lmv_user_md *lum; lum = (struct lmv_user_md *)param->fp_lmv_md; - strncpy(pool_name, lum->lum_pool_name, LOV_MAXPOOLNAME); + strlcpy(pool_name, lum->lum_pool_name, sizeof(pool_name)); lmv_dump_user_lmm(lum, pool_name, path, param->obdindex, param->fp_max_depth, param->verbose); @@ -3302,7 +3323,7 @@ static int cb_getstripe(char *path, DIR *parent, DIR **dirp, void *data, char *fname = strrchr(path, '/'); fname = (fname == NULL ? path : fname + 1); - strncpy((char *)¶m->lmd->lmd_lmm, fname, param->lumlen); + strlcpy((char *)¶m->lmd->lmd_lmm, fname, param->lumlen); ret = ioctl(dirfd(parent), IOC_MDC_GETFILESTRIPE, (void *)¶m->lmd->lmd_lmm); diff --git a/lustre/utils/liblustreapi_json.c b/lustre/utils/liblustreapi_json.c index b4f0882..10e8e76 100644 --- a/lustre/utils/liblustreapi_json.c +++ b/lustre/utils/liblustreapi_json.c @@ -257,6 +257,7 @@ int llapi_json_add_item(struct llapi_json_item_list **json_items, { struct llapi_json_item_list *list; struct llapi_json_item *new_item; + size_t len; if (json_items == NULL || *json_items == NULL) return -EINVAL; @@ -270,11 +271,12 @@ int llapi_json_add_item(struct llapi_json_item_list **json_items, if (new_item == NULL) return -ENOMEM; - new_item->lji_key = calloc(1, strlen(key) + 1); + len = strlen(key) + 1; + new_item->lji_key = calloc(len, sizeof(char)); if (new_item->lji_key == NULL) return -ENOMEM; - strncpy(new_item->lji_key, key, strlen(key)); + strlcpy(new_item->lji_key, key, len); new_item->lji_type = type; new_item->lji_next = NULL; @@ -289,11 +291,11 @@ int llapi_json_add_item(struct llapi_json_item_list **json_items, new_item->lji_real = *(double *)val; break; case LLAPI_JSON_STRING: - new_item->lji_string = calloc(1, strlen((char *)val) + 1); + len = strlen((char *)val) + 1; + new_item->lji_string = calloc(len, sizeof(char)); if (new_item->lji_string == NULL) return -ENOMEM; - strncpy(new_item->lji_string, - (char *)val, strlen((char *)val)); + strlcpy(new_item->lji_string, (char *)val, len); break; default: llapi_err_noerrno(LLAPI_MSG_ERROR, "Unknown JSON type: %d", diff --git a/lustre/utils/ltrack_stats.c b/lustre/utils/ltrack_stats.c index 4984a46..8d73a21 100644 --- a/lustre/utils/ltrack_stats.c +++ b/lustre/utils/ltrack_stats.c @@ -389,7 +389,7 @@ void fork_command(int type, unsigned short id, char* command, char* llstat_file) int with_llstat = 1; int status; char stats_path[1024]; - char stats_path_temp[1024]; + char stats_path_temp[1024 + 6]; /* 6=strlen("/stats") */ if (strlen(llstat_file) == 0) with_llstat = 0; @@ -411,7 +411,7 @@ void fork_command(int type, unsigned short id, char* command, char* llstat_file) if (with_llstat) { /* comment #25 of BUG 10968 */ - sleep(2); + sleep(2); /* sending kill to all llstat commands created for each * lustre-client respectively */ diff --git a/lustre/utils/lustre_rsync.c b/lustre/utils/lustre_rsync.c index 113dc04..dee27b0 100644 --- a/lustre/utils/lustre_rsync.c +++ b/lustre/utils/lustre_rsync.c @@ -569,10 +569,9 @@ int lr_get_symlink(struct lr_info *info) } else { link = info->linktmp; } - strncpy(info->link, link, PATH_MAX); - info->link[PATH_MAX] = '\0'; + strlcpy(info->link, link, sizeof(info->link)); - return rc; + return rc; } /* Create file/directory/device file/symlink. */ @@ -628,24 +627,25 @@ int lr_mkfile(struct lr_info *info) int lr_add_pc(const char *pfid, const char *tfid, const char *name) { - struct lr_parent_child_list *p; - - p = calloc(1, sizeof(*p)); - if (!p) - return -ENOMEM; - if (strlen(pfid) > sizeof(p->pc_log.pcl_pfid)-1) + struct lr_parent_child_list *p; + size_t len; + + p = calloc(1, sizeof(*p)); + if (p == NULL) + return -ENOMEM; + len = strlcpy(p->pc_log.pcl_pfid, pfid, sizeof(p->pc_log.pcl_pfid)); + if (len >= sizeof(p->pc_log.pcl_pfid)) goto out_err; - strncpy(p->pc_log.pcl_pfid, pfid, sizeof(p->pc_log.pcl_pfid)); - if (strlen(tfid) > sizeof(p->pc_log.pcl_tfid)-1) + len = strlcpy(p->pc_log.pcl_tfid, tfid, sizeof(p->pc_log.pcl_tfid)); + if (len >= sizeof(p->pc_log.pcl_tfid)) goto out_err; - strncpy(p->pc_log.pcl_tfid, tfid, sizeof(p->pc_log.pcl_tfid)); - if (strlen(name) > sizeof(p->pc_log.pcl_name)-1) + len = strlcpy(p->pc_log.pcl_name, name, sizeof(p->pc_log.pcl_name)); + if (len >= sizeof(p->pc_log.pcl_name)) goto out_err; - strncpy(p->pc_log.pcl_name, name, sizeof(p->pc_log.pcl_name)); - p->pc_next = parents; - parents = p; - return 0; + p->pc_next = parents; + parents = p; + return 0; out_err: free(p); @@ -1121,7 +1121,8 @@ int lr_parse_line(void *priv, struct lr_info *info) info->type = rec->cr_type; sprintf(info->tfid, DFID, PFID(&rec->cr_tfid)); sprintf(info->pfid, DFID, PFID(&rec->cr_pfid)); - strncpy(info->name, rec->cr_name, rec->cr_namelen); + strncpy(info->name, rec->cr_name, rec->cr_namelen); + info->name[rec->cr_namelen] = '\0'; if (fid_is_sane(&rec->cr_sfid)) { sprintf(info->sfid, DFID, PFID(&rec->cr_sfid)); @@ -1134,8 +1135,6 @@ int lr_parse_line(void *priv, struct lr_info *info) printf("Rec %lld: %d %s %s\n", info->recno, info->type, info->name, info->sname); } else { - info->name[rec->cr_namelen] = '\0'; - if (verbose > 1) printf("Rec %lld: %d %s\n", info->recno, info->type, info->name); @@ -1281,20 +1280,21 @@ int lr_read_log() if (status->ls_last_recno == -1) status->ls_last_recno = s->ls_last_recno; - if (status->ls_registration[0] == '\0') - strncpy(status->ls_registration, s->ls_registration, - LR_NAME_MAXLEN); + if (status->ls_registration[0] == '\0') + strlcpy(status->ls_registration, s->ls_registration, + sizeof(status->ls_registration)); - if (status->ls_mdt_device[0] == '\0') - strncpy(status->ls_mdt_device, s->ls_mdt_device, - LR_NAME_MAXLEN); + if (status->ls_mdt_device[0] == '\0') + strlcpy(status->ls_mdt_device, s->ls_mdt_device, + sizeof(status->ls_mdt_device)); - if (status->ls_source_fs[0] == '\0') - strncpy(status->ls_source_fs, s->ls_source_fs, - LR_NAME_MAXLEN); + if (status->ls_source_fs[0] == '\0') + strlcpy(status->ls_source_fs, s->ls_source_fs, + sizeof(status->ls_source_fs)); - if (status->ls_source[0] == '\0') - strncpy(status->ls_source, s->ls_source, PATH_MAX); + if (status->ls_source[0] == '\0') + strlcpy(status->ls_source, s->ls_source, + sizeof(status->ls_source)); out: if (fd != -1) @@ -1308,9 +1308,9 @@ int lr_read_log() processing. */ int lr_clear_cl(struct lr_info *info, int force) { - char mdt_device[LR_NAME_MAXLEN + 1]; - long long rec; - int rc = 0; + char mdt_device[LR_NAME_MAXLEN + 1]; + long long rec; + int rc = 0; if (force || info->recno > status->ls_last_recno + CLEAR_INTERVAL) { if (info->type == CL_RENAME) @@ -1322,8 +1322,8 @@ int lr_clear_cl(struct lr_info *info, int force) * device name so make a copy of it until this * is fixed. */ - strncpy(mdt_device, status->ls_mdt_device, - LR_NAME_MAXLEN); + strlcpy(mdt_device, status->ls_mdt_device, + sizeof(mdt_device)); rc = llapi_changelog_clear(mdt_device, status->ls_registration, rec); @@ -1495,8 +1495,8 @@ int lr_replicate() memcpy(info->spfid, info->pfid, sizeof(info->spfid)); memcpy(info->tfid, ext->tfid, sizeof(info->tfid)); memcpy(info->pfid, ext->pfid, sizeof(info->pfid)); - strncpy(info->sname, info->name, sizeof(info->sname)); - strncpy(info->name, ext->name, sizeof(info->name)); + strlcpy(info->sname, info->name, sizeof(info->sname)); + strlcpy(info->name, ext->name, sizeof(info->name)); info->is_extended = 1; } @@ -1603,7 +1603,8 @@ int main(int argc, char *argv[]) break; case 's': /* Assume absolute paths */ - strncpy(status->ls_source, optarg, PATH_MAX); + strlcpy(status->ls_source, optarg, + sizeof(status->ls_source)); break; case 't': status->ls_num_targets++; @@ -1624,16 +1625,16 @@ int main(int argc, char *argv[]) if (status == NULL) return -ENOMEM; } - strncpy(status->ls_targets[status->ls_num_targets - 1], - optarg, - PATH_MAX); - break; - case 'm': - strncpy(status->ls_mdt_device, optarg, LR_NAME_MAXLEN); - break; - case 'u': - strncpy(status->ls_registration, optarg, - LR_NAME_MAXLEN); + strlcpy(status->ls_targets[status->ls_num_targets - 1], + optarg, sizeof(status->ls_targets[0])); + break; + case 'm': + strlcpy(status->ls_mdt_device, optarg, + sizeof(status->ls_mdt_device)); + break; + case 'u': + strlcpy(status->ls_registration, optarg, + sizeof(status->ls_registration)); break; case 'l': statuslog = optarg; diff --git a/lustre/utils/mount_utils.c b/lustre/utils/mount_utils.c index 8054b07..83a571f 100644 --- a/lustre/utils/mount_utils.c +++ b/lustre/utils/mount_utils.c @@ -450,7 +450,7 @@ struct module_backfs_ops *load_backfs_module(enum ldd_mount_type mount_type) /* This deals with duplicate ldd_mount_types resolving to same OSD layer * plugin (e.g. ext3/ldiskfs/ldiskfs2 all being ldiskfs) */ - strncpy(fsname, mt_type(mount_type), sizeof(fsname)); + strlcpy(fsname, mt_type(mount_type), sizeof(fsname)); name = fsname + sizeof("osd-") - 1; /* change osd- to osd_ */ diff --git a/lustre/utils/mount_utils_ldiskfs.c b/lustre/utils/mount_utils_ldiskfs.c index 9e1ec14..3815d72 100644 --- a/lustre/utils/mount_utils_ldiskfs.c +++ b/lustre/utils/mount_utils_ldiskfs.c @@ -639,6 +639,7 @@ static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor, */ static char *moveopts_to_end(char *start) { + size_t len; char save[512]; char *end, *idx; @@ -651,9 +652,13 @@ static char *moveopts_to_end(char *start) while (*end != ' ' && *end != '\0') ++end; + len = end - start; + if (len >= sizeof(save)) + len = sizeof(save) - 1; + /* save options */ - strncpy(save, start, end - start); - save[end - start] = '\0'; + strncpy(save, start, len); + save[len] = '\0'; /* move remaining options up front */ if (*end) -- 1.8.3.1