From patchwork Wed Apr 24 16:08:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 88960 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BA16A3849AFB for ; Wed, 24 Apr 2024 16:09:20 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 1E6EC384B11C for ; Wed, 24 Apr 2024 16:08:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1E6EC384B11C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1E6EC384B11C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974931; cv=none; b=RHyikMhNo9rmxsPAw0LZQT5WS0Cam6LUpZaIGTuU6JJg+TPBQlsq7DCIsIW+ihmQ4lEcbMvW0UgYZctaha3WYiSYUIaP8n71j9pCJG2YWyST0er2cnuXiY0puaAv03Ndy85xjO9bn+Z8d8feF/xXQw8PF93SBVVWuL/gfkYv+6w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974931; c=relaxed/simple; bh=iTYZxTxMa1uOruuhUpY10rBLFfYTa7M2qF1gIIm/ZWE=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=Ya1V6UUOE6XADfE5H30o8zdgvtFJd1G/8Bv5jj3bsrXZCRI75w8sRd4beXJCEPNiXQUtM3XkqvjQXuyVyI9S+1YrYM9ItIqGvjriLhNk+AHgCFZd/OCyEkEmui6E4/0QS7ioUXxLnoKPLQg6ADA/SJNjfBM1V0W//0oMCEt86Yw= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713974924; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=ac2X/aWkAwJLZnR+GzKJVZRH4jG6fCMvLzeLGcARDd4=; b=OZnxzEt9gV6auXjOs9dGtqqOBASvkTqojvkpmf3RyI+1dpqmv6Qe+0NJXE+1GwWKI/Yc6+ wKjED76RbSaqBRqNFyRTSR218fMc170uS/ud8iWPS3e+c/ql9yfGwOUlULXZl7Fu5IxgPC xHFWJMecAtr2qjGbxpb8DSWSowXxemQ= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-217-wBJCs0HBPtGHefege-AcXA-1; Wed, 24 Apr 2024 12:08:43 -0400 X-MC-Unique: wBJCs0HBPtGHefege-AcXA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E462B29AC027 for ; Wed, 24 Apr 2024 16:08:42 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.74]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4FCFD2166B34 for ; Wed, 24 Apr 2024 16:08:42 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 1/4] nscd: Stack-based buffer overflow in netgroup cache (bug 31677) In-Reply-To: Message-ID: <73a91330cea898a1d48c0033ffcdb2cf8e6fbc4c.1713974801.git.fweimer@redhat.com> References: X-From-Line: 73a91330cea898a1d48c0033ffcdb2cf8e6fbc4c Mon Sep 17 00:00:00 2001 Date: Wed, 24 Apr 2024 18:08:37 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.6 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Using alloca matches what other caches do. The request length is bounded by MAXKEYLEN. --- nscd/netgroupcache.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 0c6e46f15c..24fbac7668 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -502,12 +502,11 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, = (struct indataset *) mempool_alloc (db, sizeof (*dataset) + req->key_len, 1); - struct indataset dataset_mem; bool cacheable = true; if (__glibc_unlikely (dataset == NULL)) { cacheable = false; - dataset = &dataset_mem; + dataset = alloca (sizeof (*dataset) + req->key_len); } datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, From patchwork Wed Apr 24 16:08:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 88961 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B107F384772F for ; Wed, 24 Apr 2024 16:09:22 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id A756E3849AC1 for ; Wed, 24 Apr 2024 16:08:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A756E3849AC1 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A756E3849AC1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974931; cv=none; b=D9n5GcFMcbJZtMYe0BLirYX3AMYfB+famp1TDnH03dJqQjgiBTK+g0aNJMFNuJrnzhDbTSW7DbF7z1WV2LqidpQNw8a5cLV9wPX/Jptp2Pes+xCGSttWnBa4adsW/CkVVDZrguZVS67Qpm628yUfZARLzcbqEiG7se4jAH4gmdw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974931; c=relaxed/simple; bh=MGjoa72Q724jQooNweBbmh1GHQmU01YtWdOyTq+i6yc=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=ORzaCI5nr4vL+MeEAX37s+F7lkO3Q2/dYnI3fVdxhxROIrYw/U6auAPkbcLgyCxRk5VAA3dvR208eXWn5WcWbXAk7WvKHhP0BZlIoOquaFcAueqeJueDOKMfrb4I52KGrZ1sfJHRRqJ9UVX5V38jTTKK1RIxcJqbxScY8y8FzB4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713974929; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=4Fdm+iWbM0iFS6/TbecF8ky2BihZ3zVY/UOcR3JflfM=; b=eUCQ1qW+9GUO+ERVXtegKaRmvaB/OZyBRhyOzn9J65tp0Y2F6WtsMHdbbQAFYm7KuHu+mW crzDBKd9AyKb/M7Y9Lp0p2PiwTawmzeBlXJEW8IBlxBkS0QQE0dfniGhwfsUaS4nSx+db+ rruYMTmuYZ+AuuqHeB56u4WDDQebaPg= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-336-xhQUUNQ3NfejFmIzZhANvA-1; Wed, 24 Apr 2024 12:08:48 -0400 X-MC-Unique: xhQUUNQ3NfejFmIzZhANvA-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B6B6D380670D for ; Wed, 24 Apr 2024 16:08:46 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.74]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4A5D85C820 for ; Wed, 24 Apr 2024 16:08:46 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 2/4] nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678) In-Reply-To: Message-ID: <90f1fccc39a22663a5c57c4e7c938480ada61d87.1713974801.git.fweimer@redhat.com> References: X-From-Line: 90f1fccc39a22663a5c57c4e7c938480ada61d87 Mon Sep 17 00:00:00 2001 Date: Wed, 24 Apr 2024 18:08:44 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org If we failed to add a not-found response to the cache, the dataset point can be null, resulting in a null pointer dereference. Reviewed-by: Siddhesh Poyarekar --- nscd/netgroupcache.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 24fbac7668..8709fb77b6 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -147,7 +147,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, /* No such service. */ cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, &key_copy); - goto writeout; + goto maybe_cache_add; } memset (&data, '\0', sizeof (data)); @@ -348,7 +348,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, { cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, &key_copy); - goto writeout; + goto maybe_cache_add; } total = buffilled; @@ -410,14 +410,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, } if (he == NULL && fd != -1) - { - /* We write the dataset before inserting it to the database - since while inserting this thread might block and so would - unnecessarily let the receiver wait. */ - writeout: + /* We write the dataset before inserting it to the database since + while inserting this thread might block and so would + unnecessarily let the receiver wait. */ writeall (fd, &dataset->resp, dataset->head.recsize); - } + maybe_cache_add: if (cacheable) { /* If necessary, we also propagate the data to disk. */ From patchwork Wed Apr 24 16:08:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 88962 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 84F053846013 for ; Wed, 24 Apr 2024 16:09:23 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 29C753849AE0 for ; Wed, 24 Apr 2024 16:08:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 29C753849AE0 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 29C753849AE0 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974934; cv=none; b=jrtxcs3vaog1yI8ytwuXK9HytcDE83QQDXWtsJPmtUZxz757YJaKoFVrqHEYbugZ9cWq1QTrdFWr3fu+qk4H5fIbQ4955MwHl1iPO7RK809yHzShp8qU7Q8hCbFcP6KmDb7QwqXynXjpCZrh3c/X5yARZ6Riv+5BkawDXv9a94w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974934; c=relaxed/simple; bh=67JA5jch1YOBKxEqkr17/mg0mGJKGFpZXlifnxIYOJo=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=JGPDMUCWIwAPBsOVdUEFD5s70DZKHQo1IqRM5BfhRdayIslt04wCgvrJlbyzXJWYFszMf6q/zHZ6JQ1FalededDb6w0Rn22/k4nkOhuF9yxKpSWUvxUL8xie7faw1R9ofCdtUTNqzipfhJwj0NW/v6Q1hXxkI+iW9mVV7wkGZig= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713974932; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=+Ap2pgItGIwz/67j5UZRG4A7iqMMSBcSLvNTncgMbzA=; b=hXvyDmC0M/Z7JGy/DxRz5ZcbBT+qomQ3X3xXdpH2K7iEEyFnPbbMpiaswPia43MLLpFoZX NNKeRca3zicqJk5df6+yau2r6HTMi6wxAdhdslWOAuP/M6SkAne8S0ISMMwANqbhP3+Ueb SKGrY/rX+kLkVzpL4T0FquBUv5QvvE4= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-448-ceVqq4PYNe66LT3kTno3xg-1; Wed, 24 Apr 2024 12:08:51 -0400 X-MC-Unique: ceVqq4PYNe66LT3kTno3xg-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 073963C02B44 for ; Wed, 24 Apr 2024 16:08:51 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.74]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 60B97400EAC for ; Wed, 24 Apr 2024 16:08:50 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 3/4] nscd: Avoid null pointer crashes after notfound response (bug 31678) In-Reply-To: Message-ID: <93eda86975719a1a40957e5f57fcb972b7daebbf.1713974801.git.fweimer@redhat.com> References: X-From-Line: 93eda86975719a1a40957e5f57fcb972b7daebbf Mon Sep 17 00:00:00 2001 Date: Wed, 24 Apr 2024 18:08:48 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org The addgetnetgrentX call in addinnetgrX may have failed to produce a result, so the result variable in addinnetgrX can be NULL. Use db->negtimeout as the fallback value if there is no result data; the timeout is also overwritten below. Also avoid sending a second not-found response. (The client disconnects after receiving the first response, so the data stream did not go out of sync even without this fix.) It is still beneficial to add the negative response to the mapping, so that the client can get it from there in the future, instead of going through the socket. Reviewed-by: Siddhesh Poyarekar --- nscd/netgroupcache.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 8709fb77b6..8f9eb84e39 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -509,14 +509,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len, sizeof (innetgroup_response_header), - he == NULL ? 0 : dh->nreloads + 1, result->head.ttl); + he == NULL ? 0 : dh->nreloads + 1, + result == NULL ? db->negtimeout : result->head.ttl); /* Set the notfound status and timeout based on the result from getnetgrent. */ - dataset->head.notfound = result->head.notfound; + dataset->head.notfound = result == NULL || result->head.notfound; dataset->head.timeout = timeout; dataset->resp.version = NSCD_VERSION; - dataset->resp.found = result->resp.found; + dataset->resp.found = result != NULL && result->resp.found; /* Until we find a matching entry the result is 0. */ dataset->resp.result = 0; @@ -564,7 +565,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, goto out; } - if (he == NULL) + /* addgetnetgrentX may have already sent a notfound response. Do + not send another one. */ + if (he == NULL && dataset->resp.found) { /* We write the dataset before inserting it to the database since while inserting this thread might block and so would From patchwork Wed Apr 24 16:08:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 88963 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4172A3849AF6 for ; Wed, 24 Apr 2024 16:10:06 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 277463846401 for ; Wed, 24 Apr 2024 16:08:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 277463846401 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 277463846401 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974942; cv=none; b=pD/8dM83qkR0pSgrldKP8YyiGW8dbE5kqCilu/xFuyvbJu1VZAishgPpfYLgb8wMqU5HuaXQfiDrTGpauE3q/YwTylCwJ9glRW4HZRcthr0DAHvRSO93nX7oxOICBUF4y/yaCNgN8o4FLKVzkOQ2x9yesHhur8v5l2p7QXGS/yQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713974942; c=relaxed/simple; bh=dhz7vNW/7L0UB8ipPsvzMTmZgFjAbl49zikrefVTMLs=; h=DKIM-Signature:From:To:Subject:Message-ID:Date:MIME-Version; b=HTLvJdUQt1cuTcaaGNB19Ku/fIcwSQXyLnS7GAnPv5jz7p8e1IDdJKvdM2H1ur/Bgq6+4Fxf/nJ1edGTLQOCR2hV4d+cuU+ftBFXRi6BKoB8kX8fUYGAm8mODjMY3wjIiAiKoERQOyMRFFymnzdD+lvR7tZ26u57ZYXV9clYsR4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713974937; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=hob0U8j/2Y6QryM5AObRHCq24otRzRqQRrSfNCHJnps=; b=OmmPQecCSmvXvUxktzpjtT+bd4Uvl/23QMx99gc454y7Vrx5XpztuDLSK6q7zH9c9v/E2h EAjT+WNKrsvmapfuTGyeaUItdCVVZN1OitLH44PIzNxCIx1e7NTo9Wz6USo0jLg6EYIiBS Hc6zZ5r+m0J/Gljr+08Ttrt0WQX9QRQ= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-288-BsuElicEM3ObXtwuGVbzjQ-1; Wed, 24 Apr 2024 12:08:56 -0400 X-MC-Unique: BsuElicEM3ObXtwuGVbzjQ-1 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.rdu2.redhat.com [10.11.54.10]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2359529AC027 for ; Wed, 24 Apr 2024 16:08:56 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.39.192.74]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E4C3D492BC7 for ; Wed, 24 Apr 2024 16:08:54 +0000 (UTC) From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH 4/4] nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680) In-Reply-To: Message-ID: <9abb85706e6a6876c55daed36e56c4e59e05b039.1713974801.git.fweimer@redhat.com> References: X-From-Line: 9abb85706e6a6876c55daed36e56c4e59e05b039 Mon Sep 17 00:00:00 2001 Date: Wed, 24 Apr 2024 18:08:53 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.10 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org This avoids potential memory corruption when the underlying NSS callback function does not use the buffer space to store all strings (e.g., for constant strings). Instead of custom buffer management, two scratch buffers are used. This increases stack usage somewhat. Scratch buffer allocation failure is handled by return -1 (an invalid timeout value) instead of terminating the process. This fixes bug 31679. Reviewed-by: Siddhesh Poyarekar --- nscd/netgroupcache.c | 219 ++++++++++++++++++++++++------------------- 1 file changed, 121 insertions(+), 98 deletions(-) diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index 8f9eb84e39..8b5ebfaf31 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "../nss/netgroup.h" #include "nscd.h" @@ -65,6 +66,16 @@ struct dataset char strdata[0]; }; +/* Send a notfound response to FD. Always returns -1 to indicate an + ephemeral error. */ +static time_t +send_notfound (int fd) +{ + if (fd != -1) + TEMP_FAILURE_RETRY (send (fd, ¬found, sizeof (notfound), MSG_NOSIGNAL)); + return -1; +} + /* Sends a notfound message and prepares a notfound dataset to write to the cache. Returns true if there was enough memory to allocate the dataset and returns the dataset in DATASETP, total bytes to write in TOTALP and the @@ -83,8 +94,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, total = sizeof (notfound); timeout = time (NULL) + db->negtimeout; - if (fd != -1) - TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL)); + send_notfound (fd); dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1); /* If we cannot permanently store the result, so be it. */ @@ -109,11 +119,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, return cacheable; } +struct addgetnetgrentX_scratch +{ + /* This is the result that the caller should use. It can be NULL, + point into buffer, or it can be in the cache. */ + struct dataset *dataset; + + struct scratch_buffer buffer; + + /* Used internally in addgetnetgrentX as a staging area. */ + struct scratch_buffer tmp; + + /* Number of bytes in buffer that are actually used. */ + size_t buffer_used; +}; + +static void +addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch) +{ + scratch->dataset = NULL; + scratch_buffer_init (&scratch->buffer); + scratch_buffer_init (&scratch->tmp); + + /* Reserve space for the header. */ + scratch->buffer_used = sizeof (struct dataset); + static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space), + "initial buffer space"); + memset (scratch->tmp.data, 0, sizeof (struct dataset)); +} + +static void +addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch) +{ + scratch_buffer_free (&scratch->buffer); + scratch_buffer_free (&scratch->tmp); +} + +/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH + could not be resized, otherwise a pointer to the copy. */ +static char * +addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch, + const char *s, size_t length) +{ + while (true) + { + size_t remaining = scratch->buffer.length - scratch->buffer_used; + if (remaining >= length) + break; + if (!scratch_buffer_grow_preserve (&scratch->buffer)) + return NULL; + } + char *copy = scratch->buffer.data + scratch->buffer_used; + memcpy (copy, s, length); + scratch->buffer_used += length; + return copy; +} + +/* Copy S into SCRATCH, including its null terminator. Returns false + if SCRATCH could not be resized. */ +static bool +addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s) +{ + if (s == NULL) + s = ""; + return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL; +} + +/* Caller must initialize and free *SCRATCH. If the return value is + negative, this function has sent a notfound response. */ 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, - void **tofreep) + struct datahead *dh, struct addgetnetgrentX_scratch *scratch) { if (__glibc_unlikely (debug_level > 0)) { @@ -132,14 +209,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, char *key_copy = NULL; struct __netgrent data; - size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len); - size_t buffilled = sizeof (*dataset); - char *buffer = NULL; size_t nentries = 0; 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_get (nss_database_netgroup, &netgroup_database)) @@ -151,8 +224,6 @@ 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; @@ -195,8 +266,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, while (1) { int e; - status = getfct.f (&data, buffer + buffilled, - buflen - buffilled - req->key_len, &e); + status = getfct.f (&data, scratch->tmp.data, + scratch->tmp.length, &e); if (status == NSS_STATUS_SUCCESS) { if (data.type == triple_val) @@ -204,68 +275,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, const char *nhost = data.val.triple.host; const char *nuser = data.val.triple.user; const char *ndomain = data.val.triple.domain; - - size_t hostlen = strlen (nhost ?: "") + 1; - size_t userlen = strlen (nuser ?: "") + 1; - size_t domainlen = strlen (ndomain ?: "") + 1; - - if (nhost == NULL || nuser == NULL || ndomain == NULL - || nhost > nuser || nuser > ndomain) - { - const char *last = nhost; - if (last == NULL - || (nuser != NULL && nuser > last)) - last = nuser; - if (last == NULL - || (ndomain != NULL && ndomain > last)) - last = ndomain; - - size_t bufused - = (last == NULL - ? buffilled - : last + strlen (last) + 1 - buffer); - - /* We have to make temporary copies. */ - size_t needed = hostlen + userlen + domainlen; - - if (buflen - req->key_len - bufused < needed) - { - buflen += MAX (buflen, 2 * needed); - /* Save offset in the old buffer. We don't - bother with the NULL check here since - we'll do that later anyway. */ - size_t nhostdiff = nhost - buffer; - size_t nuserdiff = nuser - buffer; - size_t ndomaindiff = ndomain - buffer; - - char *newbuf = xrealloc (buffer, buflen); - /* Fix up the triplet pointers into the new - buffer. */ - nhost = (nhost ? newbuf + nhostdiff - : NULL); - nuser = (nuser ? newbuf + nuserdiff - : NULL); - ndomain = (ndomain ? newbuf + ndomaindiff - : NULL); - *tofreep = buffer = newbuf; - } - - nhost = memcpy (buffer + bufused, - nhost ?: "", hostlen); - nuser = memcpy ((char *) nhost + hostlen, - nuser ?: "", userlen); - ndomain = memcpy ((char *) nuser + userlen, - ndomain ?: "", domainlen); - } - - char *wp = buffer + buffilled; - wp = memmove (wp, nhost ?: "", hostlen); - wp += hostlen; - wp = memmove (wp, nuser ?: "", userlen); - wp += userlen; - wp = memmove (wp, ndomain ?: "", domainlen); - wp += domainlen; - buffilled = wp - buffer; + if (!(addgetnetgrentX_append (scratch, nhost) + && addgetnetgrentX_append (scratch, nuser) + && addgetnetgrentX_append (scratch, ndomain))) + return send_notfound (fd); ++nentries; } else @@ -317,8 +330,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, } else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) { - buflen *= 2; - *tofreep = buffer = xrealloc (buffer, buflen); + if (!scratch_buffer_grow (&scratch->tmp)) + return send_notfound (fd); } else if (status == NSS_STATUS_RETURN || status == NSS_STATUS_NOTFOUND @@ -351,10 +364,17 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, goto maybe_cache_add; } - total = buffilled; + /* Capture the result size without the key appended. */ + total = scratch->buffer_used; + + /* Make a copy of the key. The scratch buffer must not move after + this point. */ + key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len); + if (key_copy == NULL) + return send_notfound (fd); /* Fill in the dataset. */ - dataset = (struct dataset *) buffer; + dataset = scratch->buffer.data; timeout = datahead_init_pos (&dataset->head, total + req->key_len, total - offsetof (struct dataset, resp), he == NULL ? 0 : dh->nreloads + 1, @@ -363,11 +383,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, dataset->resp.version = NSCD_VERSION; dataset->resp.found = 1; dataset->resp.nresults = nentries; - dataset->resp.result_len = buffilled - sizeof (*dataset); - - assert (buflen - buffilled >= req->key_len); - key_copy = memcpy (buffer + buffilled, key, req->key_len); - buffilled += req->key_len; + dataset->resp.result_len = total - sizeof (*dataset); /* Now we can determine whether on refill we have to create a new record or not. */ @@ -398,7 +414,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, if (__glibc_likely (newp != NULL)) { /* Adjust pointer into the memory block. */ - key_copy = (char *) newp + (key_copy - buffer); + key_copy = (char *) newp + (key_copy - (char *) dataset); dataset = memcpy (newp, dataset, total + req->key_len); cacheable = true; @@ -439,7 +455,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, } out: - *resultp = dataset; + scratch->dataset = dataset; return timeout; } @@ -460,6 +476,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, if (user != NULL) key = strchr (key, '\0') + 1; const char *domain = *key++ ? key : NULL; + struct addgetnetgrentX_scratch scratch; + + addgetnetgrentX_scratch_init (&scratch); if (__glibc_unlikely (debug_level > 0)) { @@ -475,12 +494,8 @@ 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; - tofree = NULL; - } + timeout = result->head.timeout; else { request_header req_get = @@ -489,7 +504,10 @@ 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, &tofree); + &scratch); + result = scratch.dataset; + if (timeout < 0) + goto out; } struct indataset @@ -601,7 +619,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, } out: - free (tofree); + addgetnetgrentX_scratch_free (&scratch); return timeout; } @@ -611,11 +629,12 @@ 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); + struct addgetnetgrentX_scratch scratch; + addgetnetgrentX_scratch_init (&scratch); + time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch); + addgetnetgrentX_scratch_free (&scratch); + if (timeout < 0) + timeout = 0; return timeout; } @@ -659,5 +678,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he, .key_len = he->len }; - return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh); + int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner, + he, dh); + if (timeout < 0) + timeout = 0; + return timeout; }