From patchwork Tue Aug 14 10:54:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 957430 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-95232-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="ZU0DtZM9"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41qTxK2bnbz9s78 for ; Tue, 14 Aug 2018 20:54:13 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:to:subject:mime-version:content-type :content-transfer-encoding:message-id:from; q=dns; s=default; b= vxEjyBUU4ss6p2hI+ntPLE2z4Njy8UZEC+J/2u+pp5yQVzDKBO/4+kuoP42HU/fC Y3ubaju7gEyB+JlEG/epDkkPUgL9jd3y5PAJuP94ph6KLb22/oD8I1Rkxkquue9A 7KwnBgxCtjb04DoAigMRdC3c+Ygh59XFggLK8KtbHYk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:to:subject:mime-version:content-type :content-transfer-encoding:message-id:from; s=default; bh=6iccTR 0gXDJ7VGuwdiDlCXx63rU=; b=ZU0DtZM99VQMsKpNmpYZudzXSIey2YDZ5JxqJ6 QUt40cLRPODUaHrvucJBzGlb0nNrfilkEjWBfUSpdmeuLYXQWuSpLEPieXoDt3Vv hKKdgFG1VWFpOnAxTTvK/BijyoTBUn+ksEdHkK/JfnbCFL424T9RKlI6QfWMQajl zU3DM= Received: (qmail 60621 invoked by alias); 14 Aug 2018 10:54:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 60608 invoked by uid 89); 14 Aug 2018 10:54:06 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=1516 X-HELO: mx1.redhat.com Date: Tue, 14 Aug 2018 12:54:02 +0200 To: libc-alpha@sourceware.org Subject: [PATCH] nscd: Fix use-after-free in addgetnetgrentX [BZ #23520] User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20180814105402.C227D4056649D@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) addinnetgrX may use the heap-allocated buffer, so free the buffer in this function. 2018-08-14 Florian Weimer [BZ #23520] nscd: Fix use-after-free in addgetnetgrentX and its callers. * nscd/netgroupcache.c (addgetnetgrentX): Add tofreep parameter. Do not free heap-allocated buffer. (addinnetgrX): Free buffer allocated bt addgetnetgrentX. (addgetnetgrentX_ignore): New function. (addgetnetgrent): Call it. (readdgetnetgrent): Likewise. Reviewed-by: Carlos O'Donell diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 2b35389cc8..87059fb280 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, static time_t addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, const char *key, uid_t uid, struct hashentry *he, - struct datahead *dh, struct dataset **resultp) + struct datahead *dh, struct dataset **resultp, + void **tofreep) { if (__glibc_unlikely (debug_level > 0)) { @@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, size_t group_len = strlen (key) + 1; struct name_list *first_needed = alloca (sizeof (struct name_list) + group_len); + *tofreep = NULL; if (netgroup_database == NULL && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) @@ -151,6 +153,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, memset (&data, '\0', sizeof (data)); buffer = xmalloc (buflen); + *tofreep = buffer; first_needed->next = first_needed; memcpy (first_needed->name, key, group_len); data.needed_groups = first_needed; @@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, } out: - free (buffer); - *resultp = dataset; return timeout; @@ -477,8 +478,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, group, group_len, db, uid); time_t timeout; + void *tofree; if (result != NULL) - timeout = result->head.timeout; + { + timeout = result->head.timeout; + tofree = NULL; + } else { request_header req_get = @@ -487,7 +492,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, .key_len = group_len }; timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL, - &result); + &result, &tofree); } struct indataset @@ -560,7 +565,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, ++dh->nreloads; if (cacheable) pthread_rwlock_unlock (&db->lock); - return timeout; + goto out; } if (he == NULL) @@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, dh->usable = false; } + out: + free (tofree); return timeout; } +static time_t +addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req, + const char *key, uid_t uid, struct hashentry *he, + struct datahead *dh) +{ + struct dataset *ignore; + void *tofree; + time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, + &ignore, &tofree); + free (tofree); + return timeout; +} + void addgetnetgrent (struct database_dyn *db, int fd, request_header *req, void *key, uid_t uid) { - struct dataset *ignore; - - addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore); + addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL); } @@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he, .type = GETNETGRENT, .key_len = he->len }; - struct dataset *ignore; - - return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh, - &ignore); + return addgetnetgrentX_ignore + (db, -1, &req, db->data + he->key, he->owner, he, dh); }