Skip to content

Commit 404ca80

Browse files
edumazettorvalds
authored andcommitted
coredump: fix va_list corruption
A va_list needs to be copied in case it needs to be used twice. Thanks to Hugh for debugging this issue, leading to various panics. Tested: lpq84:~# echo "|/foobar12345 %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h" >/proc/sys/kernel/core_pattern 'produce_core' is simply : main() { *(int *)0 = 1;} lpq84:~# ./produce_core Segmentation fault (core dumped) lpq84:~# dmesg | tail -1 [ 614.352947] Core dump to |/foobar12345 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 (null) pipe failed Notice the last argument was replaced by a NULL (we were lucky enough to not crash, but do not try this on your production machine !) After fix : lpq83:~# echo "|/foobar12345 %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h" >/proc/sys/kernel/core_pattern lpq83:~# ./produce_core Segmentation fault lpq83:~# dmesg | tail -1 [ 740.800441] Core dump to |/foobar12345 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 pipe failed Fixes: 5fe9d8c ("coredump: cn_vprintf() has no reason to call vsnprintf() twice") Signed-off-by: Eric Dumazet <[email protected]> Diagnosed-by: Hugh Dickins <[email protected]> Acked-by: Oleg Nesterov <[email protected]> Cc: Neil Horman <[email protected]> Cc: Andrew Morton <[email protected]> Cc: [email protected] # 3.11+ Signed-off-by: Linus Torvalds <[email protected]>
1 parent 6d45969 commit 404ca80

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

fs/coredump.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,15 @@ static int expand_corename(struct core_name *cn, int size)
7373
static int cn_vprintf(struct core_name *cn, const char *fmt, va_list arg)
7474
{
7575
int free, need;
76+
va_list arg_copy;
7677

7778
again:
7879
free = cn->size - cn->used;
79-
need = vsnprintf(cn->corename + cn->used, free, fmt, arg);
80+
81+
va_copy(arg_copy, arg);
82+
need = vsnprintf(cn->corename + cn->used, free, fmt, arg_copy);
83+
va_end(arg_copy);
84+
8085
if (need < free) {
8186
cn->used += need;
8287
return 0;

0 commit comments

Comments
 (0)