bin/119129: __stack_chk_guard setup is bogus in
src/lib/libc/sys/stack_protector.c
Antoine Brodin
antoine.brodin at laposte.net
Sat Dec 29 05:10:02 PST 2007
>Number: 119129
>Category: bin
>Synopsis: __stack_chk_guard setup is bogus in src/lib/libc/sys/stack_protector.c
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Dec 29 13:10:01 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator: Antoine Brodin
>Release: FreeBSD 8.0-CURRENT i386
>Organization:
none
>Environment:
System: FreeBSD barton.dreadbsd.org. 8.0-CURRENT FreeBSD 8.0-CURRENT #0: Mon Dec 3 17:11:47 CET 2007 root at barton.dreadbsd.org.:/usr/obj/usr/src/sys/BARTON i386
>Description:
When compiling with -fstack-protector-all and executing a binary,
__stack_chk_guard is always initialized to 0xff0a0000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000.
(at least on i386).
>How-To-Repeat:
%%%
cat > b.c << EOF
#include <stdio.h>
extern long __stack_chk_guard[8];
int
main(void)
{
int i;
for (i = 0; i < 8; i++)
printf("%lx\n", __stack_chk_guard[i]);
return 0;
}
EOF
gcc -fstack-protector-all b.c
./a.out
%%%
It gives:
./a.out
ff0a0000
0
0
0
0
0
0
0
Where is the problem ?
The length returned by sysctl(mib, 2, __stack_chk_guard, &len, NULL, 0)
is not sizeof(__stack_chk_guard) so the default canary is used:
%%%
cat > a.c << EOF
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
int
main(void)
{
long stack_chk_guard[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int mib[2];
size_t len;
int i, ret;
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
len = sizeof(stack_chk_guard);
ret = sysctl(mib, 2, stack_chk_guard, &len, NULL, 0);
if (ret == -1)
printf("-1\n");
if (len != sizeof(stack_chk_guard))
printf("%d != %d\n", len, sizeof(stack_chk_guard));
if (ret == -1 || len != sizeof(stack_chk_guard))
{
((unsigned char *)(void *)stack_chk_guard)[0] = 0;
((unsigned char *)(void *)stack_chk_guard)[1] = 0;
((unsigned char *)(void *)stack_chk_guard)[2] = '\n';
((unsigned char *)(void *)stack_chk_guard)[3] = 255;
}
for (i = 0; i < 8; i++)
printf("%lx\n", stack_chk_guard[i]);
return 0;
}
EOF
gcc a.c
./a.out
%%%
It gives:
./a.out
4 != 32
ff0a0000
0
0
0
0
0
0
0
>Fix:
There is a bug in either src/lib/libc/sys/stack_protector.c:__guard_setup(),
or in src/sys/kern/kern_mib.c:sysctl_kern_arnd().
sysctl_kern_arnd() generates a random long, while __guard_setup assumes it
generates a random buffer.
On OpenBSD, src/lib/libc/sys/stack_protector.c is the same but
src/sys/kern/kern_sysctl.c initializes a buffer for KERN_ARND
( http://fxr.watson.org/fxr/source//kern/kern_sysctl.c?v=OPENBSD#L394 )
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list