From 5cb23c3c734fad8fcfcd09eef34f666f04a0af5e Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 14 Oct 2010 06:35:05 +0000 Subject: getservice: getservent_r must return ERANGE when buffer is too small This fixes issue introduced by 72e1a1ce186c39f07282398e2af9eb0253e60f15 This should also fix the following testcase to exit with error rather than cause an endless loop. int main(void) { if (getservbyname("non-existing", "udp") == NULL) err(1, "getservbyname"); return 0; } Reported by Pirmin Walthert http://lists.uclibc.org/pipermail/uclibc/2010-August/044277.html Signed-off-by: Natanael Copa Signed-off-by: Bernhard Reutner-Fischer --- libc/inet/getservice.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'libc/inet') diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c index 47d26a262..c38ff80ac 100644 --- a/libc/inet/getservice.c +++ b/libc/inet/getservice.c @@ -69,7 +69,7 @@ int getservent_r(struct servent *result_buf, char **serv_aliases; char **tok = NULL; const size_t aliaslen = sizeof(*serv_aliases) * MAXALIASES; - int ret = ENOENT; + int ret = ERANGE; *result = NULL; if (buflen < aliaslen @@ -77,7 +77,7 @@ int getservent_r(struct servent *result_buf, goto DONE_NOUNLOCK; __UCLIBC_MUTEX_LOCK(mylock); - + ret = ENOENT; if (servp == NULL) setservent(serv_stayopen); if (servp == NULL) @@ -88,7 +88,6 @@ int getservent_r(struct servent *result_buf, servp->line_len = buflen - aliaslen; /* [[:space:]]/[[:space:]][] */ if (!config_read(servp, &tok, MAXALIASES, 3, "# \t/", PARSE_NORMAL)) { - ret = ERANGE; goto DONE; } result_buf->s_name = *(tok++); -- cgit v1.2.3 From 2631ae8aab71c350273fa2d7a787bfcbff258029 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 14 Oct 2010 06:35:08 +0000 Subject: getservice: fix handling of long lines Don't try to be smart by dynamically realloc buffersize as it doesn't work. Instead, be simple and allocate a buffer big enough. This fixes a memory leak when calling getserv{ent,byname,byport} multiple times. To save memory we reduce number of max aliases. We seldomly will need more than 1 anyways. While here, fix segfault that happened if there were too many aliases. Signed-off-by: Natanael Copa Signed-off-by: Bernhard Reutner-Fischer --- libc/inet/getservice.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'libc/inet') diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c index c38ff80ac..183099f5c 100644 --- a/libc/inet/getservice.c +++ b/libc/inet/getservice.c @@ -28,9 +28,11 @@ aliases: case sensitive optional space or tab separated list of other names #include __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); -#define MAXALIASES 35 -#define BUFSZ (80) /* one line */ -#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES)) +#define MINTOKENS 3 +#define MAXALIASES 8 /* we seldomly need more than 1 alias */ +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) static parser_t *servp = NULL; static struct servent serve; @@ -65,10 +67,8 @@ libc_hidden_def(endservent) int getservent_r(struct servent *result_buf, char *buf, size_t buflen, struct servent **result) { - char **alias; - char **serv_aliases; char **tok = NULL; - const size_t aliaslen = sizeof(*serv_aliases) * MAXALIASES; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; int ret = ERANGE; *result = NULL; @@ -87,13 +87,13 @@ int getservent_r(struct servent *result_buf, servp->data_len = aliaslen; servp->line_len = buflen - aliaslen; /* [[:space:]]/[[:space:]][] */ - if (!config_read(servp, &tok, MAXALIASES, 3, "# \t/", PARSE_NORMAL)) { + if (!config_read(servp, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { goto DONE; } result_buf->s_name = *(tok++); result_buf->s_port = htons((u_short) atoi(*(tok++))); result_buf->s_proto = *(tok++); - result_buf->s_aliases = alias = serv_aliases = tok; + result_buf->s_aliases = tok; *result = result_buf; ret = 0; DONE: @@ -106,9 +106,8 @@ libc_hidden_def(getservent_r) static void __initbuf(void) { - if (servbuf) - servbuf_sz += BUFSZ; - servbuf = realloc(servbuf, servbuf_sz); + if (!servbuf) + servbuf = malloc(SBUFSIZE); if (!servbuf) abort(); } @@ -117,9 +116,8 @@ struct servent *getservent(void) { struct servent *result; - do { - __initbuf(); - } while (getservent_r(&serve, servbuf, servbuf_sz, &result) == ERANGE); + __initbuf(); + getservent_r(&serve, servbuf, servbuf_sz, &result); return result; } @@ -154,10 +152,8 @@ struct servent *getservbyname(const char *name, const char *proto) { struct servent *result; - do { - __initbuf(); - } while (getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result) - == ERANGE); + __initbuf(); + getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result); return result; } @@ -187,10 +183,8 @@ struct servent *getservbyport(int port, const char *proto) { struct servent *result; - do { - __initbuf(); - } while (getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result) - == ERANGE); + __initbuf(); + getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result); return result; } libc_hidden_def(getservbyport) -- cgit v1.2.3 From 3dc83600855e3754a9046495751758624ac5bfb7 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 14 Oct 2010 06:35:09 +0000 Subject: getnet: simplify alias handling and reduce MAXALIASES Reduce MAXALIASES to something lower. There will probably never be need for more than 1 alias but we allow a few extra. While here we alos fix segfault when there are too many aliases. Signed-off-by: Natanael Copa Signed-off-by: Bernhard Reutner-Fischer --- libc/inet/getnet.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'libc/inet') diff --git a/libc/inet/getnet.c b/libc/inet/getnet.c index c604b63d3..9049f97af 100644 --- a/libc/inet/getnet.c +++ b/libc/inet/getnet.c @@ -27,9 +27,11 @@ aliases: case sensitive optional space or tab separated list of other names #include __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); -#define MAXALIASES 35 -#define BUFSZ (80) /* one line */ -#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES)) +#define MINTOKENS 2 +#define MAXALIASES 8 +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) static parser_t *netp = NULL; static struct netent nete; @@ -65,10 +67,8 @@ int getnetent_r(struct netent *result_buf, int *h_errnop ) { - char **alias, *cp = NULL; - char **net_aliases; char **tok = NULL; - const size_t aliaslen = sizeof(*net_aliases) * MAXALIASES; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; int ret = ERANGE; *result = NULL; @@ -86,7 +86,7 @@ int getnetent_r(struct netent *result_buf, netp->data_len = aliaslen; netp->line_len = buflen - aliaslen; /* [[:space:]][[:space:]][] */ - if (!config_read(netp, &tok, 3, 2, "# \t/", PARSE_NORMAL)) { + if (!config_read(netp, &tok, MAXTOKENS-1, MINTOKENS, "# \t/", PARSE_NORMAL)) { goto DONE; } result_buf->n_name = *(tok++); @@ -110,16 +110,7 @@ int getnetent_r(struct netent *result_buf, sa4_to_uint32(addri->ai_addr); freeaddrinfo(addri); } - result_buf->n_aliases = alias = net_aliases = tok; - cp = *alias; - while (cp && *cp) { - if (alias < &net_aliases[MAXALIASES - 1]) - *alias++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *alias = NULL; + result_buf->n_aliases = tok; *result = result_buf; ret = 0; DONE: -- cgit v1.2.3 From 7b74c6bab0fc39325a5b9a978a3d8ab73009e5d3 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 14 Oct 2010 06:35:10 +0000 Subject: getproto: increase line buffer size, simlify and fix alias handling We increase line buffer size, reduce MAXALIASES and make sure we don't segfault when there are too manuy aliases in /etc/protocols. Signed-off-by: Natanael Copa Signed-off-by: Bernhard Reutner-Fischer --- libc/inet/getproto.c | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) (limited to 'libc/inet') diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c index bcf507bda..c59da7e66 100644 --- a/libc/inet/getproto.c +++ b/libc/inet/getproto.c @@ -27,9 +27,11 @@ aliases: case sensitive optional space or tab separated list of other names #include __UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); -#define MAXALIASES 35 -#define BUFSZ (80) /* one line */ -#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES)) +#define MINTOKENS 2 +#define MAXALIASES 8 /* will probably never be more than one */ +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) static parser_t *protop = NULL; static struct protoent protoe; @@ -63,10 +65,8 @@ libc_hidden_def(endprotoent) int getprotoent_r(struct protoent *result_buf, char *buf, size_t buflen, struct protoent **result) { - char **alias, *cp = NULL; - char **proto_aliases; char **tok = NULL; - const size_t aliaslen = sizeof(*proto_aliases) * MAXALIASES; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; int ret = ERANGE; *result = NULL; @@ -85,21 +85,12 @@ int getprotoent_r(struct protoent *result_buf, protop->data_len = aliaslen; protop->line_len = buflen - aliaslen; /* [[:space:]][[:space:]][] */ - if (!config_read(protop, &tok, 3, 2, "# \t/", PARSE_NORMAL)) { + if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { goto DONE; } result_buf->p_name = *(tok++); result_buf->p_proto = atoi(*(tok++)); - result_buf->p_aliases = alias = proto_aliases = tok; - cp = *alias; - while (cp && *cp) { - if (alias < &proto_aliases[MAXALIASES - 1]) - *alias++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; - } - *alias = NULL; + result_buf->p_aliases = tok; *result = result_buf; ret = 0; DONE: -- cgit v1.2.3 From c2acd989048e58dcde5c5088211b0a0e40fc0f76 Mon Sep 17 00:00:00 2001 From: Philip Nye Date: Fri, 19 Nov 2010 16:50:35 +0000 Subject: resolv.c fails for /etc/hosts lookups Patch attached: Fix a bug in offset calculations when parsing /etc/hosts in resolv.c. Formerly a miscalculation meant that having found the correct line, the code was trashing its own result data. Signed-off-by: Philip Nye Signed-off-by: Bernhard Reutner-Fischer --- libc/inet/resolv.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'libc/inet') diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 364a4b9f5..47bab7519 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -335,7 +335,7 @@ Domain name in a message can be represented as either: #define MAX_RECURSE 5 -#define MAXALIASES (6) +#define MAXALIASES (4) #define BUFSZ (80) /* one line */ #define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES)) @@ -1587,6 +1587,11 @@ parser_t * __open_etc_hosts(void) return parser; } +#define MINTOKENS 2 //dotted ip address + canonical name +#define MAXTOKENS (MINTOKENS + MAXALIASES) +#define HALISTOFF (sizeof(char*) * MAXTOKENS) +#define INADDROFF (HALISTOFF + 2 * sizeof(char*)) + int attribute_hidden __read_etc_hosts_r( parser_t * parser, const char *name, @@ -1601,8 +1606,7 @@ int attribute_hidden __read_etc_hosts_r( char **host_aliases; char **tok = NULL; struct in_addr *h_addr0 = NULL; -#define ALIASOFF (sizeof(*host_aliases) * MAXALIASES + 2 * sizeof(char*)) - const size_t aliaslen = ALIASOFF + + const size_t aliaslen = INADDROFF + #ifdef __UCLIBC_HAS_IPV6__ sizeof(struct in6_addr) #else @@ -1622,8 +1626,8 @@ int attribute_hidden __read_etc_hosts_r( return errno; } /* Layout in buf: - * char **alias for MAXALIAS aliases - * char **h_addr_list[1] = {*in[6]_addr, NULL} + * char *alias[MAXTOKENS] = {address, name, aliases...} + * char **h_addr_list[1] = {*in[6]_addr, NULL} * struct in[6]_addr * char line_buffer[BUFSZ+]; */ @@ -1632,7 +1636,7 @@ int attribute_hidden __read_etc_hosts_r( parser->line_len = buflen - aliaslen; *h_errnop = HOST_NOT_FOUND; /* [[:space:]][] */ - while (config_read(parser, &tok, MAXALIASES, 2, "# \t", PARSE_NORMAL)) { + while (config_read(parser, &tok, MAXTOKENS, MINTOKENS, "# \t", PARSE_NORMAL)) { result_buf->h_aliases = alias = host_aliases = tok+1; if (action == GETHOSTENT) { /* Return whatever the next entry happens to be. */ @@ -1650,9 +1654,9 @@ int attribute_hidden __read_etc_hosts_r( } found: result_buf->h_name = *(result_buf->h_aliases++); - result_buf->h_addr_list = (char**)(buf + ALIASOFF); + result_buf->h_addr_list = (char**)(buf + HALISTOFF); *(result_buf->h_addr_list + 1) = '\0'; - h_addr0 = (struct in_addr*)(buf + ALIASOFF + 2 * sizeof (char*)); + h_addr0 = (struct in_addr*)(buf + INADDROFF); result_buf->h_addr = (char*)h_addr0; if (0) /* nothing */; #ifdef __UCLIBC_HAS_IPV4__ -- cgit v1.2.3