The third argument of gethostbyname_r() is supposed to be a buffer of type char *buf, with no particular memory alignment. This buffer is then casted into a (struct host_data *). This causes a SIGBUS on architecture that does not support unaligned memory access. As it is not possible to change the API, please find a small patch below, which align the buffer before using it. The drawback of this method is that the buffer may be a bit smaller. --- resolv/nss_dns/dns-host.c.orig 2007-04-16 00:13:12.000000000 +0200 +++ resolv/nss_dns/dns-host.c 2007-04-16 00:34:41.000000000 +0200 @@ -78,6 +78,7 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> +#include <obstack.h> #include <sys/syslog.h> #include "nsswitch.h" @@ -465,8 +466,8 @@ char *aliases[MAX_NR_ALIASES]; unsigned char host_addr[16]; /* IPv4 or IPv6 */ char *h_addr_ptrs[0]; - } *host_data = (struct host_data *) buffer; - int linebuflen = buflen - sizeof (struct host_data); + } *host_data; + int linebuflen; register const HEADER *hp; const u_char *end_of_message, *cp; int n, ancount, qdcount; @@ -479,6 +480,10 @@ int have_to_map = 0; int32_t ttl = 0; + /* Align the buffer. */ + host_data = (struct host_data *) __PTR_ALIGN(0, buffer, sizeof(char*) - 1); + linebuflen = buflen - sizeof (struct host_data) - ((char *)host_data - buffer); + if (__builtin_expect (linebuflen, 0) < 0) { /* The buffer is too small. */
Fixed in cvs.
Subject: Bug 4381 CVSROOT: /cvs/glibc Module name: libc Branch: glibc-2_5-branch Changes by: jakub@sourceware.org 2007-07-12 15:10:44 Modified files: . : ChangeLog nis/nss_nis : nis-hosts.c nss/nss_files : files-hosts.c resolv/nss_dns : dns-host.c dns-network.c Log message: 2007-04-23 Jakub Jelinek <jakub@redhat.com> [BZ #4381] * nss/nss_files/files-hosts.c (HOST_DB_LOOKUP): Ensure sufficient alignment of buffer and tmp_buffer. * nis/nss_nis/nis-hosts.c (internal_nis_gethostent_r, internal_gethostbyname2_r, _nss_nis_gethostbyaddr_r): Ensure sufficient alignment of buffer. * resolv/nss_dns/dns-hosts.c (getanswer_r): Likewise. Handle buflen bigger than INT_MAX. * resolv/nss_dns/dns-network.c (getanswer_r): Likewise. Add errnop and h_errnop arguments. Fail if buflen is too small. (_nss_dns_getnetbyname_r, _nss_dns_getnetbyaddr_r): Adjust callers. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/libc/ChangeLog.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.10362.2.69&r2=1.10362.2.70 http://sourceware.org/cgi-bin/cvsweb.cgi/libc/nis/nss_nis/nis-hosts.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.26&r2=1.26.2.1 http://sourceware.org/cgi-bin/cvsweb.cgi/libc/nss/nss_files/files-hosts.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.23&r2=1.23.8.1 http://sourceware.org/cgi-bin/cvsweb.cgi/libc/resolv/nss_dns/dns-host.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.43&r2=1.43.4.1 http://sourceware.org/cgi-bin/cvsweb.cgi/libc/resolv/nss_dns/dns-network.c.diff?cvsroot=glibc&only_with_tag=glibc-2_5-branch&r1=1.21&r2=1.21.2.1