diff options
author | Mike Frysinger <vapier@gentoo.org> | 2008-01-09 05:49:44 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2008-01-09 05:49:44 +0000 |
commit | e0523d622cdf5b96575ce025221ec2533a6b4454 (patch) | |
tree | 8a708bf35f651121317735ddb3f1c3c9fbeecb09 /libc/inet | |
parent | 6c05ed96f646e20a8ef104d36d260fab30486768 (diff) |
Daniel Jacobowitz writes:
MontaVista noticed that when their kernels were configured to trap on unaligned
access gethostbyname_r could mysteriously crash. I tracked this down to an
unaligned buffer being passed to gethostbyname_r from some other part of uClibc
(afraid I don't remember where from any more). We have to pad the beginning of
the buffer to a pointer alignment before we store pointers in it.
Diffstat (limited to 'libc/inet')
-rw-r--r-- | libc/inet/resolv.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 7f9d7d536..591106a24 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -234,6 +234,14 @@ libc_hidden_proto(__ctype_b) #define DPRINTF(X,args...) #endif /* DEBUG */ +/* Make sure the incoming char * buffer is aligned enough to handle our random + * structures. This define is the same as we use for malloc alignment (which + * has same requirements). The offset is the number of bytes we need to adjust + * in order to attain desired alignment. + */ +#define ALIGN_ATTR __alignof__(double __attribute_aligned__ (sizeof(size_t))) +#define ALIGN_BUFFER_OFFSET(buf) ((ALIGN_ATTR - ((size_t)buf % ALIGN_ATTR)) % ALIGN_ATTR) + /* Global stuff (stuff needing to be locked to be thread safe)... */ extern int __nameservers attribute_hidden; @@ -1534,6 +1542,15 @@ int attribute_hidden __read_etc_hosts_r(FILE * fp, const char * name, int type, char *cp, **alias; int aliases, i, ret = HOST_NOT_FOUND; + /* make sure user char * is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + if (unlikely(i)) { + if (buflen < i) + return ERANGE; + buf += i; + buflen -= i; + } + if (buflen < sizeof(char *)*(ALIAS_DIM)) return ERANGE; alias = (char **)buf; @@ -2029,6 +2046,15 @@ int gethostbyname_r(const char * name, DPRINTF("Nothing found in /etc/hosts\n"); + /* make sure user char * is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + if (unlikely(i)) { + if (buflen < i) + return ERANGE; + buf += i; + buflen -= i; + } + *h_errnop = NETDB_INTERNAL; if (buflen < sizeof(*in)) return ERANGE; |