mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
nvmet-auth: validate reply message payload bounds against transfer length
nvmet_auth_reply() accesses the variable-length rval[] array using
attacker-controlled hl (hash length) and dhvlen (DH value length) fields
without verifying they fit within the allocated buffer of tl bytes.
A malicious NVMe-oF initiator can craft a DHCHAP_REPLY message with a
small transfer length but large hl/dhvlen values, causing out-of-bounds
heap reads when the target processes the DH public key (rval + 2*hl) or
performs the host response memcmp.
With DH authentication configured, the OOB pointer is passed directly to
sg_init_one() and read by crypto_kpp_compute_shared_secret(), reaching
up to 526 bytes past the buffer. This is exploitable pre-authentication.
Add bounds validation ensuring sizeof(*data) + 2*hl + dhvlen <= tl before
any access to the variable-length fields.
Discovered by Atuin - Automated Vulnerability Discovery Engine.
Fixes: db1312dd95 ("nvmet: implement basic In-Band Authentication")
Cc: stable@vger.kernel.org
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
parent
59c0517123
commit
3a413ece25
|
|
@ -132,13 +132,22 @@ static u8 nvmet_auth_negotiate(struct nvmet_req *req, void *d)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u8 nvmet_auth_reply(struct nvmet_req *req, void *d)
|
||||
static u8 nvmet_auth_reply(struct nvmet_req *req, void *d, u32 tl)
|
||||
{
|
||||
struct nvmet_ctrl *ctrl = req->sq->ctrl;
|
||||
struct nvmf_auth_dhchap_reply_data *data = d;
|
||||
u16 dhvlen = le16_to_cpu(data->dhvlen);
|
||||
u16 dhvlen;
|
||||
u8 *response;
|
||||
|
||||
if (tl < sizeof(*data))
|
||||
return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
|
||||
|
||||
dhvlen = le16_to_cpu(data->dhvlen);
|
||||
|
||||
/* Validate that hl and dhvlen fit within the transfer length */
|
||||
if (sizeof(*data) + 2 * (size_t)data->hl + dhvlen > tl)
|
||||
return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
|
||||
|
||||
pr_debug("%s: ctrl %d qid %d: data hl %d cvalid %d dhvlen %u\n",
|
||||
__func__, ctrl->cntlid, req->sq->qid,
|
||||
data->hl, data->cvalid, dhvlen);
|
||||
|
|
@ -338,7 +347,7 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
|
|||
|
||||
switch (data->auth_id) {
|
||||
case NVME_AUTH_DHCHAP_MESSAGE_REPLY:
|
||||
dhchap_status = nvmet_auth_reply(req, d);
|
||||
dhchap_status = nvmet_auth_reply(req, d, tl);
|
||||
if (dhchap_status == 0)
|
||||
req->sq->dhchap_step =
|
||||
NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user