From jakub@redhat.com Mon Jun 13 08:36:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Mon, 13 Jun 2005 08:36:00 -0000 Subject: [PATCH] Handle MSG_TRUNC in getifaddrs/if_index Message-ID: <20050613083608.GH7663@sunsite.mff.cuni.cz> Hi! If there are many networking interfaces in a machine, 4096 bytes buffer namely for RTM_GETLINK query can be too small. ATM the calls just fail if MSG_TRUNC is seen, while the following patch handles that case by resending the request (with increased seq number) and doubling the buffer size for receive. Although I don't have that many interfaces myself (IP aliases don't count), I have tested it by decreasing the starting buf_size from 4096 to 256, so that it needs enlargement 2 times even on my box. 2005-06-13 Jakub Jelinek * sysdeps/unix/sysv/linux/netlinkaccess.h (__netlink_sendreq, __netlink_receive): Remove prototypes. (__netlink_request): New prototype. * sysdeps/unix/sysv/linux/ifaddrs.c: Include and . (__netlink_sendreq): Make static. (__netlink_receive): Rename to... (__netlink_request): ... this. Add type argument, call __netlink_sendreq. If MSG_TRUNC is set after recvmsg, retry with a bigger buffer. Don't record buffers that contain no messages we are expecting. (getifaddrs): Use __netlink_request instead of __netlink_sendreq and __netlink_receive pairs. Formatting. * sysdeps/unix/sysv/linux/if_index.c (if_nameindex_netlink): Use __netlink_request instead of __netlink_sendreq and __netlink_receive pair. --- libc/sysdeps/unix/sysv/linux/netlinkaccess.h.jj 2004-06-30 09:40:24.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/netlinkaccess.h 2005-06-11 11:26:16.000000000 +0200 @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 Free Software Foundation, Inc. +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -55,8 +55,7 @@ extern int __no_netlink_support attribut extern int __netlink_open (struct netlink_handle *h); extern void __netlink_close (struct netlink_handle *h); extern void __netlink_free_handle (struct netlink_handle *h); -extern int __netlink_sendreq (struct netlink_handle *h, int type); -extern int __netlink_receive (struct netlink_handle *h); +extern int __netlink_request (struct netlink_handle *h, int type); #endif /* netlinkaccess.h */ --- libc/sysdeps/unix/sysv/linux/if_index.c.jj 2004-07-12 17:50:25.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/if_index.c 2005-06-11 12:36:48.000000000 +0200 @@ -1,4 +1,5 @@ -/* Copyright (C) 1997,98,99,2000,2002,2003,2004 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -188,12 +189,8 @@ if_nameindex_netlink (void) /* Tell the kernel that we wish to get a list of all - active interfaces. */ - if (__netlink_sendreq (&nh, RTM_GETLINK) < 0) - goto exit_close; - - /* Collect all data for every interface. */ - if (__netlink_receive (&nh) < 0) + active interfaces. Collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) goto exit_free; /* Count the interfaces. */ @@ -290,7 +287,6 @@ if_nameindex_netlink (void) exit_free: __netlink_free_handle (&nh); - exit_close: __netlink_close (&nh); return idx; --- libc/sysdeps/unix/sysv/linux/ifaddrs.c.jj 2005-06-10 00:53:27.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/ifaddrs.c 2005-06-11 14:00:51.000000000 +0200 @@ -1,5 +1,5 @@ /* getifaddrs -- get names and addresses of all network interfaces - Copyright (C) 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,6 +17,7 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -84,7 +86,7 @@ __netlink_free_handle (struct netlink_ha } -int +static int __netlink_sendreq (struct netlink_handle *h, int type) { struct @@ -114,15 +116,37 @@ __netlink_sendreq (struct netlink_handle int -__netlink_receive (struct netlink_handle *h) +__netlink_request (struct netlink_handle *h, int type) { - struct netlink_res *nlm_next; - char buf[4096]; - struct iovec iov = { buf, sizeof (buf) }; + struct netlink_res *nlm_next, **new_nlm_list; + static size_t buf_size = 4096; + char *buf; struct sockaddr_nl nladdr; struct nlmsghdr *nlmh; - int read_len; + ssize_t read_len; bool done = false; + bool use_malloc = false; + + if (__netlink_sendreq (h, type) < 0) + return -1; + + if (! __libc_use_alloca (buf_size)) + { + buf = malloc (buf_size); + if (buf != NULL) + use_malloc = true; + else + buf = alloca (buf_size); + } + else + buf = alloca (buf_size); + + struct iovec iov = { buf, buf_size }; + + if (h->nlm_list != NULL) + new_nlm_list = &h->end_ptr->next; + else + new_nlm_list = &h->nlm_list; while (! done) { @@ -136,33 +160,66 @@ __netlink_receive (struct netlink_handle read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0)); if (read_len < 0) - return -1; + goto out_fail; - if (msg.msg_flags & MSG_TRUNC) - return -1; + if (nladdr.nl_pid != 0) + continue; - nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res) - + read_len); - if (nlm_next == NULL) - return -1; - nlm_next->next = NULL; - nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len); - nlm_next->size = read_len; - nlm_next->seq = h->seq; - if (h->nlm_list == NULL) - h->nlm_list = nlm_next; - else - h->end_ptr->next = nlm_next; - h->end_ptr = nlm_next; + if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0)) + { + if (buf_size >= SIZE_MAX / 2) + goto out_fail; + nlm_next = *new_nlm_list; + while (nlm_next != NULL) + { + struct netlink_res *tmpptr; + + tmpptr = nlm_next->next; + free (nlm_next); + nlm_next = tmpptr; + } + *new_nlm_list = NULL; + + buf_size *= 2; + if (use_malloc) + { + char *new_buf = realloc (buf, buf_size); + if (new_buf == NULL) + goto out_fail; + new_buf = buf; + } + else + { + buf = malloc (buf_size); + if (buf == NULL) + goto out_fail; + use_malloc = true; + } + + iov.iov_base = buf; + iov.iov_len = buf_size; + + /* Increase sequence number, so that we can distinguish + between old and new request messages. */ + h->seq++; + + if (__netlink_sendreq (h, type) < 0) + goto out_fail; + + continue; + } + + size_t count = 0, remaining_len = read_len; for (nlmh = (struct nlmsghdr *) buf; - NLMSG_OK (nlmh, (size_t) read_len); - nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len)) + NLMSG_OK (nlmh, remaining_len); + nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len)) { - if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != h->pid + if ((pid_t) nlmh->nlmsg_pid != h->pid || nlmh->nlmsg_seq != h->seq) continue; + ++count; if (nlmh->nlmsg_type == NLMSG_DONE) { /* We found the end, leave the loop. */ @@ -176,11 +233,38 @@ __netlink_receive (struct netlink_handle errno = EIO; else errno = -nlerr->error; - return -1; + goto out_fail; } } + + /* If there was nothing with the expected nlmsg_pid and nlmsg_seq, + there is no point to record it. */ + if (count == 0) + continue; + + nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res) + + read_len); + if (nlm_next == NULL) + goto out_fail; + nlm_next->next = NULL; + nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len); + nlm_next->size = read_len; + nlm_next->seq = h->seq; + if (h->nlm_list == NULL) + h->nlm_list = nlm_next; + else + h->end_ptr->next = nlm_next; + h->end_ptr = nlm_next; } + + if (use_malloc) + free (buf); return 0; + +out_fail: + if (use_malloc) + free (buf); + return -1; } @@ -268,7 +352,7 @@ getifaddrs (struct ifaddrs **ifap) unsigned int i, newlink, newaddr, newaddr_idx; int *map_newlink_data; size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */ - char *ifa_data_ptr; /* Pointer to the unused part of memory for + char *ifa_data_ptr; /* Pointer to the unused part of memory for ifa_data. */ int result = 0; @@ -288,28 +372,20 @@ getifaddrs (struct ifaddrs **ifap) #endif /* Tell the kernel that we wish to get a list of all - active interfaces. */ - if (__netlink_sendreq (&nh, RTM_GETLINK) < 0) - { - result = -1; - goto exit_close; - } - /* Collect all data for every interface. */ - if (__netlink_receive (&nh) < 0) + active interfaces, collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) { result = -1; goto exit_free; } - /* Now ask the kernel for all addresses which are assigned - to an interface. Since we store the addresses after the - interfaces in the list, we will later always find the - interface before the corresponding addresses. */ + to an interface and collect all data for every interface. + Since we store the addresses after the interfaces in the + list, we will later always find the interface before the + corresponding addresses. */ ++nh.seq; - if (__netlink_sendreq (&nh, RTM_GETADDR) < 0 - /* Collect all data for every interface. */ - || __netlink_receive (&nh) < 0) + if (__netlink_request (&nh, RTM_GETADDR) < 0) { result = -1; goto exit_free; @@ -327,7 +403,7 @@ getifaddrs (struct ifaddrs **ifap) continue; /* Walk through all entries we got from the kernel and look, which - message type they contain. */ + message type they contain. */ for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) { /* Check if the message is what we want. */ @@ -423,7 +499,7 @@ getifaddrs (struct ifaddrs **ifap) /* Interfaces are stored in the first "newlink" entries of our list, starting in the order as we got from the kernel. */ - ifa_index = map_newlink (ifim->ifi_index - 1, ifas, + ifa_index = map_newlink (ifim->ifi_index - 1, ifas, map_newlink_data, newlink); ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags; @@ -767,8 +843,6 @@ getifaddrs (struct ifaddrs **ifap) exit_free: __netlink_free_handle (&nh); - - exit_close: __netlink_close (&nh); return result; Jakub From jakub@redhat.com Mon Jun 13 17:14:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Mon, 13 Jun 2005 17:14:00 -0000 Subject: [PATCH] Move DT_DEBUG initialization earlier in dl_main Message-ID: <20050613171435.GI7663@sunsite.mff.cuni.cz> Hi! gdb can't debug PIE binaries without this, because it will see DT_DEBUG being NULL the first time it is notified. 2005-06-13 Jakub Jelinek * elf/rtld.c (dl_main): Move DT_DEBUG setup before first _dl_debug_state call. --- libc/elf/rtld.c.jj 2005-05-26 14:21:09.000000000 +0200 +++ libc/elf/rtld.c 2005-06-13 18:59:11.000000000 +0200 @@ -1540,6 +1540,30 @@ ERROR: ld.so: object '%s' cannot be load } } + { + struct link_map *l = main_map; + +#ifdef ELF_MACHINE_DEBUG_SETUP + + /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ + + ELF_MACHINE_DEBUG_SETUP (l, r); + ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r); + +#else + + if (l->l_info[DT_DEBUG] != NULL) + /* There is a DT_DEBUG entry in the dynamic section. Fill it in + with the run-time address of the r_debug structure */ + l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; + + /* Fill in the pointer in the dynamic linker's own dynamic section, in + case you run gdb on the dynamic linker directly. */ + if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL) + GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; +#endif + } + /* We start adding objects. */ r->r_state = RT_ADD; _dl_debug_state (); @@ -2058,30 +2082,6 @@ ERROR: ld.so: object '%s' cannot be load } - { - struct link_map *l = main_map; - -#ifdef ELF_MACHINE_DEBUG_SETUP - - /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ - - ELF_MACHINE_DEBUG_SETUP (l, r); - ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r); - -#else - - if (l->l_info[DT_DEBUG] != NULL) - /* There is a DT_DEBUG entry in the dynamic section. Fill it in - with the run-time address of the r_debug structure */ - l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; - - /* Fill in the pointer in the dynamic linker's own dynamic section, in - case you run gdb on the dynamic linker directly. */ - if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL) - GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; -#endif - } - /* Now set up the variable which helps the assembler startup code. */ GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist = &main_map->l_searchlist; GL(dl_ns)[LM_ID_BASE]._ns_global_scope[0] = &main_map->l_searchlist; Jakub From drepper@redhat.com Mon Jun 13 22:57:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Mon, 13 Jun 2005 22:57:00 -0000 Subject: [PATCH] Move DT_DEBUG initialization earlier in dl_main In-Reply-To: <20050613171435.GI7663@sunsite.mff.cuni.cz> References: <20050613171435.GI7663@sunsite.mff.cuni.cz> Message-ID: <42AE0E70.9010401@redhat.com> Applied after some cleanup. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From drepper@redhat.com Mon Jun 13 23:57:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Mon, 13 Jun 2005 23:57:00 -0000 Subject: [PATCH] Handle MSG_TRUNC in getifaddrs/if_index In-Reply-To: <20050613083608.GH7663@sunsite.mff.cuni.cz> References: <20050613083608.GH7663@sunsite.mff.cuni.cz> Message-ID: <42AE1C8C.3040708@redhat.com> I rearranged the memory handling a bit. If malloc fails and the size is know to be large, it's probably no good idea to use alloca. And in the resizing round alloca might still be a choice. Lightly tested so far but it should work. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From jakub@redhat.com Thu Jun 16 21:12:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Thu, 16 Jun 2005 21:12:00 -0000 Subject: [PATCH] Cosmetic fix for ia64 strlen [BZ #1016] Message-ID: <20050616211238.GR7663@sunsite.mff.cuni.cz> Hi! Trivial cosmetic (confuses disassembly/debugger) fix. 2005-06-16 Jakub Jelinek [BZ #1016] * sysdeps/ia64/strlen.S (strlen): Change l2 into a local label. --- libc/sysdeps/ia64/strlen.S.jj 2003-04-30 00:47:19.000000000 +0200 +++ libc/sysdeps/ia64/strlen.S 2005-06-16 23:03:40.000000000 +0200 @@ -1,6 +1,6 @@ /* Optimized version of the standard strlen() function. This file is part of the GNU C Library. - Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc. Contributed by Dan Pop . The GNU C Library is free software; you can redistribute it and/or @@ -73,7 +73,7 @@ ENTRY(strlen) ld8 val1 = [str], 8;; nop.b 0 nop.b 0 -l2: ld8.s val2 = [str], 8 // don't bomb out here +.l2: ld8.s val2 = [str], 8 // don't bomb out here czx1.r pos0 = val1 ;; cmp.ne p6, p0 = 8, pos0 @@ -81,7 +81,7 @@ l2: ld8.s val2 = [str], 8 // don't bomb chk.s val2, .recovery .back: mov val1 = val2 - br.cond.dptk l2 + br.cond.dptk .l2 .foundit: sub tmp = str, origadd // tmp = crt address - orig add len = len, pos0;; Jakub From jakub@redhat.com Mon Jun 20 09:44:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Mon, 20 Jun 2005 09:44:00 -0000 Subject: [PATCH] Add RLIMIT_NICE and RLIMIT_RTPRIO Message-ID: <20050620094434.GV7663@sunsite.mff.cuni.cz> Hi! Linux 2.6.12 added 2 new resource limits. The following patch adjusts glibc accordingly. 2005-06-20 Jakub Jelinek * sysdeps/unix/sysv/linux/bits/resource.h (RLIMIT_NICE, RLIMIT_RTPRIO): Add. (RLIMIT_NLIMITS): Adjust. * sysdeps/unix/sysv/linux/alpha/bits/resource.h (RLIMIT_NICE, RLIMIT_RTPRIO): Add. (RLIMIT_NLIMITS): Adjust. * sysdeps/unix/sysv/linux/mips/bits/resource.h (RLIMIT_NICE, RLIMIT_RTPRIO): Add. (RLIMIT_NLIMITS): Adjust. * sysdeps/unix/sysv/linux/sparc/bits/resource.h (RLIMIT_NICE, RLIMIT_RTPRIO): Add. (RLIMIT_NLIMITS): Adjust. --- libc/sysdeps/unix/sysv/linux/bits/resource.h.jj 2004-08-30 12:04:01.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/bits/resource.h 2005-06-20 11:28:33.000000000 +0200 @@ -1,5 +1,5 @@ /* Bit values & structures for resource limits. Linux version. - Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004 + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -89,7 +89,18 @@ enum __rlimit_resource __RLIMIT_MSGQUEUE = 12, #define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE - __RLIMIT_NLIMITS = 13, + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO _RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, __RLIM_NLIMITS = __RLIMIT_NLIMITS #define RLIMIT_NLIMITS __RLIMIT_NLIMITS #define RLIM_NLIMITS __RLIM_NLIMITS --- libc/sysdeps/unix/sysv/linux/alpha/bits/resource.h.jj 2004-08-30 12:04:01.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/alpha/bits/resource.h 2005-06-20 11:29:13.000000000 +0200 @@ -1,5 +1,5 @@ /* Bit values & structures for resource limits. Alpha/Linux version. - Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004 + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -89,7 +89,18 @@ enum __rlimit_resource __RLIMIT_MSGQUEUE = 12, #define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE - __RLIMIT_NLIMITS = 13, + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO _RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, __RLIM_NLIMITS = __RLIMIT_NLIMITS #define RLIMIT_NLIMITS __RLIMIT_NLIMITS #define RLIM_NLIMITS __RLIM_NLIMITS --- libc/sysdeps/unix/sysv/linux/sparc/bits/resource.h.jj 2004-08-30 12:04:08.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/sparc/bits/resource.h 2005-06-20 11:30:51.000000000 +0200 @@ -1,5 +1,5 @@ /* Bit values & structures for resource limits. Linux/SPARC version. - Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004 + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -89,7 +89,18 @@ enum __rlimit_resource __RLIMIT_MSGQUEUE = 12, #define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE - __RLIMIT_NLIMITS = 13, + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO _RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, __RLIM_NLIMITS = __RLIMIT_NLIMITS #define RLIMIT_NLIMITS __RLIMIT_NLIMITS #define RLIM_NLIMITS __RLIM_NLIMITS --- libc/sysdeps/unix/sysv/linux/mips/bits/resource.h.jj 2004-08-30 12:04:04.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/mips/bits/resource.h 2005-06-20 11:33:09.000000000 +0200 @@ -1,5 +1,5 @@ /* Bit values & structures for resource limits. Linux/MIPS version. - Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004 + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -89,7 +89,18 @@ enum __rlimit_resource __RLIMIT_MSGQUEUE = 12, #define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE - __RLIMIT_NLIMITS = 13, + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO _RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, __RLIM_NLIMITS = __RLIMIT_NLIMITS #define RLIMIT_NLIMITS __RLIMIT_NLIMITS #define RLIM_NLIMITS __RLIM_NLIMITS Jakub From jakub@redhat.com Mon Jun 20 11:40:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Mon, 20 Jun 2005 11:40:00 -0000 Subject: [PATCH] changes for current quotactl Message-ID: <20050620114023.GW7663@sunsite.mff.cuni.cz> Hi! 2.4.22+ as well as all 2.6.xx kernels contain a different set of operations for quotactl and the associated structures etc. Unfortunately the names of quotactl(2) commands etc. remained the same. This patch solves this by providing both incompatible interfaces in , with the new one being the default and with -D_LINUX_QUOTA_VERSION=1 that will provide the old interface. 2005-06-20 Jakub Jelinek * sysdeps/unix/sysv/linux/sys/quota.h: Add definitions and types for _LINUX_QUOTA_VERSION >= 2. (_LINUX_QUOTA_VERSION): Define if not yet defined. --- libc/sysdeps/unix/sysv/linux/sys/quota.h.jj 1999-10-19 05:05:21.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/sys/quota.h 2005-06-20 13:26:35.000000000 +0200 @@ -41,6 +41,14 @@ #include /* + * Select between different incompatible quota versions. + * Default to the version used by Linux kernel version 2.4.22 + * or later. */ +#ifndef _LINUX_QUOTA_VERSION +# define _LINUX_QUOTA_VERSION 2 +#endif + +/* * Convert diskblocks to blocks and the other way around. * currently only to fool the BSD source. :-) */ @@ -94,21 +102,33 @@ #define SUBCMDSHIFT 8 #define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) -#define Q_QUOTAON 0x0100 /* enable quotas */ -#define Q_QUOTAOFF 0x0200 /* disable quotas */ -#define Q_GETQUOTA 0x0300 /* get limits and usage */ -#define Q_SETQUOTA 0x0400 /* set limits and usage */ -#define Q_SETUSE 0x0500 /* set usage */ -#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ -#define Q_SETQLIM 0x0700 /* set limits */ -#define Q_GETSTATS 0x0800 /* get collected stats */ -#define Q_RSQUASH 0x1000 /* set root_squash option */ +#if _LINUX_QUOTA_VERSION < 2 +# define Q_QUOTAON 0x0100 /* enable quotas */ +# define Q_QUOTAOFF 0x0200 /* disable quotas */ +# define Q_GETQUOTA 0x0300 /* get limits and usage */ +# define Q_SETQUOTA 0x0400 /* set limits and usage */ +# define Q_SETUSE 0x0500 /* set usage */ +# define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ +# define Q_SETQLIM 0x0700 /* set limits */ +# define Q_GETSTATS 0x0800 /* get collected stats */ +# define Q_RSQUASH 0x1000 /* set root_squash option */ +#else +# define Q_SYNC 0x800001 /* sync disk copy of a filesystems quotas */ +# define Q_QUOTAON 0x800002 /* turn quotas on */ +# define Q_QUOTAOFF 0x800003 /* turn quotas off */ +# define Q_GETFMT 0x800004 /* get quota format used on given filesystem */ +# define Q_GETINFO 0x800005 /* get information about quota files */ +# define Q_SETINFO 0x800006 /* set information about quota files */ +# define Q_GETQUOTA 0x800007 /* get user quota structure */ +# define Q_SETQUOTA 0x800008 /* set user quota structure */ +#endif /* * The following structure defines the format of the disk quota file * (as it appears on disk) - the file is an array of these structures * indexed by user or group number. */ +#if _LINUX_QUOTA_VERSION < 2 struct dqblk { u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ @@ -120,13 +140,45 @@ struct dqblk time_t dqb_btime; /* time limit for excessive disk use */ time_t dqb_itime; /* time limit for excessive files */ }; +#else + +/* Flags that indicate which fields in dqblk structure are valid. */ +#define QIF_BLIMITS 1 +#define QIF_SPACE 2 +#define QIF_ILIMITS 4 +#define QIF_INODES 8 +#define QIF_BTIME 16 +#define QIF_ITIME 32 +#define QIF_LIMITS (QIF_BLIMITS | QIF_ILIMITS) +#define QIF_USAGE (QIF_SPACE | QIF_INODES) +#define QIF_TIMES (QIF_BTIME | QIF_ITIME) +#define QIF_ALL (QIF_LIMITS | QIF_USAGE | QIF_TIMES) + +struct dqblk + { + u_int64_t dqb_bhardlimit; /* absolute limit on disk quota blocks alloc */ + u_int64_t dqb_bsoftlimit; /* preferred limit on disk quota blocks */ + u_int64_t dqb_curspace; /* current quota block count */ + u_int64_t dqb_ihardlimit; /* maximum # allocated inodes */ + u_int64_t dqb_isoftlimit; /* preferred inode limit */ + u_int64_t dqb_curinodes; /* current # allocated inodes */ + u_int64_t dqb_btime; /* time limit for excessive disk use */ + u_int64_t dqb_itime; /* time limit for excessive files */ + u_int32_t dqb_valid; /* bitmask of QIF_* constants */ + }; +#endif /* * Shorthand notation. */ #define dq_bhardlimit dq_dqb.dqb_bhardlimit #define dq_bsoftlimit dq_dqb.dqb_bsoftlimit -#define dq_curblocks dq_dqb.dqb_curblocks +#if _LINUX_QUOTA_VERSION < 2 +# define dq_curblocks dq_dqb.dqb_curblocks +#else +# define dq_curspace dq_dqb.dqb_curspace +# define dq_valid dq_dqb.dqb_valid +#endif #define dq_ihardlimit dq_dqb.dqb_ihardlimit #define dq_isoftlimit dq_dqb.dqb_isoftlimit #define dq_curinodes dq_dqb.dqb_curinodes @@ -135,6 +187,7 @@ struct dqblk #define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) +#if _LINUX_QUOTA_VERSION < 2 struct dqstats { u_int32_t lookups; @@ -147,6 +200,22 @@ struct dqstats u_int32_t free_dquots; u_int32_t syncs; }; +#else + +/* Flags that indicate which fields in dqinfo structure are valid. */ +# define IIF_BGRACE 1 +# define IIF_IGRACE 2 +# define IIF_FLAGS 4 +# define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS) + +struct dqinfo + { + u_int64_t dqi_bgrace; + u_int64_t dqi_igrace; + u_int32_t dqi_flags; + u_int32_t dqi_valid; + }; +#endif __BEGIN_DECLS Jakub From drepper@redhat.com Mon Jun 20 15:08:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Mon, 20 Jun 2005 15:08:00 -0000 Subject: [PATCH] Add RLIMIT_NICE and RLIMIT_RTPRIO In-Reply-To: <20050620094434.GV7663@sunsite.mff.cuni.cz> References: <20050620094434.GV7663@sunsite.mff.cuni.cz> Message-ID: <42B6DACF.4090606@redhat.com> Applied. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From drepper@redhat.com Mon Jun 20 15:26:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Mon, 20 Jun 2005 15:26:00 -0000 Subject: [PATCH] changes for current quotactl In-Reply-To: <20050620114023.GW7663@sunsite.mff.cuni.cz> References: <20050620114023.GW7663@sunsite.mff.cuni.cz> Message-ID: <42B6DF05.4060809@redhat.com> Applied. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From jakub@redhat.com Thu Jun 23 22:25:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Thu, 23 Jun 2005 22:25:00 -0000 Subject: [RFC PATCH] glibc part of stack protector Message-ID: <20050623222514.GC7663@sunsite.mff.cuni.cz> Hi! In http://gcc.gnu.org/ml/gcc-patches/2005-05/msg01193.html Richard Henderson posted a patch to implement -fstack-protector in GCC 4+. It can either use support stuff in libgcc.{a,so}, or in libc. This patch adds support for that to glibc. As the kernel doesn't provide a random integer to the programs in aux vector (yet), the initialization is quite expensive (open/read/close from /dev/urandom) and especially for the time being, as not everybody is going to use GCC with -fstack-protector, all that on every program startup would be done completely needlessly for all those people, I have made it optional. The default is now that __stack_chk_guard will be initialized by the default 0 ... '\n' 255 magic, but if you know you are going to use -fstack-protector compiled programs extensively, --enable-stackguard-randomization as configure option is highly desirable. Tested on x86-64 (NPTL and LinuxThreads) and ppc64 (NPTL) so far. Some architectures like Alpha are probably going to always use __stack_chk_guard variable, but on i386/x86-64/ppc/ppc64/s390/s390x and likely ia64 it is better to use the thread local area access. I'm still undecided whether we want to export __stack_chk_guard@@GLIBC_2.4 from ld.so on the architectures that are always going to use the thread local area access. The patch below exports it unconditionally, to export it only for Alpha etc. it would need to avoid the __stack_chk_guard variable altogether if THREAD_SET_STACK_GUARD macro is defined. I will post corresponding GCC patches later today. 2005-06-24 Jakub Jelinek * Versions.def (ld): Add GLIBC_2.4. * configure.in: Add --enable-stackguard-randomization option. (ENABLE_STACKGUARD_RANDOMIZE): New define. * config.h.in (ENABLE_STACKGUARD_RANDOMIZE): Add. * configure: Rebuilt. * sysdeps/unix/sysv/linux/dl-osinfo.h: Include stdint.h. (_dl_setup_stack_chk_guard): New inline function. * sysdeps/generic/dl-osinfo.h: Include stdint.h. (_dl_setup_stack_chk_guard): New inline function. * elf/rtld.c (__stack_chk_guard): New variable. * elf/Versions (ld): Export __stack_chk_guard@@GLIBC_2.4. (dl_main): Remove all traces of TLS_INIT_TP_EXPENSIVE. Set __stack_chk_guard to _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. * sysdeps/generic/libc-start.c (__stack_chk_guard): New variable. (__libc_start_main): Set __stack_chk_guard to _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. * sysdeps/generic/libc-tls.c (__libc_setup_tls): Remove all tracesof TLS_INIT_TP_EXPENSIVE. * debug/Versions (libc): Export __stack_chk_fail@@GLIBC_2.4. * debug/Makefile (routines): Add stack_chk_fail. (static-only-routines): Add stack_chk_fail_local. * debug/stack_chk_fail_local.c: New file. * debug/stack_chk_fail.c: New file. * elf/Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * elf/tst-stackguard1.c: New file. * elf/tst-stackguard1-static.c: New file. * elf/stackguard-macros.h: New file. nptl/ * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard field. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/x86_64/tls.h (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/s390/tls.h (tcbhead_t): Add stack_guard field. Put in sysinfo field unconditionally. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/powerpc/tls.h (tcbhead_t): Add stack_guard field. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/sparc/tls.h (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * pthread_create.c (__pthread_create_2_1): Use THREAD_COPY_STACK_GUARD macro. * Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * tst-stackguard1.c: New file. * tst-stackguard1-static.c: New file. linuxthreads/ * pthread.c (__pthread_initialize_manager): Use THREAD_COPY_STACK_GUARD macro. * manager.c (pthread_handle_create): Likewise. * descr.h (struct _pthread_descr_struct): Add p_header.stack_guard field. Put in p_header.sysinfo field unconditionally. * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard field. Put in sysinfo field unconditionally. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/x86_64/tls.h: Include stdint.h. (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/s390/tls.h: Include stdint.h. (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/powerpc/tls.h: Include stdint.h. (tcbhead_t): Add in stack_guard field. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. (NONTLS_INIT_TP): Fix for current TLS ABI. * sysdeps/sparc/tls.h: Include stdint.h. (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * tst-stackguard1.c: New file. * tst-stackguard1-static.c: New file. --- libc/elf/Makefile.jj 2005-04-27 14:03:47.000000000 +0200 +++ libc/elf/Makefile 2005-06-23 18:43:55.000000000 +0200 @@ -87,7 +87,8 @@ distribute := rtld-Rules \ unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \ unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \ unload6mod1.c unload6mod2.c unload6mod3.c tst-auditmod1.c \ - order2mod1.c order2mod2.c order2mod3.c order2mod4.c + order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ + tst-stackguard1.c tst-stackguard1-static.c CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables @@ -140,7 +141,7 @@ ifeq (yes,$(have-initfini-array)) tests += tst-array1 tst-array2 tst-array3 tst-array4 endif ifeq (yes,$(build-static)) -tests-static = tst-tls1-static tst-tls2-static +tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static ifeq (yesyesyes,$(build-static)$(build-shared)$(elf)) tests-static += tst-tls9-static tst-tls9-static-ENV = \ @@ -162,7 +163,8 @@ tests += loadtest restest1 preloadtest l tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \ tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \ tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 + unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \ + tst-stackguard1 # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -843,3 +845,6 @@ $(objpfx)order2mod1.so: $(objpfx)order2m $(objpfx)order2mod4.so: $(objpfx)order2mod3.so $(objpfx)order2mod2.so: $(objpfx)order2mod3.so order2mod2.so-no-z-defs = yes + +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" --- libc/elf/tst-stackguard1.c.jj 2005-06-23 17:03:19.000000000 +0200 +++ libc/elf/tst-stackguard1.c 2005-06-23 18:45:31.000000000 +0200 @@ -0,0 +1,216 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool con_failure, stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = __stack_chk_guard; + if (stack_chk_guard_copy != STACK_CHK_GUARD) + con_failure = true; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (con_failure) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in the constructor"); + return 1; + } + + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed between constructor and do_test"); + return 1; + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in do_test"); + return 1; + } + + if (child) + { + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed after fork"); + exit (1); + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_CHILD: \ + child = true; \ + break; +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" --- libc/elf/rtld.c.jj 2005-06-23 12:15:47.000000000 +0200 +++ libc/elf/rtld.c 2005-06-23 14:19:23.000000000 +0200 @@ -80,6 +80,8 @@ char **_dl_argv attribute_relro = NULL; #endif INTDEF(_dl_argv) +uintptr_t __stack_chk_guard attribute_relro; + /* Nonzero if we were run directly. */ unsigned int _dl_skip_args attribute_relro attribute_hidden; @@ -1398,9 +1400,6 @@ ld.so does not support TLS, but program always allocate the static block, we never defer it even if no DF_STATIC_TLS bit is set. The reason is that we know glibc will use the static model. */ -# ifndef TLS_INIT_TP_EXPENSIVE -# define TLS_INIT_TP_EXPENSIVE 0 -# endif /* Since we start using the auditing DSOs right away we need to initialize the data structures now. */ @@ -1807,10 +1806,16 @@ ERROR: ld.so: object '%s' cannot be load used. Trying to do it lazily is too hairy to try when there could be multiple threads (from a non-TLS-using libpthread). */ bool was_tls_init_tp_called = tls_init_tp_called; - if (tcbp == NULL && (!TLS_INIT_TP_EXPENSIVE || GL(dl_tls_max_dtv_idx) > 0)) + if (tcbp == NULL) tcbp = init_tls (); #endif + /* Set up the stack checker's canary. */ + __stack_chk_guard = _dl_setup_stack_chk_guard (); +#ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (__stack_chk_guard); +#endif + if (__builtin_expect (mode, normal) != normal) { /* We were run just to list the shared libraries. It is @@ -2230,29 +2235,26 @@ ERROR: ld.so: object '%s' cannot be load #endif #ifdef USE_TLS - if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE) - { - if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) - ++GL(dl_tls_generation); + if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) + ++GL(dl_tls_generation); - /* Now that we have completed relocation, the initializer data - for the TLS blocks has its final values and we can copy them - into the main thread's TLS area, which we allocated above. */ - _dl_allocate_tls_init (tcbp); - - /* And finally install it for the main thread. If ld.so itself uses - TLS we know the thread pointer was initialized earlier. */ - if (! tls_init_tp_called) - { - const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); - if (__builtin_expect (lossage != NULL, 0)) - _dl_fatal_printf ("cannot set up thread-local storage: %s\n", - lossage); - } + /* Now that we have completed relocation, the initializer data + for the TLS blocks has its final values and we can copy them + into the main thread's TLS area, which we allocated above. */ + _dl_allocate_tls_init (tcbp); + + /* And finally install it for the main thread. If ld.so itself uses + TLS we know the thread pointer was initialized earlier. */ + if (! tls_init_tp_called) + { + const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); + if (__builtin_expect (lossage != NULL, 0)) + _dl_fatal_printf ("cannot set up thread-local storage: %s\n", + lossage); } - else +#else + NONTLS_INIT_TP; #endif - NONTLS_INIT_TP; #ifdef SHARED /* Auditing checkpoint: we have added all objects. */ --- libc/elf/Versions.jj 2005-05-03 21:50:14.000000000 +0200 +++ libc/elf/Versions 2005-06-23 12:22:09.000000000 +0200 @@ -43,6 +43,10 @@ ld { # runtime interface to TLS __tls_get_addr; } + GLIBC_2.4 { + # stack canary + __stack_chk_guard; + } GLIBC_PRIVATE { # Those are in the dynamic linker, but used by libc.so. __libc_enable_secure; --- libc/elf/tst-stackguard1-static.c.jj 2005-06-23 18:41:42.000000000 +0200 +++ libc/elf/tst-stackguard1-static.c 2005-06-23 18:45:33.000000000 +0200 @@ -0,0 +1 @@ +#include "tst-stackguard1.c" --- libc/elf/stackguard-macros.h.jj 2005-06-23 16:58:17.000000000 +0200 +++ libc/elf/stackguard-macros.h 2005-06-23 16:58:11.000000000 +0200 @@ -0,0 +1,31 @@ +#include + +extern uintptr_t __stack_chk_guard; +#ifdef __i386__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; }) +#elif defined __x86_64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("movq %%fs:0x28, %0" : "=r" (x)); x; }) +#elif defined __powerpc64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; }) +#elif defined __powerpc__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; }) +#elif defined __sparc__ && defined __arch64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; }) +#elif defined __sparc__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; }) +#elif defined __s390x__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ear %0,%a0; sllg %0,%0,32; ear %0,%a1; lg %0,0x28(%0)" : "=r" (x)); x; }) +#elif defined __s390__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=r" (x)); x; }) +#else +# define STACK_CHK_GUARD __stack_chk_guard +#endif + --- libc/sysdeps/unix/sysv/linux/dl-osinfo.h.jj 2005-06-06 11:41:17.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/dl-osinfo.h 2005-06-23 16:08:51.000000000 +0200 @@ -23,6 +23,7 @@ #include #include "kernel-features.h" #include +#include #ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) @@ -157,3 +158,24 @@ _dl_discover_osversion (void) else if (__LINUX_KERNEL_VERSION > 0) \ FATAL ("FATAL: cannot determine kernel version\n"); \ } while (0) + +static inline uintptr_t __attribute__ ((always_inline)) +_dl_setup_stack_chk_guard (void) +{ + uintptr_t ret; +#ifdef ENABLE_STACKGUARD_RANDOMIZE + int fd = __open ("/dev/urandom", O_RDONLY); + if (fd >= 0) + { + ssize_t reslen = __read (fd, &ret, sizeof (ret)); + __close (fd); + if (reslen == (ssize_t) sizeof (ret)) + return ret; + } +#endif + ret = 0; + unsigned char *p = (unsigned char *) &ret; + p[sizeof (ret) - 1] = 255; + p[sizeof (ret) - 2] = '\n'; + return ret; +} --- libc/sysdeps/generic/libc-start.c.jj 2005-02-21 17:20:16.000000000 +0100 +++ libc/sysdeps/generic/libc-start.c 2005-06-23 16:34:49.000000000 +0200 @@ -35,6 +35,7 @@ extern void __pthread_initialize_minimal __attribute__ ((weak)) # endif ; +uintptr_t __stack_chk_guard attribute_relro; #endif #ifdef HAVE_PTR_NTHREADS @@ -152,6 +153,14 @@ LIBC_START_MAIN (int (*main) (int, char __pthread_initialize_minimal (); #endif +# ifndef SHARED + /* Set up the stack checker's canary. */ + __stack_chk_guard = _dl_setup_stack_chk_guard (); +# ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (__stack_chk_guard); +# endif +#endif + /* Register the destructor of the dynamic linker if there is any. */ if (__builtin_expect (rtld_fini != NULL, 1)) __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL); --- libc/sysdeps/generic/libc-tls.c.jj 2005-02-25 14:45:06.000000000 +0100 +++ libc/sysdeps/generic/libc-tls.c 2005-06-23 16:28:55.000000000 +0200 @@ -133,17 +133,6 @@ __libc_setup_tls (size_t tcbsize, size_t break; } -#ifdef TLS_INIT_TP_EXPENSIVE - if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE) - { - /* We do not need a TLS block and no thread descriptor. */ -# ifdef NONTLS_INIT_TP - NONTLS_INIT_TP; -# endif - return; - } -#endif - /* We have to set up the TCB block which also (possibly) contains 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. Instead we use 'sbrk' which would only uses 'errno' if it fails. --- libc/sysdeps/generic/dl-osinfo.h.jj 2005-05-03 21:50:44.000000000 +0200 +++ libc/sysdeps/generic/dl-osinfo.h 2005-06-23 18:28:55.000000000 +0200 @@ -1 +1,12 @@ -/* Nothing needed in general. */ +#include + +static inline uintptr_t __attribute__ ((always_inline)) +_dl_setup_stack_chk_guard (void) +{ + uintptr_t ret = 0; + unsigned char *p = (unsigned char *) &ret; + p[sizeof (ret) - 1] = 255; + p[sizeof (ret) - 2] = '\n'; + p[0] = 0; + return ret; +} --- libc/nptl/Makefile.jj 2005-04-27 14:03:51.000000000 +0200 +++ libc/nptl/Makefile 2005-06-23 19:16:08.000000000 +0200 @@ -269,7 +269,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-c tst-oncex3 tst-oncex4 endif ifeq ($(build-shared),yes) -tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 +tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \ + tst-stackguard1 tests-nolibpthread += tst-fini1 ifeq ($(have-z-execstack),yes) tests += tst-execstack @@ -337,7 +338,8 @@ link-libc-static := $(common-objpfx)libc $(common-objpfx)libc.a ifeq ($(build-static),yes) -tests-static += tst-locale1 tst-locale2 +tests-static += tst-locale1 tst-locale2 tst-stackguard1-static +tests += tst-stackguard1-static xtests-static += tst-setuid1-static endif # These tests are linked with libc before libpthread @@ -586,6 +588,9 @@ LDFLAGS-tst-execstack = -Wl,-z,noexecsta $(objpfx)tst-fini1mod.so: $(shared-thread-library) +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" + # The tests here better do not run in parallel ifneq ($(filter %tests,$(MAKECMDGOALS)),) .NOTPARALLEL: --- libc/nptl/sysdeps/s390/tls.h.jj 2005-05-23 18:22:04.000000000 +0200 +++ libc/nptl/sysdeps/s390/tls.h 2005-06-23 12:22:09.000000000 +0200 @@ -48,9 +48,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; -# ifdef NEED_DL_SYSINFO uintptr_t sysinfo; -# endif + uintptr_t stack_guard; } tcbhead_t; # ifndef __s390x__ @@ -158,6 +157,13 @@ typedef struct #define THREAD_SETMEM_NC(descr, member, idx, value) \ descr->member[idx] = (value) +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ --- libc/nptl/sysdeps/powerpc/tls.h.jj 2005-05-03 21:50:31.000000000 +0200 +++ libc/nptl/sysdeps/powerpc/tls.h 2005-06-23 12:22:09.000000000 +0200 @@ -65,11 +65,11 @@ typedef union dtv /* Get the thread descriptor definition. */ # include -/* This layout is actually wholly private and not affected by the ABI. - Nor does it overlap the pthread data structure, so we need nothing - extra here at all. */ +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv field is private. */ typedef struct { + uintptr_t stack_guard; dtv_t *dtv; } tcbhead_t; @@ -127,7 +127,7 @@ register void *__thread_register __asm__ /* Return the address of the dtv for the current thread. */ # define THREAD_DTV() \ - (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) /* Return the thread descriptor for the current thread. */ # define THREAD_SELF \ @@ -136,9 +136,9 @@ register void *__thread_register __asm__ /* Magic for libthread_db to know how to do THREAD_SELF. */ # define DB_THREAD_SELF \ - REGISTER (32, 32, PT_THREAD_POINTER * 4, \ + REGISTER (32, 32, PT_THREAD_POINTER * 4, \ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \ - REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) /* Read member of the thread descriptor directly. */ @@ -156,6 +156,16 @@ register void *__thread_register __asm__ # define THREAD_SETMEM_NC(descr, member, idx, value) \ ((void)(descr), (THREAD_SELF)->member[idx] = (value)) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + /* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some different value to mean unset l_tls_offset. */ # define NO_TLS_OFFSET -1 --- libc/nptl/sysdeps/sparc/tls.h.jj 2005-05-23 18:22:05.000000000 +0200 +++ libc/nptl/sysdeps/sparc/tls.h 2005-06-23 12:22:09.000000000 +0200 @@ -46,6 +46,8 @@ typedef struct dtv_t *dtv; void *self; int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -126,6 +128,13 @@ register struct pthread *__thread_self _ #define THREAD_SETMEM_NC(descr, member, idx, value) \ descr->member[idx] = (value) +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + #endif /* !ASSEMBLER */ #endif /* tls.h */ --- libc/nptl/sysdeps/i386/tls.h.jj 2005-05-23 18:22:02.000000000 +0200 +++ libc/nptl/sysdeps/i386/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -49,6 +49,7 @@ typedef struct void *self; /* Pointer to the thread descriptor. */ int multiple_threads; uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; # define TLS_MULTIPLE_THREADS_IN_TCB 1 @@ -416,6 +417,14 @@ union user_desc_init __res; }) +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ --- libc/nptl/sysdeps/x86_64/tls.h.jj 2005-05-23 18:22:11.000000000 +0200 +++ libc/nptl/sysdeps/x86_64/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -47,6 +47,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -320,6 +322,13 @@ typedef struct __res; }) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ --- libc/nptl/tst-stackguard1.c.jj 2005-06-23 17:03:19.000000000 +0200 +++ libc/nptl/tst-stackguard1.c 2005-06-23 19:13:27.000000000 +0200 @@ -0,0 +1,252 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool con_failure, stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = __stack_chk_guard; + if (stack_chk_guard_copy != STACK_CHK_GUARD) + con_failure = true; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static void * +tf (void *arg) +{ + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed in thread"); + return (void *) 1L; + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in thread"); + return (void *) 1L; + } + return NULL; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (con_failure) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in the constructor"); + return 1; + } + + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed between constructor and do_test"); + return 1; + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in do_test"); + return 1; + } + + if (child) + { + int i; + pthread_t th[4]; + void *ret; + for (i = 0; i < 4; ++i) + if (pthread_create (&th[i], NULL, tf, NULL)) + { + puts ("thread creation failed"); + return 1; + } + for (i = 0; i < 4; ++i) + if (pthread_join (th[i], &ret)) + { + puts ("thread join failed"); + return 1; + } + else if (ret != NULL) + return 1; + + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed after fork"); + exit (1); + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_CHILD: \ + child = true; \ + break; +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" --- libc/nptl/pthread_create.c.jj 2005-05-03 21:50:28.000000000 +0200 +++ libc/nptl/pthread_create.c 2005-06-23 12:22:14.000000000 +0200 @@ -399,6 +399,11 @@ __pthread_create_2_1 (newthread, attr, s pd->schedpolicy = self->schedpolicy; pd->schedparam = self->schedparam; + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (pd); +#endif + /* Determine scheduling parameters for the thread. */ if (attr != NULL && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0) --- libc/nptl/tst-stackguard1-static.c.jj 2005-06-23 18:41:42.000000000 +0200 +++ libc/nptl/tst-stackguard1-static.c 2005-06-23 19:15:12.000000000 +0200 @@ -0,0 +1 @@ +#include "tst-stackguard1.c" --- libc/debug/Makefile.jj 2005-05-03 21:50:13.000000000 +0200 +++ libc/debug/Makefile 2005-06-23 12:56:11.000000000 +0200 @@ -31,9 +31,9 @@ routines = backtrace backtracesyms back printf_chk fprintf_chk vprintf_chk vfprintf_chk \ gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ - readlink_chk getwd_chk getcwd_chk \ + readlink_chk getwd_chk getcwd_chk stack_chk_fail \ $(static-only-routines) -static-only-routines := warning-nop +static-only-routines := warning-nop stack_chk_fail_local CFLAGS-backtrace.c = -fno-omit-frame-pointer CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO --- libc/debug/stack_chk_fail_local.c.jj 2005-06-23 12:52:34.000000000 +0200 +++ libc/debug/stack_chk_fail_local.c 2005-06-23 12:55:57.000000000 +0200 @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern void __stack_chk_fail (void) __attribute__ ((noreturn)); + +/* On some architectures, this helps needless PIC pointer setup + that would be needed just for the __stack_chk_fail call. */ + +void __attribute__ ((noreturn)) attribute_hidden +__stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} --- libc/debug/stack_chk_fail.c.jj 2005-06-23 12:22:14.000000000 +0200 +++ libc/debug/stack_chk_fail.c 2005-06-23 12:22:14.000000000 +0200 @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +extern char **__libc_argv attribute_hidden; + +void +__attribute__ ((noreturn)) +__stack_chk_fail (void) +{ + /* The loop is added only to keep gcc happy. */ + while (1) + __libc_message (1, "*** buffer overflow detected ***: %s terminated\n", + __libc_argv[0] ?: ""); +} --- libc/debug/Versions.jj 2005-05-03 21:50:13.000000000 +0200 +++ libc/debug/Versions 2005-06-23 12:22:53.000000000 +0200 @@ -23,5 +23,7 @@ libc { __read_chk; __pread_chk; __pread64_chk; __readlink_chk; __getcwd_chk; __getwd_chk; __recv_chk; __recvfrom_chk; + + __stack_chk_fail; } } --- libc/config.h.in.jj 2005-06-22 18:34:09.000000000 +0200 +++ libc/config.h.in 2005-06-23 13:25:00.000000000 +0200 @@ -223,6 +223,9 @@ /* Define if your assembler and linker support R_PPC_REL16* relocs. */ #undef HAVE_ASM_PPC_REL16 +/* Define if __stack_chk_guard canary should be randomized at program startup. */ +#undef ENABLE_STACKGUARD_RANDOMIZE + /* */ --- libc/Versions.def.jj 2005-05-03 21:50:05.000000000 +0200 +++ libc/Versions.def 2005-06-23 14:02:50.000000000 +0200 @@ -102,6 +102,7 @@ ld { GLIBC_2.0 GLIBC_2.1 GLIBC_2.3 + GLIBC_2.4 GLIBC_PRIVATE } libthread_db { --- libc/linuxthreads/Makefile.jj 2005-02-08 17:17:06.000000000 +0100 +++ libc/linuxthreads/Makefile 2005-06-23 19:19:09.000000000 +0200 @@ -117,13 +117,14 @@ test-srcs = tst-signal tests-reverse += tst-cancel5 ifeq ($(build-static),yes) -tests += tststatic tst-static-locale tst-cancel-static -tests-static += tststatic tst-static-locale tst-cancel-static +tests += tststatic tst-static-locale tst-cancel-static tst-stackguard1-static +tests-static += tststatic tst-static-locale tst-cancel-static \ + tst-stackguard1-static endif ifeq (yes,$(build-shared)) tests-nodelete-yes = unload -tests += tst-tls1 tst-_res1 +tests += tst-tls1 tst-_res1 tst-stackguard1 endif modules-names = tst-_res1mod1 tst-_res1mod2 \ @@ -343,3 +344,6 @@ $(objpfx)tst-cancel-wrappers.out: tst-ca generated += tst-signal.out tst-cancel-wrappers.out endif endif + +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" --- libc/linuxthreads/sysdeps/s390/tls.h.jj 2005-05-03 21:50:22.000000000 +0200 +++ libc/linuxthreads/sysdeps/s390/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -44,6 +45,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -122,9 +125,16 @@ typedef struct # define THREAD_DTV() \ (((tcbhead_t *) __builtin_thread_pointer ())->dtv) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif /* __ASSEMBLER__ */ -#else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#else /* HAVE_TLS_SUPPORT */ # ifndef __ASSEMBLER__ @@ -140,6 +150,6 @@ typedef struct # endif /* __ASSEMBLER__ */ -#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#endif /* HAVE_TLS_SUPPORT */ #endif /* tls.h */ --- libc/linuxthreads/sysdeps/powerpc/tls.h.jj 2005-05-03 21:50:21.000000000 +0200 +++ libc/linuxthreads/sysdeps/powerpc/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -48,11 +49,11 @@ typedef union dtv # ifndef __ASSEMBLER__ -/* This layout is actually wholly private and not affected by the ABI. - Nor does it overlap the pthread data structure, so we need nothing - extra here at all. */ +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv field is private. */ typedef struct { + uintptr_t stack_guard; dtv_t *dtv; } tcbhead_t; @@ -79,7 +80,7 @@ typedef struct assume that the pthread_descr is allocated immediately ahead of the TCB. This implies that the pthread_descr address is TP - (TLS_PRE_TCB_SIZE + 0x7000). */ -#define TLS_TCB_OFFSET 0x7000 +# define TLS_TCB_OFFSET 0x7000 /* The DTV is allocated at the TP; the TCB is placed elsewhere. */ /* This is not really true for powerpc64. We are following alpha @@ -138,6 +139,16 @@ typedef struct different value to mean unset l_tls_offset. */ # define NO_TLS_OFFSET -1 +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + # endif /* __ASSEMBLER__ */ #elif !defined __ASSEMBLER__ @@ -148,16 +159,16 @@ typedef struct single-threaded and multi-threaded code. */ typedef struct { - void *tcb; /* Never used. */ - dtv_t *dtv; /* Never used. */ - void *self; /* Used only if multithreaded, and rarely. */ - int multiple_threads; /* Only this member is really used. */ + uintptr_t stack_guard; + int multiple_threads; } tcbhead_t; #define NONTLS_INIT_TP \ do { \ static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ - __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + char *addr; \ + __asm ("" : "r" (addr) : "0" (&nontls_init_tp[1])); \ + __thread_self = (__typeof (__thread_self)) (addr + TLS_TCB_OFFSET); \ } while (0) #endif /* HAVE_TLS_SUPPORT */ --- libc/linuxthreads/sysdeps/sparc/tls.h.jj 2005-05-03 21:50:23.000000000 +0200 +++ libc/linuxthreads/sysdeps/sparc/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -44,6 +45,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -99,6 +102,13 @@ typedef struct # define THREAD_DTV() \ (((tcbhead_t *) __thread_self)->dtv) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif #else --- libc/linuxthreads/sysdeps/i386/tls.h.jj 2005-05-03 21:50:21.000000000 +0200 +++ libc/linuxthreads/sysdeps/i386/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -47,9 +47,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; -#ifdef NEED_DL_SYSINFO uintptr_t sysinfo; -#endif + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -224,6 +223,13 @@ TLS_DO_MODIFY_LDT_KERNEL_CHECK( ({ struct _pthread_descr_struct *__descr; \ THREAD_GETMEM (__descr, p_header.data.dtvp); }) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ #endif /* __ASSEMBLER__ */ --- libc/linuxthreads/sysdeps/x86_64/tls.h.jj 2005-05-03 21:50:25.000000000 +0200 +++ libc/linuxthreads/sysdeps/x86_64/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -45,6 +46,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -128,6 +131,13 @@ typedef struct ({ struct _pthread_descr_struct *__descr; \ THREAD_GETMEM (__descr, p_header.data.dtvp); }) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif /* HAVE_TLS_SUPPORT */ #endif /* __ASSEMBLER__ */ --- libc/linuxthreads/pthread.c.jj 2005-01-19 14:12:43.000000000 +0100 +++ libc/linuxthreads/pthread.c 2005-06-23 23:01:11.000000000 +0200 @@ -696,6 +696,11 @@ int __pthread_initialize_manager(void) mgr = &__pthread_manager_thread; #endif + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (mgr); +#endif + __pthread_manager_request = manager_pipe[1]; /* writing end */ __pthread_manager_reader = manager_pipe[0]; /* reading end */ --- libc/linuxthreads/manager.c.jj 2005-05-03 21:50:20.000000000 +0200 +++ libc/linuxthreads/manager.c 2005-06-23 12:22:14.000000000 +0200 @@ -698,6 +698,12 @@ static int pthread_handle_create(pthread new_thread->p_start_args.start_routine = start_routine; new_thread->p_start_args.arg = arg; new_thread->p_start_args.mask = *mask; + + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (new_thread); +#endif + /* Make the new thread ID available already now. If any of the later functions fail we return an error value and the caller must not use the stored thread ID. */ --- libc/linuxthreads/tst-stackguard1.c.jj 2005-06-23 17:03:19.000000000 +0200 +++ libc/linuxthreads/tst-stackguard1.c 2005-06-23 19:13:27.000000000 +0200 @@ -0,0 +1,252 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool con_failure, stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = __stack_chk_guard; + if (stack_chk_guard_copy != STACK_CHK_GUARD) + con_failure = true; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static void * +tf (void *arg) +{ + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed in thread"); + return (void *) 1L; + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in thread"); + return (void *) 1L; + } + return NULL; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (con_failure) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in the constructor"); + return 1; + } + + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed between constructor and do_test"); + return 1; + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard in do_test"); + return 1; + } + + if (child) + { + int i; + pthread_t th[4]; + void *ret; + for (i = 0; i < 4; ++i) + if (pthread_create (&th[i], NULL, tf, NULL)) + { + puts ("thread creation failed"); + return 1; + } + for (i = 0; i < 4; ++i) + if (pthread_join (th[i], &ret)) + { + puts ("thread join failed"); + return 1; + } + else if (ret != NULL) + return 1; + + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != __stack_chk_guard) + { + puts ("__stack_chk_guard changed after fork"); + exit (1); + } + + if (__stack_chk_guard != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD != __stack_chk_guard after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_CHILD: \ + child = true; \ + break; +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" --- libc/linuxthreads/descr.h.jj 2005-05-03 21:50:20.000000000 +0200 +++ libc/linuxthreads/descr.h 2005-06-23 12:22:14.000000000 +0200 @@ -120,9 +120,8 @@ struct _pthread_descr_struct union dtv *dtvp; pthread_descr self; /* Pointer to this structure */ int multiple_threads; -# ifdef NEED_DL_SYSINFO uintptr_t sysinfo; -# endif + uintptr_t stack_guard; } data; void *__padding[16]; } p_header; --- libc/linuxthreads/tst-stackguard1-static.c.jj 2005-06-23 18:41:42.000000000 +0200 +++ libc/linuxthreads/tst-stackguard1-static.c 2005-06-23 19:15:12.000000000 +0200 @@ -0,0 +1 @@ +#include "tst-stackguard1.c" --- libc/configure.in.jj 2005-06-22 18:34:10.000000000 +0200 +++ libc/configure.in 2005-06-23 13:22:56.000000000 +0200 @@ -174,6 +174,15 @@ else fi AC_SUBST(oldest_abi) +AC_ARG_ENABLE([stackguard-randomization], + AC_HELP_STRING([--enable-stackguard-randomization], + [initialize __stack_chk_guard canary with a random number at program start]), + [enable_stackguard_randomize=$enableval], + [enable_stackguard_randomize=no]) +if test "$enable_stackguard_randomize" = yes; then + AC_DEFINE(ENABLE_STACKGUARD_RANDOMIZE) +fi + dnl Generic infrastructure for drop-in additions to libc. AC_ARG_ENABLE([add-ons], AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@], --- libc/configure.jj 2005-06-22 18:34:09.000000000 +0200 +++ libc/configure 2005-06-23 13:23:16.000000000 +0200 @@ -873,6 +873,9 @@ Optional Features: objects [default=yes if supported] --enable-oldest-abi=ABI configure the oldest ABI supported [e.g. 2.2] [default=glibc default] + --enable-stackguard-randomization + initialize __stack_chk_guard canary with a random + number at program start --enable-add-ons[=DIRS...] configure and build add-ons in DIR1,DIR2,... search for add-ons if no parameter given @@ -1597,6 +1600,20 @@ _ACEOF fi +# Check whether --enable-stackguard-randomization or --disable-stackguard-randomization was given. +if test "${enable_stackguard_randomization+set}" = set; then + enableval="$enable_stackguard_randomization" + enable_stackguard_randomize=$enableval +else + enable_stackguard_randomize=no +fi; +if test "$enable_stackguard_randomize" = yes; then + cat >>confdefs.h <<\_ACEOF +#define ENABLE_STACKGUARD_RANDOMIZE 1 +_ACEOF + +fi + # Check whether --enable-add-ons or --disable-add-ons was given. if test "${enable_add_ons+set}" = set; then enableval="$enable_add_ons" Jakub From drepper@redhat.com Fri Jun 24 15:14:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Fri, 24 Jun 2005 15:14:00 -0000 Subject: [RFC PATCH] glibc part of stack protector In-Reply-To: <20050623222514.GC7663@sunsite.mff.cuni.cz> References: <20050623222514.GC7663@sunsite.mff.cuni.cz> Message-ID: <42BC2325.90707@redhat.com> Looks good. Jakub Jelinek wrote: > I'm still undecided whether we want to export __stack_chk_guard@@GLIBC_2.4 > from ld.so on the architectures that are always going to use > the thread local area access. No. Don't let there be an ambiguities in the ABI. These archs use the TLS variable and nothing else. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From jakub@redhat.com Sat Jun 25 08:55:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Sat, 25 Jun 2005 08:55:00 -0000 Subject: [PATCH] glibc part of stack protector (take 2) In-Reply-To: <42BC2325.90707@redhat.com> References: <20050623222514.GC7663@sunsite.mff.cuni.cz> <42BC2325.90707@redhat.com> Message-ID: <20050625085455.GD7663@sunsite.mff.cuni.cz> On Fri, Jun 24, 2005 at 08:13:41AM -0700, Ulrich Drepper wrote: > Looks good. > > > I'm still undecided whether we want to export __stack_chk_guard@@GLIBC_2.4 > > from ld.so on the architectures that are always going to use > > the thread local area access. > > No. Don't let there be an ambiguities in the ABI. These archs use the > TLS variable and nothing else. Ok, here is an updated patch that does not export __stack_chk_guard@@GLIBC_2.4 from ld.so if THREAD_SET_STACK_GUARD is defined, adjusts the testcases accordingly and changes the message printed when the canary has been overwritten, so that it is clearly distinguishable if the reason for aborting the application was heap corruption/double free, _FORTIFY_SOURCE or overwriting of the canary. 2005-06-25 Jakub Jelinek * Versions.def (ld): Add GLIBC_2.4. * configure.in: Add --enable-stackguard-randomization option. (ENABLE_STACKGUARD_RANDOMIZE): New define. * config.h.in (ENABLE_STACKGUARD_RANDOMIZE): Add. * configure: Rebuilt. * sysdeps/unix/sysv/linux/dl-osinfo.h: Include stdint.h. (_dl_setup_stack_chk_guard): New inline function. * sysdeps/generic/dl-osinfo.h: Include stdint.h. (_dl_setup_stack_chk_guard): New inline function. * elf/rtld.c (__stack_chk_guard): New variable. * elf/Versions (ld): Export __stack_chk_guard@@GLIBC_2.4. (dl_main): Remove all traces of TLS_INIT_TP_EXPENSIVE. Set __stack_chk_guard to _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. * sysdeps/generic/libc-start.c (__stack_chk_guard): New variable. (__libc_start_main): Set __stack_chk_guard to _dl_setup_stack_chk_guard (), use THREAD_SET_STACK_GUARD if defined. * sysdeps/generic/libc-tls.c (__libc_setup_tls): Remove all tracesof TLS_INIT_TP_EXPENSIVE. * debug/Versions (libc): Export __stack_chk_fail@@GLIBC_2.4. * debug/Makefile (routines): Add stack_chk_fail. (static-only-routines): Add stack_chk_fail_local. * debug/stack_chk_fail_local.c: New file. * debug/stack_chk_fail.c: New file. * elf/Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * elf/tst-stackguard1.c: New file. * elf/tst-stackguard1-static.c: New file. * elf/stackguard-macros.h: New file. nptl/ * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard field. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/x86_64/tls.h (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/s390/tls.h (tcbhead_t): Add stack_guard field. Put in sysinfo field unconditionally. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/powerpc/tls.h (tcbhead_t): Add stack_guard field. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/sparc/tls.h (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * pthread_create.c (__pthread_create_2_1): Use THREAD_COPY_STACK_GUARD macro. * Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * tst-stackguard1.c: New file. * tst-stackguard1-static.c: New file. linuxthreads/ * pthread.c (__pthread_initialize_manager): Use THREAD_COPY_STACK_GUARD macro. * manager.c (pthread_handle_create): Likewise. * descr.h (struct _pthread_descr_struct): Add p_header.stack_guard field. Put in p_header.sysinfo field unconditionally. * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard field. Put in sysinfo field unconditionally. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/x86_64/tls.h: Include stdint.h. (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/s390/tls.h: Include stdint.h. (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * sysdeps/powerpc/tls.h: Include stdint.h. (tcbhead_t): Add in stack_guard field. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. (NONTLS_INIT_TP): Fix for current TLS ABI. * sysdeps/sparc/tls.h: Include stdint.h. (tcbhead_t): Add sysinfo and stack_guard fields. (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. * Makefile: Add rules to build and run tst-stackguard1{,-static} tests. * tst-stackguard1.c: New file. * tst-stackguard1-static.c: New file. --- libc/elf/Makefile.jj 2005-04-27 14:03:47.000000000 +0200 +++ libc/elf/Makefile 2005-06-23 18:43:55.000000000 +0200 @@ -87,7 +87,8 @@ distribute := rtld-Rules \ unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \ unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \ unload6mod1.c unload6mod2.c unload6mod3.c tst-auditmod1.c \ - order2mod1.c order2mod2.c order2mod3.c order2mod4.c + order2mod1.c order2mod2.c order2mod3.c order2mod4.c \ + tst-stackguard1.c tst-stackguard1-static.c CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-dl-lookup.c = -fexceptions -fasynchronous-unwind-tables @@ -140,7 +141,7 @@ ifeq (yes,$(have-initfini-array)) tests += tst-array1 tst-array2 tst-array3 tst-array4 endif ifeq (yes,$(build-static)) -tests-static = tst-tls1-static tst-tls2-static +tests-static = tst-tls1-static tst-tls2-static tst-stackguard1-static ifeq (yesyesyes,$(build-static)$(build-shared)$(elf)) tests-static += tst-tls9-static tst-tls9-static-ENV = \ @@ -162,7 +163,8 @@ tests += loadtest restest1 preloadtest l tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \ tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \ tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 + unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2 \ + tst-stackguard1 # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -843,3 +845,6 @@ $(objpfx)order2mod1.so: $(objpfx)order2m $(objpfx)order2mod4.so: $(objpfx)order2mod3.so $(objpfx)order2mod2.so: $(objpfx)order2mod3.so order2mod2.so-no-z-defs = yes + +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" --- libc/elf/tst-stackguard1.c.jj 2005-06-23 17:03:19.000000000 +0200 +++ libc/elf/tst-stackguard1.c 2005-06-25 10:21:29.000000000 +0200 @@ -0,0 +1,196 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = STACK_CHK_GUARD; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed between constructor and do_test"); + return 1; + } + + if (child) + { + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_CHILD: \ + child = true; \ + break; +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" --- libc/elf/rtld.c.jj 2005-06-23 12:15:47.000000000 +0200 +++ libc/elf/rtld.c 2005-06-25 10:17:48.000000000 +0200 @@ -80,6 +80,12 @@ char **_dl_argv attribute_relro = NULL; #endif INTDEF(_dl_argv) +#ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + in thread local area. */ +uintptr_t __stack_chk_guard attribute_relro; +#endif + /* Nonzero if we were run directly. */ unsigned int _dl_skip_args attribute_relro attribute_hidden; @@ -1398,9 +1404,6 @@ ld.so does not support TLS, but program always allocate the static block, we never defer it even if no DF_STATIC_TLS bit is set. The reason is that we know glibc will use the static model. */ -# ifndef TLS_INIT_TP_EXPENSIVE -# define TLS_INIT_TP_EXPENSIVE 0 -# endif /* Since we start using the auditing DSOs right away we need to initialize the data structures now. */ @@ -1807,10 +1810,18 @@ ERROR: ld.so: object '%s' cannot be load used. Trying to do it lazily is too hairy to try when there could be multiple threads (from a non-TLS-using libpthread). */ bool was_tls_init_tp_called = tls_init_tp_called; - if (tcbp == NULL && (!TLS_INIT_TP_EXPENSIVE || GL(dl_tls_max_dtv_idx) > 0)) + if (tcbp == NULL) tcbp = init_tls (); #endif + /* Set up the stack checker's canary. */ + uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (); +#ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +#else + __stack_chk_guard = stack_chk_guard; +#endif + if (__builtin_expect (mode, normal) != normal) { /* We were run just to list the shared libraries. It is @@ -2230,29 +2241,26 @@ ERROR: ld.so: object '%s' cannot be load #endif #ifdef USE_TLS - if (GL(dl_tls_max_dtv_idx) > 0 || USE___THREAD || !TLS_INIT_TP_EXPENSIVE) - { - if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) - ++GL(dl_tls_generation); + if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0) + ++GL(dl_tls_generation); - /* Now that we have completed relocation, the initializer data - for the TLS blocks has its final values and we can copy them - into the main thread's TLS area, which we allocated above. */ - _dl_allocate_tls_init (tcbp); - - /* And finally install it for the main thread. If ld.so itself uses - TLS we know the thread pointer was initialized earlier. */ - if (! tls_init_tp_called) - { - const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); - if (__builtin_expect (lossage != NULL, 0)) - _dl_fatal_printf ("cannot set up thread-local storage: %s\n", - lossage); - } + /* Now that we have completed relocation, the initializer data + for the TLS blocks has its final values and we can copy them + into the main thread's TLS area, which we allocated above. */ + _dl_allocate_tls_init (tcbp); + + /* And finally install it for the main thread. If ld.so itself uses + TLS we know the thread pointer was initialized earlier. */ + if (! tls_init_tp_called) + { + const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); + if (__builtin_expect (lossage != NULL, 0)) + _dl_fatal_printf ("cannot set up thread-local storage: %s\n", + lossage); } - else +#else + NONTLS_INIT_TP; #endif - NONTLS_INIT_TP; #ifdef SHARED /* Auditing checkpoint: we have added all objects. */ --- libc/elf/Versions.jj 2005-05-03 21:50:14.000000000 +0200 +++ libc/elf/Versions 2005-06-23 12:22:09.000000000 +0200 @@ -43,6 +43,10 @@ ld { # runtime interface to TLS __tls_get_addr; } + GLIBC_2.4 { + # stack canary + __stack_chk_guard; + } GLIBC_PRIVATE { # Those are in the dynamic linker, but used by libc.so. __libc_enable_secure; --- libc/elf/tst-stackguard1-static.c.jj 2005-06-23 18:41:42.000000000 +0200 +++ libc/elf/tst-stackguard1-static.c 2005-06-23 18:45:33.000000000 +0200 @@ -0,0 +1 @@ +#include "tst-stackguard1.c" --- libc/elf/stackguard-macros.h.jj 2005-06-23 16:58:17.000000000 +0200 +++ libc/elf/stackguard-macros.h 2005-06-25 10:22:05.000000000 +0200 @@ -0,0 +1,30 @@ +#include + +#ifdef __i386__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("movl %%gs:0x14, %0" : "=r" (x)); x; }) +#elif defined __x86_64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("movq %%fs:0x28, %0" : "=r" (x)); x; }) +#elif defined __powerpc64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ld %0,-28688(13)" : "=r" (x)); x; }) +#elif defined __powerpc__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("lwz %0,-28680(2)" : "=r" (x)); x; }) +#elif defined __sparc__ && defined __arch64__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ldx [%%g7+0x28], %0" : "=r" (x)); x; }) +#elif defined __sparc__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ld [%%g7+0x14], %0" : "=r" (x)); x; }) +#elif defined __s390x__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ear %0,%a0; sllg %0,%0,32; ear %0,%a1; lg %0,0x28(%0)" : "=r" (x)); x; }) +#elif defined __s390__ +# define STACK_CHK_GUARD \ + ({ uintptr_t x; asm ("ear %0,%%a0; l %0,0x14(%0)" : "=r" (x)); x; }) +#else +extern uintptr_t __stack_chk_guard; +# define STACK_CHK_GUARD __stack_chk_guard +#endif --- libc/sysdeps/unix/sysv/linux/dl-osinfo.h.jj 2005-06-06 11:41:17.000000000 +0200 +++ libc/sysdeps/unix/sysv/linux/dl-osinfo.h 2005-06-23 16:08:51.000000000 +0200 @@ -23,6 +23,7 @@ #include #include "kernel-features.h" #include +#include #ifndef MIN # define MIN(a,b) (((a)<(b))?(a):(b)) @@ -157,3 +158,24 @@ _dl_discover_osversion (void) else if (__LINUX_KERNEL_VERSION > 0) \ FATAL ("FATAL: cannot determine kernel version\n"); \ } while (0) + +static inline uintptr_t __attribute__ ((always_inline)) +_dl_setup_stack_chk_guard (void) +{ + uintptr_t ret; +#ifdef ENABLE_STACKGUARD_RANDOMIZE + int fd = __open ("/dev/urandom", O_RDONLY); + if (fd >= 0) + { + ssize_t reslen = __read (fd, &ret, sizeof (ret)); + __close (fd); + if (reslen == (ssize_t) sizeof (ret)) + return ret; + } +#endif + ret = 0; + unsigned char *p = (unsigned char *) &ret; + p[sizeof (ret) - 1] = 255; + p[sizeof (ret) - 2] = '\n'; + return ret; +} --- libc/sysdeps/generic/libc-start.c.jj 2005-02-21 17:20:16.000000000 +0100 +++ libc/sysdeps/generic/libc-start.c 2005-06-25 10:19:02.000000000 +0200 @@ -35,6 +35,11 @@ extern void __pthread_initialize_minimal __attribute__ ((weak)) # endif ; +# ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + in thread local area. */ +uintptr_t __stack_chk_guard attribute_relro; +# endif #endif #ifdef HAVE_PTR_NTHREADS @@ -152,6 +157,16 @@ LIBC_START_MAIN (int (*main) (int, char __pthread_initialize_minimal (); #endif +# ifndef SHARED + /* Set up the stack checker's canary. */ + uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (); +# ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +# else + __stack_chk_guard = stack_chk_guard; +# endif +#endif + /* Register the destructor of the dynamic linker if there is any. */ if (__builtin_expect (rtld_fini != NULL, 1)) __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL); --- libc/sysdeps/generic/libc-tls.c.jj 2005-02-25 14:45:06.000000000 +0100 +++ libc/sysdeps/generic/libc-tls.c 2005-06-23 16:28:55.000000000 +0200 @@ -133,17 +133,6 @@ __libc_setup_tls (size_t tcbsize, size_t break; } -#ifdef TLS_INIT_TP_EXPENSIVE - if (memsz == 0 && tcbsize <= TLS_INIT_TCB_SIZE) - { - /* We do not need a TLS block and no thread descriptor. */ -# ifdef NONTLS_INIT_TP - NONTLS_INIT_TP; -# endif - return; - } -#endif - /* We have to set up the TCB block which also (possibly) contains 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. Instead we use 'sbrk' which would only uses 'errno' if it fails. --- libc/sysdeps/generic/dl-osinfo.h.jj 2005-05-03 21:50:44.000000000 +0200 +++ libc/sysdeps/generic/dl-osinfo.h 2005-06-23 18:28:55.000000000 +0200 @@ -1 +1,12 @@ -/* Nothing needed in general. */ +#include + +static inline uintptr_t __attribute__ ((always_inline)) +_dl_setup_stack_chk_guard (void) +{ + uintptr_t ret = 0; + unsigned char *p = (unsigned char *) &ret; + p[sizeof (ret) - 1] = 255; + p[sizeof (ret) - 2] = '\n'; + p[0] = 0; + return ret; +} --- libc/nptl/Makefile.jj 2005-04-27 14:03:51.000000000 +0200 +++ libc/nptl/Makefile 2005-06-23 19:16:08.000000000 +0200 @@ -269,7 +269,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-c tst-oncex3 tst-oncex4 endif ifeq ($(build-shared),yes) -tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 +tests += tst-atfork2 tst-tls3 tst-tls4 tst-tls5 tst-_res1 tst-fini1 \ + tst-stackguard1 tests-nolibpthread += tst-fini1 ifeq ($(have-z-execstack),yes) tests += tst-execstack @@ -337,7 +338,8 @@ link-libc-static := $(common-objpfx)libc $(common-objpfx)libc.a ifeq ($(build-static),yes) -tests-static += tst-locale1 tst-locale2 +tests-static += tst-locale1 tst-locale2 tst-stackguard1-static +tests += tst-stackguard1-static xtests-static += tst-setuid1-static endif # These tests are linked with libc before libpthread @@ -586,6 +588,9 @@ LDFLAGS-tst-execstack = -Wl,-z,noexecsta $(objpfx)tst-fini1mod.so: $(shared-thread-library) +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" + # The tests here better do not run in parallel ifneq ($(filter %tests,$(MAKECMDGOALS)),) .NOTPARALLEL: --- libc/nptl/sysdeps/s390/tls.h.jj 2005-05-23 18:22:04.000000000 +0200 +++ libc/nptl/sysdeps/s390/tls.h 2005-06-23 12:22:09.000000000 +0200 @@ -48,9 +48,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; -# ifdef NEED_DL_SYSINFO uintptr_t sysinfo; -# endif + uintptr_t stack_guard; } tcbhead_t; # ifndef __s390x__ @@ -158,6 +157,13 @@ typedef struct #define THREAD_SETMEM_NC(descr, member, idx, value) \ descr->member[idx] = (value) +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ --- libc/nptl/sysdeps/powerpc/tls.h.jj 2005-05-03 21:50:31.000000000 +0200 +++ libc/nptl/sysdeps/powerpc/tls.h 2005-06-23 12:22:09.000000000 +0200 @@ -65,11 +65,11 @@ typedef union dtv /* Get the thread descriptor definition. */ # include -/* This layout is actually wholly private and not affected by the ABI. - Nor does it overlap the pthread data structure, so we need nothing - extra here at all. */ +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv field is private. */ typedef struct { + uintptr_t stack_guard; dtv_t *dtv; } tcbhead_t; @@ -127,7 +127,7 @@ register void *__thread_register __asm__ /* Return the address of the dtv for the current thread. */ # define THREAD_DTV() \ - (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) /* Return the thread descriptor for the current thread. */ # define THREAD_SELF \ @@ -136,9 +136,9 @@ register void *__thread_register __asm__ /* Magic for libthread_db to know how to do THREAD_SELF. */ # define DB_THREAD_SELF \ - REGISTER (32, 32, PT_THREAD_POINTER * 4, \ + REGISTER (32, 32, PT_THREAD_POINTER * 4, \ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \ - REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) /* Read member of the thread descriptor directly. */ @@ -156,6 +156,16 @@ register void *__thread_register __asm__ # define THREAD_SETMEM_NC(descr, member, idx, value) \ ((void)(descr), (THREAD_SELF)->member[idx] = (value)) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + /* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some different value to mean unset l_tls_offset. */ # define NO_TLS_OFFSET -1 --- libc/nptl/sysdeps/sparc/tls.h.jj 2005-05-23 18:22:05.000000000 +0200 +++ libc/nptl/sysdeps/sparc/tls.h 2005-06-23 12:22:09.000000000 +0200 @@ -46,6 +46,8 @@ typedef struct dtv_t *dtv; void *self; int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -126,6 +128,13 @@ register struct pthread *__thread_self _ #define THREAD_SETMEM_NC(descr, member, idx, value) \ descr->member[idx] = (value) +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + #endif /* !ASSEMBLER */ #endif /* tls.h */ --- libc/nptl/sysdeps/i386/tls.h.jj 2005-05-23 18:22:02.000000000 +0200 +++ libc/nptl/sysdeps/i386/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -49,6 +49,7 @@ typedef struct void *self; /* Pointer to the thread descriptor. */ int multiple_threads; uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; # define TLS_MULTIPLE_THREADS_IN_TCB 1 @@ -416,6 +417,14 @@ union user_desc_init __res; }) +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ --- libc/nptl/sysdeps/x86_64/tls.h.jj 2005-05-23 18:22:11.000000000 +0200 +++ libc/nptl/sysdeps/x86_64/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -47,6 +47,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -320,6 +322,13 @@ typedef struct __res; }) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ --- libc/nptl/tst-stackguard1.c.jj 2005-06-23 17:03:19.000000000 +0200 +++ libc/nptl/tst-stackguard1.c 2005-06-25 10:23:33.000000000 +0200 @@ -0,0 +1,226 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = STACK_CHK_GUARD; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static void * +tf (void *arg) +{ + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed in thread"); + return (void *) 1L; + } + return NULL; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed between constructor and do_test"); + return 1; + } + + if (child) + { + int i; + pthread_t th[4]; + void *ret; + for (i = 0; i < 4; ++i) + if (pthread_create (&th[i], NULL, tf, NULL)) + { + puts ("thread creation failed"); + return 1; + } + for (i = 0; i < 4; ++i) + if (pthread_join (th[i], &ret)) + { + puts ("thread join failed"); + return 1; + } + else if (ret != NULL) + return 1; + + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_CHILD: \ + child = true; \ + break; +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" --- libc/nptl/pthread_create.c.jj 2005-05-03 21:50:28.000000000 +0200 +++ libc/nptl/pthread_create.c 2005-06-23 12:22:14.000000000 +0200 @@ -399,6 +399,11 @@ __pthread_create_2_1 (newthread, attr, s pd->schedpolicy = self->schedpolicy; pd->schedparam = self->schedparam; + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (pd); +#endif + /* Determine scheduling parameters for the thread. */ if (attr != NULL && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0) --- libc/nptl/tst-stackguard1-static.c.jj 2005-06-23 18:41:42.000000000 +0200 +++ libc/nptl/tst-stackguard1-static.c 2005-06-23 19:15:12.000000000 +0200 @@ -0,0 +1 @@ +#include "tst-stackguard1.c" --- libc/debug/Makefile.jj 2005-05-03 21:50:13.000000000 +0200 +++ libc/debug/Makefile 2005-06-23 12:56:11.000000000 +0200 @@ -31,9 +31,9 @@ routines = backtrace backtracesyms back printf_chk fprintf_chk vprintf_chk vfprintf_chk \ gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ read_chk pread_chk pread64_chk recv_chk recvfrom_chk \ - readlink_chk getwd_chk getcwd_chk \ + readlink_chk getwd_chk getcwd_chk stack_chk_fail \ $(static-only-routines) -static-only-routines := warning-nop +static-only-routines := warning-nop stack_chk_fail_local CFLAGS-backtrace.c = -fno-omit-frame-pointer CFLAGS-sprintf_chk.c = -D_IO_MTSAFE_IO --- libc/debug/stack_chk_fail_local.c.jj 2005-06-23 12:52:34.000000000 +0200 +++ libc/debug/stack_chk_fail_local.c 2005-06-23 12:55:57.000000000 +0200 @@ -0,0 +1,30 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern void __stack_chk_fail (void) __attribute__ ((noreturn)); + +/* On some architectures, this helps needless PIC pointer setup + that would be needed just for the __stack_chk_fail call. */ + +void __attribute__ ((noreturn)) attribute_hidden +__stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} --- libc/debug/stack_chk_fail.c.jj 2005-06-23 12:22:14.000000000 +0200 +++ libc/debug/stack_chk_fail.c 2005-06-25 10:48:42.000000000 +0200 @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +extern char **__libc_argv attribute_hidden; + +void +__attribute__ ((noreturn)) +__stack_chk_fail (void) +{ + /* The loop is added only to keep gcc happy. */ + while (1) + __libc_message (1, "*** stack smashing detected ***: %s terminated\n", + __libc_argv[0] ?: ""); +} --- libc/debug/Versions.jj 2005-05-03 21:50:13.000000000 +0200 +++ libc/debug/Versions 2005-06-23 12:22:53.000000000 +0200 @@ -23,5 +23,7 @@ libc { __read_chk; __pread_chk; __pread64_chk; __readlink_chk; __getcwd_chk; __getwd_chk; __recv_chk; __recvfrom_chk; + + __stack_chk_fail; } } --- libc/config.h.in.jj 2005-06-22 18:34:09.000000000 +0200 +++ libc/config.h.in 2005-06-23 13:25:00.000000000 +0200 @@ -223,6 +223,9 @@ /* Define if your assembler and linker support R_PPC_REL16* relocs. */ #undef HAVE_ASM_PPC_REL16 +/* Define if __stack_chk_guard canary should be randomized at program startup. */ +#undef ENABLE_STACKGUARD_RANDOMIZE + /* */ --- libc/Versions.def.jj 2005-05-03 21:50:05.000000000 +0200 +++ libc/Versions.def 2005-06-23 14:02:50.000000000 +0200 @@ -102,6 +102,7 @@ ld { GLIBC_2.0 GLIBC_2.1 GLIBC_2.3 + GLIBC_2.4 GLIBC_PRIVATE } libthread_db { --- libc/linuxthreads/Makefile.jj 2005-02-08 17:17:06.000000000 +0100 +++ libc/linuxthreads/Makefile 2005-06-23 19:19:09.000000000 +0200 @@ -117,13 +117,14 @@ test-srcs = tst-signal tests-reverse += tst-cancel5 ifeq ($(build-static),yes) -tests += tststatic tst-static-locale tst-cancel-static -tests-static += tststatic tst-static-locale tst-cancel-static +tests += tststatic tst-static-locale tst-cancel-static tst-stackguard1-static +tests-static += tststatic tst-static-locale tst-cancel-static \ + tst-stackguard1-static endif ifeq (yes,$(build-shared)) tests-nodelete-yes = unload -tests += tst-tls1 tst-_res1 +tests += tst-tls1 tst-_res1 tst-stackguard1 endif modules-names = tst-_res1mod1 tst-_res1mod2 \ @@ -343,3 +344,6 @@ $(objpfx)tst-cancel-wrappers.out: tst-ca generated += tst-signal.out tst-cancel-wrappers.out endif endif + +tst-stackguard1-ARGS = --command "$(built-program-cmd) --child" +tst-stackguard1-static-ARGS = --command "$(objpfx)tst-stackguard1-static --child" --- libc/linuxthreads/sysdeps/s390/tls.h.jj 2005-05-03 21:50:22.000000000 +0200 +++ libc/linuxthreads/sysdeps/s390/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -44,6 +45,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -122,9 +125,16 @@ typedef struct # define THREAD_DTV() \ (((tcbhead_t *) __builtin_thread_pointer ())->dtv) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif /* __ASSEMBLER__ */ -#else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#else /* HAVE_TLS_SUPPORT */ # ifndef __ASSEMBLER__ @@ -140,6 +150,6 @@ typedef struct # endif /* __ASSEMBLER__ */ -#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#endif /* HAVE_TLS_SUPPORT */ #endif /* tls.h */ --- libc/linuxthreads/sysdeps/powerpc/tls.h.jj 2005-05-03 21:50:21.000000000 +0200 +++ libc/linuxthreads/sysdeps/powerpc/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -48,11 +49,11 @@ typedef union dtv # ifndef __ASSEMBLER__ -/* This layout is actually wholly private and not affected by the ABI. - Nor does it overlap the pthread data structure, so we need nothing - extra here at all. */ +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv field is private. */ typedef struct { + uintptr_t stack_guard; dtv_t *dtv; } tcbhead_t; @@ -79,7 +80,7 @@ typedef struct assume that the pthread_descr is allocated immediately ahead of the TCB. This implies that the pthread_descr address is TP - (TLS_PRE_TCB_SIZE + 0x7000). */ -#define TLS_TCB_OFFSET 0x7000 +# define TLS_TCB_OFFSET 0x7000 /* The DTV is allocated at the TP; the TCB is placed elsewhere. */ /* This is not really true for powerpc64. We are following alpha @@ -138,6 +139,16 @@ typedef struct different value to mean unset l_tls_offset. */ # define NO_TLS_OFFSET -1 +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + # endif /* __ASSEMBLER__ */ #elif !defined __ASSEMBLER__ @@ -148,16 +159,16 @@ typedef struct single-threaded and multi-threaded code. */ typedef struct { - void *tcb; /* Never used. */ - dtv_t *dtv; /* Never used. */ - void *self; /* Used only if multithreaded, and rarely. */ - int multiple_threads; /* Only this member is really used. */ + uintptr_t stack_guard; + int multiple_threads; } tcbhead_t; #define NONTLS_INIT_TP \ do { \ static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ - __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + char *addr; \ + __asm ("" : "r" (addr) : "0" (&nontls_init_tp[1])); \ + __thread_self = (__typeof (__thread_self)) (addr + TLS_TCB_OFFSET); \ } while (0) #endif /* HAVE_TLS_SUPPORT */ --- libc/linuxthreads/sysdeps/sparc/tls.h.jj 2005-05-03 21:50:23.000000000 +0200 +++ libc/linuxthreads/sysdeps/sparc/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -44,6 +45,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -99,6 +102,13 @@ typedef struct # define THREAD_DTV() \ (((tcbhead_t *) __thread_self)->dtv) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif #else --- libc/linuxthreads/sysdeps/i386/tls.h.jj 2005-05-03 21:50:21.000000000 +0200 +++ libc/linuxthreads/sysdeps/i386/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -47,9 +47,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; -#ifdef NEED_DL_SYSINFO uintptr_t sysinfo; -#endif + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -224,6 +223,13 @@ TLS_DO_MODIFY_LDT_KERNEL_CHECK( ({ struct _pthread_descr_struct *__descr; \ THREAD_GETMEM (__descr, p_header.data.dtvp); }) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ #endif /* __ASSEMBLER__ */ --- libc/linuxthreads/sysdeps/x86_64/tls.h.jj 2005-05-03 21:50:25.000000000 +0200 +++ libc/linuxthreads/sysdeps/x86_64/tls.h 2005-06-23 12:22:14.000000000 +0200 @@ -25,6 +25,7 @@ # include # include # include +# include /* Type for the dtv. */ typedef union dtv @@ -45,6 +46,8 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -128,6 +131,13 @@ typedef struct ({ struct _pthread_descr_struct *__descr; \ THREAD_GETMEM (__descr, p_header.data.dtvp); }) +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, p_header.data.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->p_header.data.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, p_header.data.stack_guard)) + # endif /* HAVE_TLS_SUPPORT */ #endif /* __ASSEMBLER__ */ --- libc/linuxthreads/pthread.c.jj 2005-01-19 14:12:43.000000000 +0100 +++ libc/linuxthreads/pthread.c 2005-06-23 23:01:11.000000000 +0200 @@ -696,6 +696,11 @@ int __pthread_initialize_manager(void) mgr = &__pthread_manager_thread; #endif + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (mgr); +#endif + __pthread_manager_request = manager_pipe[1]; /* writing end */ __pthread_manager_reader = manager_pipe[0]; /* reading end */ --- libc/linuxthreads/manager.c.jj 2005-05-03 21:50:20.000000000 +0200 +++ libc/linuxthreads/manager.c 2005-06-23 12:22:14.000000000 +0200 @@ -698,6 +698,12 @@ static int pthread_handle_create(pthread new_thread->p_start_args.start_routine = start_routine; new_thread->p_start_args.arg = arg; new_thread->p_start_args.mask = *mask; + + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (new_thread); +#endif + /* Make the new thread ID available already now. If any of the later functions fail we return an error value and the caller must not use the stored thread ID. */ --- libc/linuxthreads/tst-stackguard1.c.jj 2005-06-23 17:03:19.000000000 +0200 +++ libc/linuxthreads/tst-stackguard1.c 2005-06-25 10:23:33.000000000 +0200 @@ -0,0 +1,226 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *command; +static bool child; +static uintptr_t stack_chk_guard_copy; +static bool stack_chk_guard_copy_set; +static int fds[2]; + +static void __attribute__ ((constructor)) +con (void) +{ + stack_chk_guard_copy = STACK_CHK_GUARD; + stack_chk_guard_copy_set = true; +} + +static int +uintptr_t_cmp (const void *a, const void *b) +{ + if (*(uintptr_t *) a < *(uintptr_t *) b) + return 1; + if (*(uintptr_t *) a > *(uintptr_t *) b) + return -1; + return 0; +} + +static void * +tf (void *arg) +{ + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed in thread"); + return (void *) 1L; + } + return NULL; +} + +static int +do_test (void) +{ + if (!stack_chk_guard_copy_set) + { + puts ("constructor has not been run"); + return 1; + } + + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed between constructor and do_test"); + return 1; + } + + if (child) + { + int i; + pthread_t th[4]; + void *ret; + for (i = 0; i < 4; ++i) + if (pthread_create (&th[i], NULL, tf, NULL)) + { + puts ("thread creation failed"); + return 1; + } + for (i = 0; i < 4; ++i) + if (pthread_join (th[i], &ret)) + { + puts ("thread join failed"); + return 1; + } + else if (ret != NULL) + return 1; + + write (2, &stack_chk_guard_copy, sizeof (stack_chk_guard_copy)); + return 0; + } + + if (command == NULL) + { + puts ("missing --command or --child argument"); + return 1; + } + +#define N 16 + uintptr_t child_stack_chk_guards[N + 1]; + child_stack_chk_guards[N] = stack_chk_guard_copy; + int i; + for (i = 0; i < N; ++i) + { + if (pipe (fds) < 0) + { + printf ("couldn't create pipe: %m\n"); + return 1; + } + + pid_t pid = fork (); + if (pid < 0) + { + printf ("fork failed: %m\n"); + return 1; + } + + if (!pid) + { + if (stack_chk_guard_copy != STACK_CHK_GUARD) + { + puts ("STACK_CHK_GUARD changed after fork"); + exit (1); + } + + close (fds[0]); + close (2); + dup2 (fds[1], 2); + close (fds[1]); + + system (command); + exit (0); + } + + close (fds[1]); + + if (TEMP_FAILURE_RETRY (read (fds[0], &child_stack_chk_guards[i], + sizeof (uintptr_t))) != sizeof (uintptr_t)) + { + puts ("could not read stack_chk_guard value from child"); + return 1; + } + + close (fds[0]); + + pid_t termpid; + int status; + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("waitpid failed: %m\n"); + return 1; + } + else if (termpid != pid) + { + printf ("waitpid returned %ld != %ld\n", + (long int) termpid, (long int) pid); + return 1; + } + else if (!WIFEXITED (status) || WEXITSTATUS (status)) + { + puts ("child hasn't exited with exit status 0"); + return 1; + } + } + + qsort (child_stack_chk_guards, N + 1, sizeof (uintptr_t), uintptr_t_cmp); + + uintptr_t default_guard = 0; + unsigned char *p = (unsigned char *) &default_guard; + p[sizeof (uintptr_t) - 1] = 255; + p[sizeof (uintptr_t) - 2] = '\n'; + p[0] = 0; + + /* Test if the stack guard canaries are either randomized, + or equal to the default stack guard canary value. + Even with randomized stack guards it might happen + that the random number generator generates the same + values, but if that happens in more than half from + the 16 runs, something is very wrong. */ + int ndifferences = 0; + int ndefaults = 0; + for (i = 0; i < N; ++i) + { + if (child_stack_chk_guards[i] != child_stack_chk_guards[i+1]) + ndifferences++; + else if (child_stack_chk_guards[i] == default_guard) + ndefaults++; + } + + printf ("differences %d defaults %d\n", ndifferences, ndefaults); + + if (ndifferences < N / 2 && ndefaults < N / 2) + { + puts ("stack guard canaries are not randomized enough"); + puts ("nor equal to the default canary value"); + return 1; + } + + return 0; +} + +#define OPT_COMMAND 10000 +#define OPT_CHILD 10001 +#define CMDLINE_OPTIONS \ + { "command", required_argument, NULL, OPT_COMMAND }, \ + { "child", no_argument, NULL, OPT_CHILD }, +#define CMDLINE_PROCESS \ + case OPT_COMMAND: \ + command = optarg; \ + break; \ + case OPT_CHILD: \ + child = true; \ + break; +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" --- libc/linuxthreads/descr.h.jj 2005-05-03 21:50:20.000000000 +0200 +++ libc/linuxthreads/descr.h 2005-06-23 12:22:14.000000000 +0200 @@ -120,9 +120,8 @@ struct _pthread_descr_struct union dtv *dtvp; pthread_descr self; /* Pointer to this structure */ int multiple_threads; -# ifdef NEED_DL_SYSINFO uintptr_t sysinfo; -# endif + uintptr_t stack_guard; } data; void *__padding[16]; } p_header; --- libc/linuxthreads/tst-stackguard1-static.c.jj 2005-06-23 18:41:42.000000000 +0200 +++ libc/linuxthreads/tst-stackguard1-static.c 2005-06-23 19:15:12.000000000 +0200 @@ -0,0 +1 @@ +#include "tst-stackguard1.c" --- libc/configure.in.jj 2005-06-22 18:34:10.000000000 +0200 +++ libc/configure.in 2005-06-23 13:22:56.000000000 +0200 @@ -174,6 +174,15 @@ else fi AC_SUBST(oldest_abi) +AC_ARG_ENABLE([stackguard-randomization], + AC_HELP_STRING([--enable-stackguard-randomization], + [initialize __stack_chk_guard canary with a random number at program start]), + [enable_stackguard_randomize=$enableval], + [enable_stackguard_randomize=no]) +if test "$enable_stackguard_randomize" = yes; then + AC_DEFINE(ENABLE_STACKGUARD_RANDOMIZE) +fi + dnl Generic infrastructure for drop-in additions to libc. AC_ARG_ENABLE([add-ons], AC_HELP_STRING([--enable-add-ons@<:@=DIRS...@:>@], --- libc/configure.jj 2005-06-22 18:34:09.000000000 +0200 +++ libc/configure 2005-06-23 13:23:16.000000000 +0200 @@ -873,6 +873,9 @@ Optional Features: objects [default=yes if supported] --enable-oldest-abi=ABI configure the oldest ABI supported [e.g. 2.2] [default=glibc default] + --enable-stackguard-randomization + initialize __stack_chk_guard canary with a random + number at program start --enable-add-ons[=DIRS...] configure and build add-ons in DIR1,DIR2,... search for add-ons if no parameter given @@ -1597,6 +1600,20 @@ _ACEOF fi +# Check whether --enable-stackguard-randomization or --disable-stackguard-randomization was given. +if test "${enable_stackguard_randomization+set}" = set; then + enableval="$enable_stackguard_randomization" + enable_stackguard_randomize=$enableval +else + enable_stackguard_randomize=no +fi; +if test "$enable_stackguard_randomize" = yes; then + cat >>confdefs.h <<\_ACEOF +#define ENABLE_STACKGUARD_RANDOMIZE 1 +_ACEOF + +fi + # Check whether --enable-add-ons or --disable-add-ons was given. if test "${enable_add_ons+set}" = set; then enableval="$enable_add_ons" Jakub From jakub@redhat.com Sat Jun 25 10:27:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Sat, 25 Jun 2005 10:27:00 -0000 Subject: [PATCH] Fix xdr_{,u_}{hyper,longlong_t} on 64-bit architectures Message-ID: <20050625102730.GE7663@sunsite.mff.cuni.cz> Hi! As the testcase shows, decoding long long values does not work on 64-bit architectures - if bit 31 is set, then all upper 32 bits were set to 1. 2005-06-25 Jakub Jelinek * sunrpc/xdr.c (xdr_hyper, xdr_u_hyper): When decoding, cast t2 to uint32_t instead of ulong. * sunrpc/Makefile (tests): Add tst-xdrmem. * sunrpc/tst-xdrmem.c: New test. --- libc/sunrpc/xdr.c.jj 2005-04-26 12:06:48.000000000 +0200 +++ libc/sunrpc/xdr.c 2005-06-25 12:22:07.000000000 +0200 @@ -239,7 +239,7 @@ xdr_hyper (XDR *xdrs, quad_t *llp) if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) return FALSE; *llp = ((quad_t) t1) << 32; - *llp |= (unsigned long int) t2; + *llp |= (uint32_t) t2; return TRUE; } @@ -272,7 +272,7 @@ xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) return FALSE; *ullp = ((u_quad_t) t1) << 32; - *ullp |= (unsigned long int) t2; + *ullp |= (uint32_t) t2; return TRUE; } --- libc/sunrpc/Makefile.jj 2005-06-06 11:43:31.000000000 +0200 +++ libc/sunrpc/Makefile 2005-06-25 12:19:57.000000000 +0200 @@ -85,6 +85,7 @@ all: # Make this the default target; it include ../Makeconfig +tests = tst-xdrmem xtests := tst-getmyaddr ifeq ($(have-thread-library),yes) --- libc/sunrpc/tst-xdrmem.c.jj 2005-06-25 11:10:55.000000000 +0200 +++ libc/sunrpc/tst-xdrmem.c 2005-06-25 12:21:26.000000000 +0200 @@ -0,0 +1,205 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +static int +do_test (void) +{ + XDR xdrs; + unsigned char buf[8192]; + int v_int; + u_int v_u_int; + long v_long; + u_long v_u_long; + quad_t v_hyper; + u_quad_t v_u_hyper; + quad_t v_longlong_t; + u_quad_t v_u_longlong_t; + short v_short; + u_short v_u_short; + char v_char; + u_char v_u_char; + bool_t v_bool; + enum_t v_enum; + char *v_wrapstring; + + xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_ENCODE); + +#define TESTS \ + T(int, 0) \ + T(int, CHAR_MAX) \ + T(int, CHAR_MIN) \ + T(int, SHRT_MAX) \ + T(int, SHRT_MIN) \ + T(int, INT_MAX) \ + T(int, INT_MIN) \ + T(int, 0x123) \ + T(u_int, 0) \ + T(u_int, UCHAR_MAX) \ + T(u_int, USHRT_MAX) \ + T(u_int, UINT_MAX) \ + T(u_int, 0xdeadbeef) \ + T(u_int, 0x12345678) \ + T(long, 0) \ + T(long, 2147483647L) \ + T(long, -2147483648L) \ + T(long, -305419896L) \ + T(long, -305419896L) \ + T(u_long, 0) \ + T(u_long, 0xffffffffUL) \ + T(u_long, 0xdeadbeefUL) \ + T(u_long, 0x12345678UL) \ + T(hyper, 0) \ + T(hyper, CHAR_MAX) \ + T(hyper, CHAR_MIN) \ + T(hyper, SHRT_MAX) \ + T(hyper, SHRT_MIN) \ + T(hyper, INT_MAX) \ + T(hyper, INT_MIN) \ + T(hyper, LONG_MAX) \ + T(hyper, LONG_MIN) \ + T(hyper, LONG_LONG_MAX) \ + T(hyper, LONG_LONG_MIN) \ + T(hyper, 0x12312345678LL) \ + T(hyper, 0x12387654321LL) \ + T(u_hyper, 0) \ + T(u_hyper, UCHAR_MAX) \ + T(u_hyper, USHRT_MAX) \ + T(u_hyper, UINT_MAX) \ + T(u_hyper, ULONG_MAX) \ + T(u_hyper, ULONG_LONG_MAX) \ + T(u_hyper, 0xdeadbeefdeadbeefULL) \ + T(u_hyper, 0x12312345678ULL) \ + T(u_hyper, 0x12387654321ULL) \ + T(longlong_t, 0) \ + T(longlong_t, CHAR_MAX) \ + T(longlong_t, CHAR_MIN) \ + T(longlong_t, SHRT_MAX) \ + T(longlong_t, SHRT_MIN) \ + T(longlong_t, INT_MAX) \ + T(longlong_t, INT_MIN) \ + T(longlong_t, LONG_MAX) \ + T(longlong_t, LONG_MIN) \ + T(longlong_t, LONG_LONG_MAX) \ + T(longlong_t, LONG_LONG_MIN) \ + T(longlong_t, 0x12312345678LL) \ + T(longlong_t, 0x12387654321LL) \ + T(u_longlong_t, 0) \ + T(u_longlong_t, UCHAR_MAX) \ + T(u_longlong_t, USHRT_MAX) \ + T(u_longlong_t, UINT_MAX) \ + T(u_longlong_t, ULONG_MAX) \ + T(u_longlong_t, ULONG_LONG_MAX) \ + T(u_longlong_t, 0xdeadbeefdeadbeefULL)\ + T(u_longlong_t, 0x12312345678ULL) \ + T(u_longlong_t, 0x12387654321ULL) \ + T(short, CHAR_MAX) \ + T(short, CHAR_MIN) \ + T(short, SHRT_MAX) \ + T(short, SHRT_MIN) \ + T(short, 0x123) \ + T(u_short, 0) \ + T(u_short, UCHAR_MAX) \ + T(u_short, USHRT_MAX) \ + T(u_short, 0xbeef) \ + T(u_short, 0x5678) \ + T(char, CHAR_MAX) \ + T(char, CHAR_MIN) \ + T(char, 0x23) \ + T(u_char, 0) \ + T(u_char, UCHAR_MAX) \ + T(u_char, 0xef) \ + T(u_char, 0x78) \ + T(bool, 0) \ + T(bool, 1) \ + T(enum, 0) \ + T(enum, CHAR_MAX) \ + T(enum, CHAR_MIN) \ + T(enum, SHRT_MAX) \ + T(enum, SHRT_MIN) \ + T(enum, INT_MAX) \ + T(enum, INT_MIN) \ + T(enum, 0x123) \ + S(wrapstring, (char *) "") \ + S(wrapstring, (char *) "hello, world") + +#define T(type, val) \ + v_##type = val; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("encoding of " #type \ + " " #val " failed"); \ + return 1; \ + } +#define S(type, val) T(type, val) + + TESTS +#undef T +#undef S + + xdr_destroy (&xdrs); + + xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_DECODE); + +#define T(type, val) \ + v_##type = 0x15; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (v_##type != val) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } +#define S(type, val) \ + v_##type = NULL; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (strcmp (v_##type, val)) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } \ + free (v_##type); \ + v_##type = NULL; + + TESTS +#undef T +#undef S + + xdr_destroy (&xdrs); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" Jakub From drepper@redhat.com Sun Jun 26 18:22:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Sun, 26 Jun 2005 18:22:00 -0000 Subject: [PATCH] glibc part of stack protector (take 2) In-Reply-To: <20050625085455.GD7663@sunsite.mff.cuni.cz> References: <20050623222514.GC7663@sunsite.mff.cuni.cz> <42BC2325.90707@redhat.com> <20050625085455.GD7663@sunsite.mff.cuni.cz> Message-ID: <42BEF204.1000007@redhat.com> I applied the patch. But not the LinuxThreads part. In fact, once I have the time (probably the week after next) LT will be removed from the trunk of the CVS archive. This has *loooong* been announced. We cannot carry forward that crappy code forever. And the 2.4 release is the time to make the break. Programs will know when they cannot run with LT if they reference symbols with version GLIBC_2.4. The code base still exists on the 2.3 branch so there is always the possibility to a) use 2.3 outright, since Roland still backports patches and b) people can build a separate glibc with its own ld.so for desperate LT users. At the same time I'll likely remove the non-TLS support. That's a wakeup call for the Hurd people: get moving with implementing the support. It's been now almost 3 years. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From drepper@redhat.com Sun Jun 26 18:24:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Sun, 26 Jun 2005 18:24:00 -0000 Subject: [PATCH] Fix xdr_{,u_}{hyper,longlong_t} on 64-bit architectures In-Reply-To: <20050625102730.GE7663@sunsite.mff.cuni.cz> References: <20050625102730.GE7663@sunsite.mff.cuni.cz> Message-ID: <42BEF2B3.7050903@redhat.com> Applied. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From drepper@redhat.com Sun Jun 26 19:06:00 2005 From: drepper@redhat.com (Ulrich Drepper) Date: Sun, 26 Jun 2005 19:06:00 -0000 Subject: [PATCH] Cosmetic fix for ia64 strlen [BZ #1016] In-Reply-To: <20050616211238.GR7663@sunsite.mff.cuni.cz> References: <20050616211238.GR7663@sunsite.mff.cuni.cz> Message-ID: <42BEFC61.6000409@redhat.com> Applied. -- ? Ulrich Drepper ? Red Hat, Inc. ? 444 Castro St ? Mountain View, CA ? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 251 bytes Desc: OpenPGP digital signature URL: From jakub@redhat.com Mon Jun 27 21:44:00 2005 From: jakub@redhat.com (Jakub Jelinek) Date: Mon, 27 Jun 2005 21:44:00 -0000 Subject: [PATCH] Stop using > 6 years deprecated switch (BZ #1037) Message-ID: <20050627214442.GH7663@sunsite.mff.cuni.cz> Hi! Already gcc 2.95.x preferred -mcpu=v8 over -mv8... 2005-06-27 Jakub Jelinek [BZ #1037] * sysdeps/unix/sysv/linux/sparc/sparc32/Makefile: -mv8 is deprecated, use -mcpu=v8. --- libc/sysdeps/unix/sysv/linux/sparc/sparc32/Makefile 31 Aug 2003 17:22:46 -0000 1.11 +++ libc/sysdeps/unix/sysv/linux/sparc/sparc32/Makefile 27 Jun 2005 21:38:44 -0000 @@ -4,7 +4,7 @@ LD += -melf32_sparc # When I get this to work, this is the right thing ifeq ($(subdir),elf) -CFLAGS-rtld.c += -mv8 +CFLAGS-rtld.c += -mcpu=v8 #rtld-routines += dl-sysdepsparc sysdep-others += lddlibc4 install-bin += lddlibc4 Jakub