Date: Sat, 29 Dec 2007 14:09:14 +0100 (CET) From: Antoine Brodin <antoine.brodin@laposte.net> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/119129: __stack_chk_guard setup is bogus in src/lib/libc/sys/stack_protector.c Message-ID: <200712291309.lBTD9EAG019604@peanut.dreadbsd.org> Resent-Message-ID: <200712291310.lBTDA1rM030145@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712291309.lBTD9EAG019604>