btrfs-progs: use strncpy_null everywhere

Use the safe version of strncpy that makes sure the string is
terminated.

To be noted:

- the conversion in scrub path handling was skipped
- sizes of device paths in some ioctl related structures is
  BTRFS_DEVICE_PATH_NAME_MAX + 1

Recently gcc 13.3 started to detect problems with our use of strncpy
potentially lacking the null terminator, warnings like:

cmds/inspect.c: In function ‘cmd_inspect_logical_resolve’:
cmds/inspect.c:294:33: warning: ‘__builtin_strncpy’ specified bound 4096 equals destination size [-Wstringop-truncation]
  294 |                                 strncpy(mount_path, mounted, PATH_MAX);
      |                                 ^

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2024-06-17 20:56:38 +02:00
parent e673aa22bc
commit 4db925911c
13 changed files with 28 additions and 32 deletions

View File

@ -1398,7 +1398,7 @@ int main(int argc, char **argv)
inode = arg_strtou64(optarg); inode = arg_strtou64(optarg);
break; break;
case 'f': case 'f':
strncpy(field, optarg, FIELD_BUF_LEN); strncpy_null(field, optarg, FIELD_BUF_LEN);
break; break;
case 'x': case 'x':
file_extent = arg_strtou64(optarg); file_extent = arg_strtou64(optarg);

View File

@ -799,9 +799,8 @@ static int cmd_device_stats(const struct cmd_struct *cmd, int argc, char **argv)
char path[BTRFS_DEVICE_PATH_NAME_MAX + 1]; char path[BTRFS_DEVICE_PATH_NAME_MAX + 1];
int err2; int err2;
strncpy(path, (char *)di_args[i].path, strncpy_null(path, (char *)di_args[i].path,
BTRFS_DEVICE_PATH_NAME_MAX); BTRFS_DEVICE_PATH_NAME_MAX + 1);
path[BTRFS_DEVICE_PATH_NAME_MAX] = 0;
args.devid = di_args[i].devid; args.devid = di_args[i].devid;
args.nr_items = BTRFS_DEV_STAT_VALUES_MAX; args.nr_items = BTRFS_DEV_STAT_VALUES_MAX;

View File

@ -258,7 +258,7 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
if (name[0] == 0) { if (name[0] == 0) {
path_ptr[-1] = '\0'; path_ptr[-1] = '\0';
path_fd = fd; path_fd = fd;
strncpy(mount_path, full_path, PATH_MAX); strncpy_null(mount_path, full_path, PATH_MAX);
} else { } else {
char *mounted = NULL; char *mounted = NULL;
char subvol[PATH_MAX]; char subvol[PATH_MAX];
@ -291,7 +291,7 @@ static int cmd_inspect_logical_resolve(const struct cmd_struct *cmd,
continue; continue;
} }
strncpy(mount_path, mounted, PATH_MAX); strncpy_null(mount_path, mounted, PATH_MAX);
free(mounted); free(mounted);
path_fd = btrfs_open_dir(mount_path); path_fd = btrfs_open_dir(mount_path);

View File

@ -266,8 +266,8 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
goto leave_with_error; goto leave_with_error;
} }
} else if (path_is_block_device(srcdev) > 0) { } else if (path_is_block_device(srcdev) > 0) {
strncpy((char *)start_args.start.srcdev_name, srcdev, strncpy_null((char *)start_args.start.srcdev_name, srcdev,
BTRFS_DEVICE_PATH_NAME_MAX); BTRFS_DEVICE_PATH_NAME_MAX + 1);
start_args.start.srcdevid = 0; start_args.start.srcdevid = 0;
srcdev_size = device_get_partition_size(srcdev); srcdev_size = device_get_partition_size(srcdev);
} else { } else {
@ -292,8 +292,8 @@ static int cmd_replace_start(const struct cmd_struct *cmd,
goto leave_with_error; goto leave_with_error;
} }
strncpy((char *)start_args.start.tgtdev_name, dstdev, strncpy_null((char *)start_args.start.tgtdev_name, dstdev,
BTRFS_DEVICE_PATH_NAME_MAX); BTRFS_DEVICE_PATH_NAME_MAX + 1);
ret = btrfs_prepare_device(fddstdev, dstdev, &dstdev_block_count, 0, ret = btrfs_prepare_device(fddstdev, dstdev, &dstdev_block_count, 0,
PREP_DEVICE_ZERO_END | PREP_DEVICE_VERBOSE | PREP_DEVICE_ZERO_END | PREP_DEVICE_VERBOSE |
(discard ? PREP_DEVICE_DISCARD : 0) | (discard ? PREP_DEVICE_DISCARD : 0) |

View File

@ -1535,8 +1535,7 @@ static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv)
ret = 1; ret = 1;
goto out; goto out;
} }
strncpy(dir_name, argv[optind + 1], sizeof dir_name); strncpy_null(dir_name, argv[optind + 1], sizeof(dir_name));
dir_name[sizeof dir_name - 1] = 0;
/* Strip the trailing / on the dir name */ /* Strip the trailing / on the dir name */
len = strlen(dir_name); len = strlen(dir_name);

View File

@ -1437,7 +1437,7 @@ static int scrub_start(const struct cmd_struct *cmd, int argc, char **argv,
sock_path, sizeof(sock_path)); sock_path, sizeof(sock_path));
/* ignore EOVERFLOW, try using a shorter path for the socket */ /* ignore EOVERFLOW, try using a shorter path for the socket */
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1); strncpy_null(addr.sun_path, sock_path, sizeof(addr.sun_path));
ret = bind(prg_fd, (struct sockaddr *)&addr, sizeof(addr)); ret = bind(prg_fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret != -1 || errno != EADDRINUSE) if (ret != -1 || errno != EADDRINUSE)
break; break;

View File

@ -547,8 +547,7 @@ static int update_root(struct rb_root *root_lookup,
error_msg(ERROR_MSG_MEMORY, NULL); error_msg(ERROR_MSG_MEMORY, NULL);
exit(1); exit(1);
} }
strncpy(ri->name, name, name_len); strncpy_null(ri->name, name, name_len);
ri->name[name_len] = 0;
} }
if (ref_tree) if (ref_tree)
ri->ref_tree = ref_tree; ri->ref_tree = ref_tree;
@ -619,8 +618,7 @@ static int add_root(struct rb_root *root_lookup,
error_msg(ERROR_MSG_MEMORY, NULL); error_msg(ERROR_MSG_MEMORY, NULL);
exit(1); exit(1);
} }
strncpy(ri->name, name, name_len); strncpy_null(ri->name, name, name_len);
ri->name[name_len] = 0;
} }
if (ref_tree) if (ref_tree)
ri->ref_tree = ref_tree; ri->ref_tree = ref_tree;

View File

@ -47,8 +47,7 @@ void fixup_argv0(char **argv, const char *token)
void set_argv0(char **argv) void set_argv0(char **argv)
{ {
strncpy(argv0_buf, argv[0], sizeof(argv0_buf)); strncpy_null(argv0_buf, argv[0], sizeof(argv0_buf));
argv0_buf[sizeof(argv0_buf) - 1] = 0;
} }
int check_argc_exact(int nargs, int expected) int check_argc_exact(int nargs, int expected)

View File

@ -32,6 +32,7 @@
#include "common/messages.h" #include "common/messages.h"
#include "common/path-utils.h" #include "common/path-utils.h"
#include "common/device-scan.h" #include "common/device-scan.h"
#include "common/string-utils.h"
#include "common/open-utils.h" #include "common/open-utils.h"
/* /*
@ -103,10 +104,9 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
} }
/* Did we find an entry in mnt table? */ /* Did we find an entry in mnt table? */
if (mnt && size && where) { if (mnt && size && where)
strncpy(where, mnt->mnt_dir, size); strncpy_null(where, mnt->mnt_dir, size);
where[size-1] = 0;
}
if (fs_dev_ret) if (fs_dev_ret)
*fs_dev_ret = fs_devices_mnt; *fs_dev_ret = fs_devices_mnt;
else if (noscan) else if (noscan)

View File

@ -1996,7 +1996,7 @@ int BOX_MAIN(convert)(int argc, char *argv[])
error("invalid UUID: %s\n", optarg); error("invalid UUID: %s\n", optarg);
return 1; return 1;
} }
strncpy(fsid, optarg, sizeof(fsid)); strncpy_null(fsid, optarg, sizeof(fsid));
} }
break; break;
case GETOPT_VAL_HELP: case GETOPT_VAL_HELP:

View File

@ -30,6 +30,7 @@
#include "kernel-shared/file-item.h" #include "kernel-shared/file-item.h"
#include "common/extent-cache.h" #include "common/extent-cache.h"
#include "common/messages.h" #include "common/messages.h"
#include "common/string-utils.h"
#include "convert/common.h" #include "convert/common.h"
#include "convert/source-fs.h" #include "convert/source-fs.h"
#include "convert/source-ext2.h" #include "convert/source-ext2.h"
@ -638,7 +639,7 @@ static int ext2_copy_single_xattr(struct btrfs_trans_handle *trans,
data = databuf; data = databuf;
datalen = bufsize; datalen = bufsize;
} }
strncpy(namebuf, xattr_prefix_table[name_index], XATTR_NAME_MAX); strncpy_null(namebuf, xattr_prefix_table[name_index], XATTR_NAME_MAX);
strncat(namebuf, EXT2_EXT_ATTR_NAME(entry), entry->e_name_len); strncat(namebuf, EXT2_EXT_ATTR_NAME(entry), entry->e_name_len);
if (name_len + datalen > BTRFS_LEAF_DATA_SIZE(root->fs_info) - if (name_len + datalen > BTRFS_LEAF_DATA_SIZE(root->fs_info) -
sizeof(struct btrfs_item) - sizeof(struct btrfs_dir_item)) { sizeof(struct btrfs_item) - sizeof(struct btrfs_dir_item)) {

View File

@ -36,6 +36,7 @@
#include "common/defs.h" #include "common/defs.h"
#include "common/internal.h" #include "common/internal.h"
#include "common/messages.h" #include "common/messages.h"
#include "common/string-utils.h"
#include "uapi/btrfs.h" #include "uapi/btrfs.h"
static void print_dir_item_type(struct extent_buffer *eb, static void print_dir_item_type(struct extent_buffer *eb,
@ -186,7 +187,7 @@ static void bg_flags_to_str(u64 flags, char *ret)
ret[0] = '\0'; ret[0] = '\0';
if (flags & BTRFS_BLOCK_GROUP_DATA) { if (flags & BTRFS_BLOCK_GROUP_DATA) {
empty = 0; empty = 0;
strncpy(ret, "DATA", BG_FLAG_STRING_LEN); strncpy_null(ret, "DATA", BG_FLAG_STRING_LEN);
} }
if (flags & BTRFS_BLOCK_GROUP_METADATA) { if (flags & BTRFS_BLOCK_GROUP_METADATA) {
if (!empty) if (!empty)
@ -209,7 +210,7 @@ static void bg_flags_to_str(u64 flags, char *ret)
* Thus here we only fill @profile if it's not single. * Thus here we only fill @profile if it's not single.
*/ */
if (strncmp(name, "SINGLE", strlen("SINGLE")) != 0) if (strncmp(name, "SINGLE", strlen("SINGLE")) != 0)
strncpy(profile, name, BG_FLAG_STRING_LEN); strncpy_null(profile, name, BG_FLAG_STRING_LEN);
} }
if (profile[0]) { if (profile[0]) {
strncat(ret, "|", BG_FLAG_STRING_LEN); strncat(ret, "|", BG_FLAG_STRING_LEN);
@ -1398,7 +1399,7 @@ static void print_header_info(struct extent_buffer *eb, unsigned int mode)
#define DEV_REPLACE_STRING_LEN 64 #define DEV_REPLACE_STRING_LEN 64
#define CASE_DEV_REPLACE_MODE_ENTRY(dest, name) \ #define CASE_DEV_REPLACE_MODE_ENTRY(dest, name) \
case BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_##name: \ case BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_##name: \
strncpy((dest), #name, DEV_REPLACE_STRING_LEN); \ strncpy_null((dest), #name, DEV_REPLACE_STRING_LEN); \
break; break;
static void replace_mode_to_str(u64 flags, char *ret) static void replace_mode_to_str(u64 flags, char *ret)
@ -1415,7 +1416,7 @@ static void replace_mode_to_str(u64 flags, char *ret)
#define CASE_DEV_REPLACE_STATE_ENTRY(dest, name) \ #define CASE_DEV_REPLACE_STATE_ENTRY(dest, name) \
case BTRFS_IOCTL_DEV_REPLACE_STATE_##name: \ case BTRFS_IOCTL_DEV_REPLACE_STATE_##name: \
strncpy((dest), #name, DEV_REPLACE_STRING_LEN); \ strncpy_null((dest), #name, DEV_REPLACE_STRING_LEN); \
break; break;
static void replace_state_to_str(u64 flags, char *ret) static void replace_state_to_str(u64 flags, char *ret)

View File

@ -1361,8 +1361,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
source_dir = strdup(optarg); source_dir = strdup(optarg);
break; break;
case 'U': case 'U':
strncpy(fs_uuid, optarg, strncpy_null(fs_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE);
BTRFS_UUID_UNPARSED_SIZE - 1);
break; break;
case 'K': case 'K':
opt_discard = false; opt_discard = false;
@ -1371,7 +1370,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
bconf_be_quiet(); bconf_be_quiet();
break; break;
case GETOPT_VAL_DEVICE_UUID: case GETOPT_VAL_DEVICE_UUID:
strncpy(dev_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE - 1); strncpy_null(dev_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE);
break; break;
case GETOPT_VAL_SHRINK: case GETOPT_VAL_SHRINK:
shrink_rootdir = true; shrink_rootdir = true;