|
|
ca483c |
commit 745664bd798ec8fd50438605948eea594179fba1
|
|
|
ca483c |
Author: Florian Weimer <fweimer@redhat.com>
|
|
|
ca483c |
Date: Tue Aug 28 13:19:27 2018 +0200
|
|
|
ca483c |
|
|
|
ca483c |
nscd: Fix use-after-free in addgetnetgrentX [BZ #23520]
|
|
|
ca483c |
|
|
|
ca483c |
addinnetgrX may use the heap-allocated buffer, so free the buffer
|
|
|
ca483c |
in this function.
|
|
|
ca483c |
|
|
|
ca483c |
Conflicts:
|
|
|
ca483c |
nscd/netgroupcache.c
|
|
|
ca483c |
(different backport order)
|
|
|
ca483c |
|
|
|
ca483c |
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
|
|
ca483c |
index 7d7269a8edf1b99d..d234eb5ac48c73f2 100644
|
|
|
ca483c |
--- a/nscd/netgroupcache.c
|
|
|
ca483c |
+++ b/nscd/netgroupcache.c
|
|
|
ca483c |
@@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
static time_t
|
|
|
ca483c |
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
const char *key, uid_t uid, struct hashentry *he,
|
|
|
ca483c |
- struct datahead *dh, struct dataset **resultp)
|
|
|
ca483c |
+ struct datahead *dh, struct dataset **resultp,
|
|
|
ca483c |
+ void **tofreep)
|
|
|
ca483c |
{
|
|
|
ca483c |
if (__builtin_expect (debug_level > 0, 0))
|
|
|
ca483c |
{
|
|
|
ca483c |
@@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
size_t group_len = strlen (key) + 1;
|
|
|
ca483c |
struct name_list *first_needed
|
|
|
ca483c |
= alloca (sizeof (struct name_list) + group_len);
|
|
|
ca483c |
+ *tofreep = NULL;
|
|
|
ca483c |
|
|
|
ca483c |
if (netgroup_database == NULL
|
|
|
ca483c |
&& __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
|
|
ca483c |
@@ -151,6 +153,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
|
|
|
ca483c |
memset (&data, '\0', sizeof (data));
|
|
|
ca483c |
buffer = xmalloc (buflen);
|
|
|
ca483c |
+ *tofreep = buffer;
|
|
|
ca483c |
first_needed->next = first_needed;
|
|
|
ca483c |
memcpy (first_needed->name, key, group_len);
|
|
|
ca483c |
data.needed_groups = first_needed;
|
|
|
ca483c |
@@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
out:
|
|
|
ca483c |
- free (buffer);
|
|
|
ca483c |
-
|
|
|
ca483c |
*resultp = dataset;
|
|
|
ca483c |
|
|
|
ca483c |
return timeout;
|
|
|
ca483c |
@@ -477,8 +478,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
group, group_len,
|
|
|
ca483c |
db, uid);
|
|
|
ca483c |
time_t timeout;
|
|
|
ca483c |
+ void *tofree;
|
|
|
ca483c |
if (result != NULL)
|
|
|
ca483c |
- timeout = result->head.timeout;
|
|
|
ca483c |
+ {
|
|
|
ca483c |
+ timeout = result->head.timeout;
|
|
|
ca483c |
+ tofree = NULL;
|
|
|
ca483c |
+ }
|
|
|
ca483c |
else
|
|
|
ca483c |
{
|
|
|
ca483c |
request_header req_get =
|
|
|
ca483c |
@@ -487,7 +492,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
.key_len = group_len
|
|
|
ca483c |
};
|
|
|
ca483c |
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
|
|
|
ca483c |
- &result);
|
|
|
ca483c |
+ &result, &tofree);
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
struct indataset
|
|
|
ca483c |
@@ -559,8 +564,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
dh->ttl = dataset->head.ttl;
|
|
|
ca483c |
++dh->nreloads;
|
|
|
ca483c |
if (cacheable)
|
|
|
ca483c |
- pthread_rwlock_unlock (&db->lock);
|
|
|
ca483c |
- return timeout;
|
|
|
ca483c |
+ pthread_rwlock_unlock (&db->lock);
|
|
|
ca483c |
+ goto out;
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
if (he == NULL)
|
|
|
ca483c |
@@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
dh->usable = false;
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
+ out:
|
|
|
ca483c |
+ free (tofree);
|
|
|
ca483c |
return timeout;
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
|
|
|
ca483c |
+static time_t
|
|
|
ca483c |
+addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
+ const char *key, uid_t uid, struct hashentry *he,
|
|
|
ca483c |
+ struct datahead *dh)
|
|
|
ca483c |
+{
|
|
|
ca483c |
+ struct dataset *ignore;
|
|
|
ca483c |
+ void *tofree;
|
|
|
ca483c |
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
|
|
|
ca483c |
+ &ignore, &tofree);
|
|
|
ca483c |
+ free (tofree);
|
|
|
ca483c |
+ return timeout;
|
|
|
ca483c |
+}
|
|
|
ca483c |
+
|
|
|
ca483c |
void
|
|
|
ca483c |
addgetnetgrent (struct database_dyn *db, int fd, request_header *req,
|
|
|
ca483c |
void *key, uid_t uid)
|
|
|
ca483c |
{
|
|
|
ca483c |
- struct dataset *ignore;
|
|
|
ca483c |
-
|
|
|
ca483c |
- addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore);
|
|
|
ca483c |
+ addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL);
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
|
|
|
ca483c |
@@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he,
|
|
|
ca483c |
.type = GETNETGRENT,
|
|
|
ca483c |
.key_len = he->len
|
|
|
ca483c |
};
|
|
|
ca483c |
- struct dataset *ignore;
|
|
|
ca483c |
-
|
|
|
ca483c |
- return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh,
|
|
|
ca483c |
- &ignore);
|
|
|
ca483c |
+ return addgetnetgrentX_ignore
|
|
|
ca483c |
+ (db, -1, &req, db->data + he->key, he->owner, he, dh);
|
|
|
ca483c |
}
|
|
|
ca483c |
|
|
|
ca483c |
|