diff options
author | Zach Brown <zab@redhat.com> | 2013-01-17 15:23:10 -0800 |
---|---|---|
committer | Zach Brown <zab@redhat.com> | 2013-02-05 16:09:38 -0800 |
commit | 9e4ad990992ebb588c599832d8d7dc0fe2a37475 (patch) | |
tree | dc0e0f8b355c09da5ff2a171089f70391a7e8da0 /kerncompat.h | |
parent | 968efc6f988623aff2b4c21af8317ec80836a4b9 (diff) |
btrfs-progs: use ftw() unstead of system("du")
size_sourcedir() uses shockingly bad code to try and estimate the size
of the files and directories in a subtree.
- Its use of snprintf(), strcat(), and sscanf() with arbitrarily small
on-stack buffers manages to overflow the stack a few times when given
long file names.
$ BIG=$(perl -e 'print "a" x 200')
$ mkdir -p /tmp/$BIG/$BIG/$BIG/$BIG/$BIG
$ mkfs.btrfs /tmp/img -r /tmp/$BIG/$BIG/$BIG/$BIG/$BIG
*** stack smashing detected ***: mkfs.btrfs terminated
- It passes raw paths to system() allowing interpreting file names as
shell control characters.
$ mkfs.btrfs /tmp/img -r /tmp/spacey\ dir/
du: cannot access `/tmp/spacey': No such file or directory
du: cannot access `dir/': No such file or directory
- It redirects du output to "temp_file" in the current directory,
allowing overwriting of files through symlinks.
$ echo hi > target
$ ln -s target temp_file
$ mkfs.btrfs /tmp/img -r /tmp/somedir/
$ cat target
3 /tmp/somedir/
This fixes the worst problems while maintaining -r functionality by
tearing out the system() code and using ftw() to walk the source tree
and sum up st.st_size.
Signed-off-by: Zach Brown <zab@redhat.com>
Diffstat (limited to 'kerncompat.h')
-rw-r--r-- | kerncompat.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/kerncompat.h b/kerncompat.h index a38a9b06..c18fdf3e 100644 --- a/kerncompat.h +++ b/kerncompat.h @@ -203,6 +203,16 @@ static inline long IS_ERR(const void *ptr) ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; }) /* + * This looks more complex than it should be. But we need to + * get the type for the ~ right in round_down (it needs to be + * as wide as the result!), and we want to evaluate the macro + * arguments just once each. + */ +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) + +/* * printk */ #define printk(fmt, args...) fprintf(stderr, fmt, ##args) |