| commit bc8f194c8c29e46e8ee4034f06e46988dfff38f7 |
| Author: Siddhesh Poyarekar <siddhesh@redhat.com> |
| Date: Wed Apr 30 12:00:39 2014 +0530 |
| |
| Initialize all of datahead structure in nscd (BZ #16791) |
| |
| The datahead structure has an unused padding field that remains |
| uninitialized. Valgrind prints out a warning for it on querying a |
| netgroups entry. This is harmless, but is a potential data leak since |
| it would result in writing out an uninitialized byte to the cache |
| file. Besides, this happens only when there is a cache miss, so we're |
| not adding computation to any fast path. |
| |
| commit 1cdeb2372ddecac0dfe0c132a033e9590ffa07d2 |
| Author: Siddhesh Poyarekar <siddhesh@redhat.com> |
| Date: Wed Apr 30 11:57:09 2014 +0530 |
| |
| Consolidate code to initialize nscd dataset header |
| |
| This patch consolidates the code to initialize the header of a dataset |
| into a single set of functions (one for positive and another for |
| negative datasets) primarily to reduce repetition of code. The |
| secondary reason is to simplify Patch 2/2 which fixes the problem of |
| an uninitialized byte in the header by initializing an unused field in |
| the structure and hence preventing a possible data leak into the cache |
| file. |
| |
| diff --git glibc-2.17-c758a686/nscd/aicache.c glibc-2.17-c758a686/nscd/aicache.c |
| index 98d40a1..d7966bd 100644 |
| |
| |
| @@ -383,17 +383,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, |
| cp = family; |
| } |
| |
| - /* Fill in the rest of the dataset. */ |
| - dataset->head.allocsize = total + req->key_len; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - dataset->head.ttl = ttl == INT32_MAX ? db->postimeout : ttl; |
| - timeout = dataset->head.timeout = time (NULL) + dataset->head.ttl; |
| + timeout = datahead_init_pos (&dataset->head, total + req->key_len, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + ttl == INT32_MAX ? db->postimeout : ttl); |
| |
| + /* Fill in the rest of the dataset. */ |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |
| dataset->resp.naddrs = naddrs; |
| @@ -528,15 +523,9 @@ next_nip: |
| else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) |
| + req->key_len), 1)) != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = time (NULL) + db->negtimeout; |
| - dataset->head.ttl = db->negtimeout; |
| + timeout = datahead_init_neg (&dataset->head, |
| + sizeof (struct dataset) + req->key_len, |
| + total, db->negtimeout); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, ¬found, total); |
| diff --git glibc-2.17-c758a686/nscd/grpcache.c glibc-2.17-c758a686/nscd/grpcache.c |
| index b5a33eb..df59fa7 100644 |
| |
| |
| @@ -128,14 +128,10 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, |
| } |
| else if ((dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1)) != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = t + db->negtimeout; |
| + timeout = datahead_init_neg (&dataset->head, |
| + (sizeof (struct dataset) |
| + + req->key_len), total, |
| + db->negtimeout); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, ¬found, total); |
| @@ -232,14 +228,10 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req, |
| dataset_temporary = true; |
| } |
| |
| - dataset->head.allocsize = total + n; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = t + db->postimeout; |
| + timeout = datahead_init_pos (&dataset->head, total + n, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + db->postimeout); |
| |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |
| diff --git glibc-2.17-c758a686/nscd/hstcache.c glibc-2.17-c758a686/nscd/hstcache.c |
| index a79b67a..d4f1ad2 100644 |
| |
| |
| @@ -152,15 +152,11 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, |
| else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) |
| + req->key_len), 1)) != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - dataset->head.ttl = ttl == INT32_MAX ? db->negtimeout : ttl; |
| - timeout = dataset->head.timeout = t + dataset->head.ttl; |
| + timeout = datahead_init_neg (&dataset->head, |
| + (sizeof (struct dataset) |
| + + req->key_len), total, |
| + (ttl == INT32_MAX |
| + ? db->negtimeout : ttl)); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, resp, total); |
| @@ -257,15 +253,10 @@ cache_addhst (struct database_dyn *db, int fd, request_header *req, |
| alloca_used = true; |
| } |
| |
| - dataset->head.allocsize = total + req->key_len; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - dataset->head.ttl = ttl == INT32_MAX ? db->postimeout : ttl; |
| - timeout = dataset->head.timeout = t + dataset->head.ttl; |
| + timeout = datahead_init_pos (&dataset->head, total + req->key_len, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + ttl == INT32_MAX ? db->postimeout : ttl); |
| |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |
| diff --git glibc-2.17-c758a686/nscd/initgrcache.c glibc-2.17-c758a686/nscd/initgrcache.c |
| index 1bf9f0d..361319f 100644 |
| |
| |
| @@ -213,14 +213,10 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, |
| else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) |
| + req->key_len), 1)) != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = time (NULL) + db->negtimeout; |
| + timeout = datahead_init_neg (&dataset->head, |
| + (sizeof (struct dataset) |
| + + req->key_len), total, |
| + db->negtimeout); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, ¬found, total); |
| @@ -276,14 +272,10 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, |
| alloca_used = true; |
| } |
| |
| - dataset->head.allocsize = total + req->key_len; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = time (NULL) + db->postimeout; |
| + timeout = datahead_init_pos (&dataset->head, total + req->key_len, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + db->postimeout); |
| |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |
| diff --git glibc-2.17-c758a686/nscd/netgroupcache.c glibc-2.17-c758a686/nscd/netgroupcache.c |
| index 820d823..b3d40e9 100644 |
| |
| |
| @@ -90,15 +90,9 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, |
| /* If we cannot permanently store the result, so be it. */ |
| if (dataset != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = time (NULL) + db->negtimeout; |
| - dataset->head.ttl = db->negtimeout; |
| + timeout = datahead_init_neg (&dataset->head, |
| + sizeof (struct dataset) + req->key_len, |
| + total, db->negtimeout); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, ¬found, total); |
| @@ -359,13 +353,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, |
| |
| /* Fill in the dataset. */ |
| dataset = (struct dataset *) buffer; |
| - dataset->head.allocsize = total + req->key_len; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - dataset->head.ttl = db->postimeout; |
| - timeout = dataset->head.timeout = time (NULL) + dataset->head.ttl; |
| + timeout = datahead_init_pos (&dataset->head, total + req->key_len, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + db->postimeout); |
| |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |
| @@ -541,12 +532,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, |
| dataset = &dataset_mem; |
| } |
| |
| - dataset->head.allocsize = sizeof (*dataset) + req->key_len; |
| - dataset->head.recsize = sizeof (innetgroup_response_header); |
| + datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, |
| + sizeof (innetgroup_response_header), |
| + he == NULL ? 0 : dh->nreloads + 1, result->head.ttl); |
| + /* Set the notfound status and timeout based on the result from |
| + getnetgrent. */ |
| dataset->head.notfound = result->head.notfound; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - dataset->head.ttl = result->head.ttl; |
| dataset->head.timeout = timeout; |
| |
| dataset->resp.version = NSCD_VERSION; |
| diff --git glibc-2.17-c758a686/nscd/nscd-client.h glibc-2.17-c758a686/nscd/nscd-client.h |
| index 98f77e7..ee16df6 100644 |
| |
| |
| @@ -236,6 +236,48 @@ struct datahead |
| } data[0]; |
| }; |
| |
| +static inline time_t |
| +datahead_init_common (struct datahead *head, nscd_ssize_t allocsize, |
| + nscd_ssize_t recsize, uint32_t ttl) |
| +{ |
| + /* Initialize so that we don't write out junk in uninitialized data to the |
| + cache. */ |
| + memset (head, 0, sizeof (*head)); |
| + |
| + head->allocsize = allocsize; |
| + head->recsize = recsize; |
| + head->usable = true; |
| + |
| + head->ttl = ttl; |
| + |
| + /* Compute and return the timeout time. */ |
| + return head->timeout = time (NULL) + ttl; |
| +} |
| + |
| +static inline time_t |
| +datahead_init_pos (struct datahead *head, nscd_ssize_t allocsize, |
| + nscd_ssize_t recsize, uint8_t nreloads, uint32_t ttl) |
| +{ |
| + time_t ret = datahead_init_common (head, allocsize, recsize, ttl); |
| + |
| + head->notfound = false; |
| + head->nreloads = nreloads; |
| + |
| + return ret; |
| +} |
| + |
| +static inline time_t |
| +datahead_init_neg (struct datahead *head, nscd_ssize_t allocsize, |
| + nscd_ssize_t recsize, uint32_t ttl) |
| +{ |
| + time_t ret = datahead_init_common (head, allocsize, recsize, ttl); |
| + |
| + /* We don't need to touch nreloads here since it is set to our desired value |
| + (0) when we clear the structure. */ |
| + head->notfound = true; |
| + |
| + return ret; |
| +} |
| |
| /* Structure for one hash table entry. */ |
| struct hashentry |
| diff --git glibc-2.17-c758a686/nscd/pwdcache.c glibc-2.17-c758a686/nscd/pwdcache.c |
| index fa355c3..41c245b 100644 |
| |
| |
| @@ -135,14 +135,10 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, |
| else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) |
| + req->key_len), 1)) != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = t + db->negtimeout; |
| + timeout = datahead_init_neg (&dataset->head, |
| + (sizeof (struct dataset) |
| + + req->key_len), total, |
| + db->negtimeout); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, ¬found, total); |
| @@ -215,14 +211,10 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req, |
| alloca_used = true; |
| } |
| |
| - dataset->head.allocsize = total + n; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = t + db->postimeout; |
| + timeout = datahead_init_pos (&dataset->head, total + n, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + db->postimeout); |
| |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |
| diff --git glibc-2.17-c758a686/nscd/servicescache.c glibc-2.17-c758a686/nscd/servicescache.c |
| index 12ce9b2..95bdcfe 100644 |
| |
| |
| @@ -120,14 +120,10 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, |
| else if ((dataset = mempool_alloc (db, (sizeof (struct dataset) |
| + req->key_len), 1)) != NULL) |
| { |
| - dataset->head.allocsize = sizeof (struct dataset) + req->key_len; |
| - dataset->head.recsize = total; |
| - dataset->head.notfound = true; |
| - dataset->head.nreloads = 0; |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = t + db->negtimeout; |
| + timeout = datahead_init_neg (&dataset->head, |
| + (sizeof (struct dataset) |
| + + req->key_len), total, |
| + db->negtimeout); |
| |
| /* This is the reply. */ |
| memcpy (&dataset->resp, ¬found, total); |
| @@ -207,14 +203,10 @@ cache_addserv (struct database_dyn *db, int fd, request_header *req, |
| alloca_used = true; |
| } |
| |
| - dataset->head.allocsize = total + req->key_len; |
| - dataset->head.recsize = total - offsetof (struct dataset, resp); |
| - dataset->head.notfound = false; |
| - dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1); |
| - dataset->head.usable = true; |
| - |
| - /* Compute the timeout time. */ |
| - timeout = dataset->head.timeout = t + db->postimeout; |
| + timeout = datahead_init_pos (&dataset->head, total + req->key_len, |
| + total - offsetof (struct dataset, resp), |
| + he == NULL ? 0 : dh->nreloads + 1, |
| + db->postimeout); |
| |
| dataset->resp.version = NSCD_VERSION; |
| dataset->resp.found = 1; |