From d25feadebbf05d6fce55cfee1e3c8f928903f543 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 1 Jul 2011 12:36:33 -0400 Subject: [PATCH 1/3] Fix insanely large stack_allocation in log_credential_status I'm not one to insist on C's miserly stack limits, but allocating a 256K array on the stack is too much even for me. Bugfix on 0.2.1.7-alpha. Found by coverity. Fixes CID # 450. --- changes/cid_450 | 5 +++++ src/common/compat.c | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 changes/cid_450 diff --git a/changes/cid_450 b/changes/cid_450 new file mode 100644 index 0000000000..2045fca239 --- /dev/null +++ b/changes/cid_450 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Don't stack-allocate the list of supplementary GIDs when we're + about to log them. Stack-allocating NGROUPS_MAX gid_t elements + could take up to 256K, which is way too much stack. Found by + Coverity; CID #450. Bugfix on 0.2.1.7-alpha. diff --git a/src/common/compat.c b/src/common/compat.c index 39651084a0..9533c115b6 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1080,7 +1080,8 @@ log_credential_status(void) /* Read, effective and saved GIDs */ gid_t rgid, egid, sgid; /* Supplementary groups */ - gid_t sup_gids[NGROUPS_MAX + 1]; + gid_t *sup_gids = NULL; + int sup_gids_size; /* Number of supplementary groups */ int ngids; @@ -1126,9 +1127,19 @@ log_credential_status(void) #endif /* log supplementary groups */ - if ((ngids = getgroups(NGROUPS_MAX + 1, sup_gids)) < 0) { + sup_gids_size = 64; + sup_gids = tor_malloc(sizeof(gid_t) * 64); + while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 && + errno == EINVAL && + sup_gids_size < NGROUPS_MAX) { + sup_gids_size *= 2; + sup_gids = tor_realloc(sup_gids, sizeof(gid_t) * sup_gids_size); + } + + if (ngids < 0) { log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s", strerror(errno)); + tor_free(sup_gids); return -1; } else { int i, retval = 0; @@ -1158,6 +1169,7 @@ log_credential_status(void) tor_free(cp); }); smartlist_free(elts); + tor_free(sup_gids); return retval; } From 46297bc7bd86826fa79195f36059ce408ef45b6c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 1 Jul 2011 11:52:39 -0400 Subject: [PATCH 2/3] Fix a rare memory leak in rend_cache_store When we rejected a descriptor for not being the one we wanted, we were letting the parsed descriptor go out of scope. Found by Coverity; CID # 30. Bugfix on 0.2.1.26. (No changes file yet, since this is not in any 0.2.1.x release.) --- src/or/rendcommon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 8727a70c2e..e0c101e1ee 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -1077,6 +1077,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published, log_warn(LD_REND, "Received service descriptor for service ID %s; " "expected descriptor for service ID %s.", query, safe_str(service_id)); + rend_service_descriptor_free(parsed); return -2; } now = time(NULL); From 959da6b7f2b5ed63426fd12a9046ac06033f6db1 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 1 Jul 2011 12:06:54 -0400 Subject: [PATCH 3/3] Use strlcpy in create_unix_sockaddr() Using strncpy meant that if listenaddress were ever >= sizeof(sockaddr_un.sun_path), we would fail to nul-terminate sun_path. This isn't a big deal: we never read sun_path, and the kernel is smart enough to reject the sockaddr_un if it isn't nul-terminated. Nonetheless, it's a dumb failure mode. Instead, we should reject addresses that don't fit in sockaddr_un.sun_path. Coverity found this; it's CID 428. Bugfix on 0.2.0.3-alpha. --- changes/cid_428 | 5 +++++ src/or/connection.c | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 changes/cid_428 diff --git a/changes/cid_428 b/changes/cid_428 new file mode 100644 index 0000000000..cb0fc8c2b2 --- /dev/null +++ b/changes/cid_428 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Always NUL-terminate the sun_path field of a sockaddr_un before + passing it to the kernel. (Not a security issue: kernels are + smart enough to reject bad sockaddr_uns.) Found by Coverity; CID + # 428. Bugfix on Tor 0.2.0.3-alpha. diff --git a/src/or/connection.c b/src/or/connection.c index 4869a2439a..2897fe10a1 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -804,7 +804,13 @@ create_unix_sockaddr(const char *listenaddress, char **readable_address, sockaddr = tor_malloc_zero(sizeof(struct sockaddr_un)); sockaddr->sun_family = AF_UNIX; - strncpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path)); + if (strlcpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path)) + >= sizeof(sockaddr->sun_path)) { + log_warn(LD_CONFIG, "Unix socket path '%s' is too long to fit.", + escaped(listenaddress)); + tor_free(sockaddr); + return NULL; + } if (readable_address) *readable_address = tor_strdup(listenaddress);