From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 393763DFC9C for ; Tue, 9 Jun 2026 18:24:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781029500; cv=none; b=DK+3GsTqedAzFyLSgwePPw411MwH6P3dwiZrjrMqUBn2AwK+n0Vfph2s0nFP3wtQk3oqikFVC63Jd6geuCk9NGF9/JDj2M5/9xDhcgRCGfBoxdxU3CE/5mjgfVvCdraQhayIpBRKr8Mi6X6M6Gz3XKPLw6IGu+byCA7PXmDsxus= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781029500; c=relaxed/simple; bh=h0qC/g9qPH8A8JOa7KFM7TefdBMjpjmgavOU87MHIc0=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=n9oRuF2XaMnxFJdJHyqCvPCesmEmWxNukpcNBWPV/wgAu8qZpPJTx1lWWInw3zEHU96LWeLiBTTnEUa3itPyOrIspY/eUAniPhTyG3V1fPSttXuP+dalA2Z03i5dbfpWWWgFUaBfhkYkJ/gsBaPns8q9HK2+mx33xqKA13nXsMA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ILjsDpWY; arc=none smtp.client-ip=209.85.160.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ILjsDpWY" Received: by mail-qt1-f178.google.com with SMTP id d75a77b69052e-517a5cafc3dso38462101cf.3 for ; Tue, 09 Jun 2026 11:24:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781029498; x=1781634298; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=nZ4xsWjsbWnXm3RQEz3hdKHfG6kaTnLOtHhVB+yWDzM=; b=ILjsDpWYls4dMSkkCiN4rY85z5vESHBIPD7cx8z5PEY3IXlz3xNWjVet76nnEV2YRJ 5VaqI+DajkNSHUIqCV/yl8kGCnv71+jLLckO4R/3nRnnBG7IE5BMppzJuGRxJJIZOWm1 iwlwYo5ZLTt/fs36jNV5pRIWAbpD8ldHSKn3wt3dbbHuwHzRHemJ2nBcXdWXYQgFjV9v yuDAf8Vy9DTaCNaWlqMS6iQkJJWkj+CzSbgokwm0pRwWNSD9JDIC+dm+Xtl6H22d/Rr0 BijNjRBpmaFw6MY7e1/ZLRAFbgAN90Zg7w0Q1EmOnnw4gjykFfpXOyY8DPJ/uC0pYSlM wGqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781029498; x=1781634298; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=nZ4xsWjsbWnXm3RQEz3hdKHfG6kaTnLOtHhVB+yWDzM=; b=I5SFyeo5lqHnpAVvo+UXhWCg8nTGoJtzljsigCVB3LwWnIDW61/1Q6ADspl2GezGu5 waz1/nfYccnj+0CHC2wgpQAsSfQM9x/QR7iF7JUi4DyYal58qb5sHYlEZqabzPGaQ73h LodWHMdx1byXmg/+4yjmDFYGYBw/5jNNqQLYx7wmjXNJU5qCyyt/yXHB3v3LWsVFu8Fv JC0VcqlRatOM7o5fudprcoksGUknWxW/B/HyqClFdhbZsVGTOMSdOj27N/atkfmyCq6t kO/HaxUVj5Gz9bM68dQbtvJTWJxFr6Cwky1NwJul2p5yEvl8WkxLnrX1FUwigd7d6Qug kpKg== X-Forwarded-Encrypted: i=1; AFNElJ8LKMyPdziSNC7ep0HuX5IZCYyZJJ66XdB/y6rtLhCHil3faGeIspB6otfS3QaBuJFjDsODl4dfQCsIaQU=@vger.kernel.org X-Gm-Message-State: AOJu0YzMs9DjkOIFIA/jQb5EZc0nKDnCgz6vnWcH2MdJ/urFV0Pbm6BL w1g01uSF6xYpXLKRyI5/46SBMTs72csF7S9mjr63kBq3L/6dYKp+Snk7 X-Gm-Gg: Acq92OF7QtDmW/BX5YkBCwL8vFmRYZnq0lLg58rY0/+R8MBG5RsPa8qMW9KJjbAzsUw TNVp9NnEsb6Ja0dfgnIlm8veNNhLNa1XGcOoIU6ryHTXgR89H3vU46T9yKYMmxDBbYcIcLKVWtg woExOyU37h6wAMZEWgFjANqyF9+t1/Qf3O7SZVahqqBeeyr+1O0Snv91mnVX5QaaMg4+GH2UYJV ERRkAZmvLv0AG8Nwq5azo+LDAlmF4+EsjCep8g8g0QOz+K1zsxepRIQuvQnZ0icJvrXrm+OTl2K rmZ3jgk13/etqF08Zg47E624QqJMQKLs+8adZIWm4j61qtNh+NK4kRKTLehI4nsHmqTFG9oyVfZ CikwHtVzRFC7GK5uiwsqv/ZWDehVi3trvyeQbAvXNwOObLZeevSZKdgD1tDTDLnswRHvWhqEiFt ur1+uRBmJYPvMl01TEO5w0SIA+23QRfcs1umXqps8Q2Q7Iv1lrWVO11uVioFQrOuhvDvyVvMkzr 3m5oyblQs1pJtrK4khLJTnATJuT0Y4= X-Received: by 2002:a05:622a:4818:b0:516:e01f:523a with SMTP id d75a77b69052e-51795bf3cf3mr319055121cf.43.1781029498000; Tue, 09 Jun 2026 11:24:58 -0700 (PDT) Received: from server0 (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-9158a3e0d55sm2174297385a.43.2026.06.09.11.24.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jun 2026 11:24:57 -0700 (PDT) From: Michael Bommarito To: Hannes Reinecke , Christoph Hellwig , Sagi Grimberg , Chaitanya Kulkarni Cc: Jens Axboe , linux-nvme@lists.infradead.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH v2] nvmet-auth: reject short AUTH_RECEIVE buffers Date: Tue, 9 Jun 2026 14:24:31 -0400 Message-ID: <20260609182431.2437882-1-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 7bit nvmet_execute_auth_receive() trusts the AUTH_RECEIVE allocation length after checking only that it is nonzero and matches the transfer length. In the SUCCESS1 and FAILURE1/default states, that lets a remote NVMe-oF initiator reach the fixed-size DH-HMAC-CHAP response builders with a kmalloc() buffer shorter than the response, so nvmet_auth_success1() and nvmet_auth_failure1() write past the allocation; both only WARN_ON the short length and then format the message anyway. Impact: A remote NVMe-oF initiator with access to an auth-enabled target can trigger a 16-byte heap out-of-bounds write via a one-byte AUTH_RECEIVE allocation length. Compute the minimum response length for the current DH-HMAC-CHAP step in nvmet_auth_receive_data_len() and report a zero data length when the host-supplied allocation length is shorter, so the existing zero-length check in nvmet_execute_auth_receive() rejects the command before any builder runs. The SUCCESS1 minimum is sizeof(struct nvmf_auth_dhchap_success1_data) plus the HMAC hash length, because the response hash is written into the rval[] flexible-array tail, so the minimum is state dependent rather than a flat sizeof. CHALLENGE keeps its existing variable-length guard in nvmet_auth_challenge(). This is reachable only when in-band DH-HMAC-CHAP authentication is configured on the target. Fixes: db1312dd9548 ("nvmet: implement basic In-Band Authentication") Cc: stable@vger.kernel.org Assisted-by: Codex:gpt-5-5-xhigh Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito --- v2: - Move the length check into nvmet_auth_receive_data_len() and reject via the existing zero-length guard in nvmet_execute_auth_receive(), per Hannes Reinecke's review. No separate helper, and nvmet_execute_auth_receive() itself is unchanged. With CONFIG_FORTIFY_SOURCE and KASAN enabled, a short al (for example al=1) on the SUCCESS1 path aborts in the sizeof(*data)=16 header memset in nvmet_auth_success1() with "memset: detected buffer overflow: 16 byte write of buffer size 1". After this change the same input is rejected before allocation and the abort no longer occurs. Validated with a KUnit/KASAN harness under UML: the stock kernel crashed and the patched kernel passed; the in-tree nvme-auth KUnit suite still passes. --- drivers/nvme/target/fabrics-cmd-auth.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c index f1e613e7c63e5..d4271fc43a95c 100644 --- a/drivers/nvme/target/fabrics-cmd-auth.c +++ b/drivers/nvme/target/fabrics-cmd-auth.c @@ -484,7 +484,31 @@ static void nvmet_auth_failure1(struct nvmet_req *req, void *d, int al) u32 nvmet_auth_receive_data_len(struct nvmet_req *req) { - return le32_to_cpu(req->cmd->auth_receive.al); + struct nvmet_ctrl *ctrl = req->sq->ctrl; + u32 al = le32_to_cpu(req->cmd->auth_receive.al); + u32 min_len; + + /* + * Reject too-short al before kmalloc(al), since the SUCCESS1 and + * FAILURE1/default builders write fixed response headers into it. + */ + switch (req->sq->dhchap_step) { + case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE: + return al; + case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1: + min_len = sizeof(struct nvmf_auth_dhchap_success1_data); + if (req->sq->dhchap_c2) + min_len += nvme_auth_hmac_hash_len(ctrl->shash_id); + break; + default: + min_len = sizeof(struct nvmf_auth_dhchap_failure_data); + break; + } + + if (al < min_len) + return 0; + + return al; } void nvmet_execute_auth_receive(struct nvmet_req *req) -- 2.53.0