btrfs-progs: fix overflow in btrfs_scan_one_dir()

btrfs_scan_one_dir() can overflow an arbitrarily small 256 byte buffer
with an arbitrarily slightly larger 1024 byte buffer as it remembers the
path of a dir to later descend.

Make these buffers the same size to stop the overflow and chose PATH_MAX
for that size so that it won't fail on legitimately bonkers paths.

Signed-off-by: Zach Brown <zab@redhat.com>
master
Zach Brown 2013-01-23 11:31:24 -08:00
parent 506fb87fe4
commit de763395fb
1 changed files with 4 additions and 6 deletions

10
utils.c
View File

@ -922,7 +922,7 @@ int get_mountpt(char *dev, char *mntpt, size_t size)
struct pending_dir { struct pending_dir {
struct list_head list; struct list_head list;
char name[256]; char name[PATH_MAX];
}; };
void btrfs_register_one_device(char *fname) void btrfs_register_one_device(char *fname)
@ -958,7 +958,6 @@ int btrfs_scan_one_dir(char *dirname, int run_ioctl)
int ret; int ret;
int fd; int fd;
int dirname_len; int dirname_len;
int pathlen;
char *fullpath; char *fullpath;
struct list_head pending_list; struct list_head pending_list;
struct btrfs_fs_devices *tmp_devices; struct btrfs_fs_devices *tmp_devices;
@ -973,8 +972,7 @@ int btrfs_scan_one_dir(char *dirname, int run_ioctl)
again: again:
dirname_len = strlen(pending->name); dirname_len = strlen(pending->name);
pathlen = 1024; fullpath = malloc(PATH_MAX);
fullpath = malloc(pathlen);
dirname = pending->name; dirname = pending->name;
if (!fullpath) { if (!fullpath) {
@ -993,11 +991,11 @@ again:
break; break;
if (dirent->d_name[0] == '.') if (dirent->d_name[0] == '.')
continue; continue;
if (dirname_len + strlen(dirent->d_name) + 2 > pathlen) { if (dirname_len + strlen(dirent->d_name) + 2 > PATH_MAX) {
ret = -EFAULT; ret = -EFAULT;
goto fail; goto fail;
} }
snprintf(fullpath, pathlen, "%s/%s", dirname, dirent->d_name); snprintf(fullpath, PATH_MAX, "%s/%s", dirname, dirent->d_name);
ret = lstat(fullpath, &st); ret = lstat(fullpath, &st);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "failed to stat %s\n", fullpath); fprintf(stderr, "failed to stat %s\n", fullpath);