Linux-NVME Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs
@ 2026-10-28  6:44 Guixin Liu
  2026-10-28  6:55 ` sashiko-bot
  2026-10-28  7:42 ` Hannes Reinecke
  0 siblings, 2 replies; 6+ messages in thread
From: Guixin Liu @ 2026-10-28  6:44 UTC (permalink / raw)
  To: Keith Busch, Jens Axboe, Christoph Hellwig, Sagi Grimberg,
	Nilay Shroff, Daniel Wagner, Hannes Reinecke
  Cc: linux-nvme

nvmet_ctrl_tls_key_show() dereferences ctrl->sqs[0] unconditionally,
but the admin queue is not installed yet while the controller is
being created, and sqs[0] is set to NULL again when it is destroyed.
Reading the tls_key debugfs entry in either window crashes the kernel.

Only query the queue's TLS key when the admin queue is present and
report 0 otherwise.

Fixes: 316dabe6089fe ("nvmet: add tls_concat and tls_key debugfs entries")
Cc: stable@vger.kernel.org
Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
---
 drivers/nvme/target/debugfs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
index e85fe1d4c9f8..a27a501fe61a 100644
--- a/drivers/nvme/target/debugfs.c
+++ b/drivers/nvme/target/debugfs.c
@@ -136,8 +136,10 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
 static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
 {
 	struct nvmet_ctrl *ctrl = m->private;
-	key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
+	key_serial_t keyid = 0;
 
+	if (ctrl->sqs[0])
+		keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
 	seq_printf(m, "%08x\n", keyid);
 	return 0;
 }
-- 
2.43.7



^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs
  2026-10-28  6:44 [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs Guixin Liu
@ 2026-10-28  6:55 ` sashiko-bot
  2026-10-28  7:42 ` Hannes Reinecke
  1 sibling, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-10-28  6:55 UTC (permalink / raw)
  To: Guixin Liu; +Cc: linux-nvme

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] nvmet: unsynchronized ctrl->sqs[0] access in nvmet_ctrl_tls_key_show()
--

commit 3cf90339b7ea83703b0eb52aef8d8c4af5c44e19
Author: Guixin Liu <kanie@linux.alibaba.com>

nvmet: Check the admin queue before reading its TLS key in debugfs

This commit checks whether ctrl->sqs[0] is non-NULL in
nvmet_ctrl_tls_key_show() before querying the admin queue's TLS key ID for
debugfs output.

> diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
> index e85fe1d4c9f8d..a27a501fe61a4 100644
> --- a/drivers/nvme/target/debugfs.c
> +++ b/drivers/nvme/target/debugfs.c
> @@ -136,8 +136,10 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
>  static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
>  {
>  	struct nvmet_ctrl *ctrl = m->private;
> -	key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
> +	key_serial_t keyid = 0;
>  
> +	if (ctrl->sqs[0])
> +		keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);

[Severity: High]
Can this unlocked check and reload of ctrl->sqs[0] race with admin queue
teardown in nvmet_tcp_release_queue_work() and nvmet_sq_destroy(), or with
the error path in nvmet_install_queue()?

First, ctrl->sqs[0] is checked and then reloaded without READ_ONCE() or any
lock synchronizing against nvmet_sq_destroy() in drivers/nvme/target/core.c:

    if (sq->qid == 0) {
        ctrl->reset_tbkas = true;
        sq->ctrl->sqs[sq->qid] = NULL;
        nvmet_ctrl_put(ctrl);
    }

If ctrl->sqs[0] is cleared to NULL between the if (ctrl->sqs[0]) check and
the argument evaluation for nvmet_queue_tls_keyid(ctrl->sqs[0]), NULL is
passed into nvmet_queue_tls_keyid() in drivers/nvme/target/nvmet.h:

    static inline key_serial_t nvmet_queue_tls_keyid(struct nvmet_sq *sq)
    {
        return sq->tls_key ? key_serial(sq->tls_key) : 0;
    }

which dereferences sq->tls_key on a NULL pointer.

Second, even when ctrl->sqs[0] is read as non-NULL, nothing pins the queue or
sq->tls_key while nvmet_ctrl_tls_key_show() runs. During queue teardown in
drivers/nvme/target/tcp.c, nvmet_tcp_release_queue_work() executes:

    nvmet_sq_put_tls_key(&queue->nvme_sq);
    nvmet_tcp_uninit_data_in_cmds(queue);
    nvmet_sq_destroy(&queue->nvme_sq);
    ...
    kfree(queue);

where nvmet_sq_put_tls_key() in drivers/nvme/target/nvmet.h drops the key
reference before ctrl->sqs[0] is cleared:

    static inline void nvmet_sq_put_tls_key(struct nvmet_sq *sq)
    {
        if (sq->tls_key) {
            key_put(sq->tls_key);
            sq->tls_key = NULL;
        }
    }

Because the controller debugfs directory stays alive until the final
ctrl->ref is dropped in nvmet_ctrl_free() -> nvmet_debugfs_ctrl_free(ctrl)
(for example, while queue->nvme_cq or I/O queues still hold controller
references), a concurrent reader of the tls_key debugfs file can dereference
sq->tls_key after key_put() or dereference sq after kfree(queue).

Could this be avoided by reading the key directly from ctrl->tls_key (or
caching the key serial on struct nvmet_ctrl), or by properly serializing
access to the queue and its key?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261028064417.548948-1-kanie@linux.alibaba.com?part=1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs
  2026-10-28  6:44 [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs Guixin Liu
  2026-10-28  6:55 ` sashiko-bot
@ 2026-10-28  7:42 ` Hannes Reinecke
  2026-10-28  8:24   ` Guixin Liu
  1 sibling, 1 reply; 6+ messages in thread
From: Hannes Reinecke @ 2026-10-28  7:42 UTC (permalink / raw)
  To: Guixin Liu, Keith Busch, Jens Axboe, Christoph Hellwig,
	Sagi Grimberg, Nilay Shroff, Daniel Wagner
  Cc: linux-nvme

On 10/28/26 7:44 AM, Guixin Liu wrote:
> nvmet_ctrl_tls_key_show() dereferences ctrl->sqs[0] unconditionally,
> but the admin queue is not installed yet while the controller is
> being created, and sqs[0] is set to NULL again when it is destroyed.
> Reading the tls_key debugfs entry in either window crashes the kernel.
> 
> Only query the queue's TLS key when the admin queue is present and
> report 0 otherwise.
> 
> Fixes: 316dabe6089fe ("nvmet: add tls_concat and tls_key debugfs entries")
> Cc: stable@vger.kernel.org
> Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
> ---
>   drivers/nvme/target/debugfs.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
> index e85fe1d4c9f8..a27a501fe61a 100644
> --- a/drivers/nvme/target/debugfs.c
> +++ b/drivers/nvme/target/debugfs.c
> @@ -136,8 +136,10 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
>   static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
>   {
>   	struct nvmet_ctrl *ctrl = m->private;
> -	key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
> +	key_serial_t keyid = 0;
>   
> +	if (ctrl->sqs[0])
> +		keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>   	seq_printf(m, "%08x\n", keyid);
>   	return 0;
>   }

I think it might be easier if 'nvmet_queue_tls_keyid()' would accept
a NULL argument.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs
  2026-10-28  7:42 ` Hannes Reinecke
@ 2026-10-28  8:24   ` Guixin Liu
  2026-10-28 14:48     ` Hannes Reinecke
  0 siblings, 1 reply; 6+ messages in thread
From: Guixin Liu @ 2026-10-28  8:24 UTC (permalink / raw)
  To: Hannes Reinecke, Keith Busch, Jens Axboe, Christoph Hellwig,
	Sagi Grimberg, Nilay Shroff, Daniel Wagner
  Cc: linux-nvme



在 2026/10/28 15:42, Hannes Reinecke 写道:
> On 10/28/26 7:44 AM, Guixin Liu wrote:
>> nvmet_ctrl_tls_key_show() dereferences ctrl->sqs[0] unconditionally,
>> but the admin queue is not installed yet while the controller is
>> being created, and sqs[0] is set to NULL again when it is destroyed.
>> Reading the tls_key debugfs entry in either window crashes the kernel.
>>
>> Only query the queue's TLS key when the admin queue is present and
>> report 0 otherwise.
>>
>> Fixes: 316dabe6089fe ("nvmet: add tls_concat and tls_key debugfs entries")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
>> ---
>>   drivers/nvme/target/debugfs.c | 4 +++-
>>   1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
>> index e85fe1d4c9f8..a27a501fe61a 100644
>> --- a/drivers/nvme/target/debugfs.c
>> +++ b/drivers/nvme/target/debugfs.c
>> @@ -136,8 +136,10 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
>>   static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
>>   {
>>       struct nvmet_ctrl *ctrl = m->private;
>> -    key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>> +    key_serial_t keyid = 0;
>>   +    if (ctrl->sqs[0])
>> +        keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>>       seq_printf(m, "%08x\n", keyid);
>>       return 0;
>>   }
>
> I think it might be easier if 'nvmet_queue_tls_keyid()' would accept
> a NULL argument.
This is simpler, however Sashiko's review points out that after the
NULL check, sq->tls_key clould be freed by nvmet_sq_put_tls_key(),
or sq itself could be destroyed. 

My idea is store admin queue's tls_key to nvmet_ctrl to prevent access
sq and sq->tls_key in debugfs interface, what do you think?

Best Regards,
Guixin Liu
>
> Cheers,
>
> Hannes



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs
  2026-10-28  8:24   ` Guixin Liu
@ 2026-10-28 14:48     ` Hannes Reinecke
  2026-10-29  3:32       ` Guixin Liu
  0 siblings, 1 reply; 6+ messages in thread
From: Hannes Reinecke @ 2026-10-28 14:48 UTC (permalink / raw)
  To: Guixin Liu, Keith Busch, Jens Axboe, Christoph Hellwig,
	Sagi Grimberg, Nilay Shroff, Daniel Wagner
  Cc: linux-nvme

On 10/28/26 9:24 AM, Guixin Liu wrote:
> 
> 
> 在 2026/10/28 15:42, Hannes Reinecke 写道:
>> On 10/28/26 7:44 AM, Guixin Liu wrote:
>>> nvmet_ctrl_tls_key_show() dereferences ctrl->sqs[0] unconditionally,
>>> but the admin queue is not installed yet while the controller is
>>> being created, and sqs[0] is set to NULL again when it is destroyed.
>>> Reading the tls_key debugfs entry in either window crashes the kernel.
>>>
>>> Only query the queue's TLS key when the admin queue is present and
>>> report 0 otherwise.
>>>
>>> Fixes: 316dabe6089fe ("nvmet: add tls_concat and tls_key debugfs entries")
>>> Cc: stable@vger.kernel.org
>>> Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
>>> ---
>>>    drivers/nvme/target/debugfs.c | 4 +++-
>>>    1 file changed, 3 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
>>> index e85fe1d4c9f8..a27a501fe61a 100644
>>> --- a/drivers/nvme/target/debugfs.c
>>> +++ b/drivers/nvme/target/debugfs.c
>>> @@ -136,8 +136,10 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
>>>    static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
>>>    {
>>>        struct nvmet_ctrl *ctrl = m->private;
>>> -    key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>>> +    key_serial_t keyid = 0;
>>>    +    if (ctrl->sqs[0])
>>> +        keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>>>        seq_printf(m, "%08x\n", keyid);
>>>        return 0;
>>>    }
>>
>> I think it might be easier if 'nvmet_queue_tls_keyid()' would accept
>> a NULL argument.
> This is simpler, however Sashiko's review points out that after the
> NULL check, sq->tls_key clould be freed by nvmet_sq_put_tls_key(),
> or sq itself could be destroyed.
> 
> My idea is store admin queue's tls_key to nvmet_ctrl to prevent access
> sq and sq->tls_key in debugfs interface, what do you think?
> 
Argl. Don't.

I would do something like

key_serial_t keyid = ctrl->sqs ? nvmet_queue_tls_keyid(ctrl->sqs[0]):0;

to make it clear that ctrl->sqs might be NULL here.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
hare@suse.de                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs
  2026-10-28 14:48     ` Hannes Reinecke
@ 2026-10-29  3:32       ` Guixin Liu
  0 siblings, 0 replies; 6+ messages in thread
From: Guixin Liu @ 2026-10-29  3:32 UTC (permalink / raw)
  To: Hannes Reinecke, Keith Busch, Jens Axboe, Christoph Hellwig,
	Sagi Grimberg, Nilay Shroff, Daniel Wagner
  Cc: linux-nvme



在 2026/10/28 22:48, Hannes Reinecke 写道:
> On 10/28/26 9:24 AM, Guixin Liu wrote:
>>
>>
>> 在 2026/10/28 15:42, Hannes Reinecke 写道:
>>> On 10/28/26 7:44 AM, Guixin Liu wrote:
>>>> nvmet_ctrl_tls_key_show() dereferences ctrl->sqs[0] unconditionally,
>>>> but the admin queue is not installed yet while the controller is
>>>> being created, and sqs[0] is set to NULL again when it is destroyed.
>>>> Reading the tls_key debugfs entry in either window crashes the kernel.
>>>>
>>>> Only query the queue's TLS key when the admin queue is present and
>>>> report 0 otherwise.
>>>>
>>>> Fixes: 316dabe6089fe ("nvmet: add tls_concat and tls_key debugfs entries")
>>>> Cc: stable@vger.kernel.org
>>>> Signed-off-by: Guixin Liu <kanie@linux.alibaba.com>
>>>> ---
>>>>    drivers/nvme/target/debugfs.c | 4 +++-
>>>>    1 file changed, 3 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/nvme/target/debugfs.c b/drivers/nvme/target/debugfs.c
>>>> index e85fe1d4c9f8..a27a501fe61a 100644
>>>> --- a/drivers/nvme/target/debugfs.c
>>>> +++ b/drivers/nvme/target/debugfs.c
>>>> @@ -136,8 +136,10 @@ NVMET_DEBUGFS_ATTR(nvmet_ctrl_host_traddr);
>>>>    static int nvmet_ctrl_tls_key_show(struct seq_file *m, void *p)
>>>>    {
>>>>        struct nvmet_ctrl *ctrl = m->private;
>>>> -    key_serial_t keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>>>> +    key_serial_t keyid = 0;
>>>>    +    if (ctrl->sqs[0])
>>>> +        keyid = nvmet_queue_tls_keyid(ctrl->sqs[0]);
>>>>        seq_printf(m, "%08x\n", keyid);
>>>>        return 0;
>>>>    }
>>>
>>> I think it might be easier if 'nvmet_queue_tls_keyid()' would accept
>>> a NULL argument.
>> This is simpler, however Sashiko's review points out that after the
>> NULL check, sq->tls_key clould be freed by nvmet_sq_put_tls_key(),
>> or sq itself could be destroyed.
>>
>> My idea is store admin queue's tls_key to nvmet_ctrl to prevent access
>> sq and sq->tls_key in debugfs interface, what do you think?
>>
> Argl. Don't.
>
> I would do something like
>
> key_serial_t keyid = ctrl->sqs ? nvmet_queue_tls_keyid(ctrl->sqs[0]):0;
>
> to make it clear that ctrl->sqs might be NULL here.
>
> Cheers,
>
> Hannes
OK, I will send a v2 patch.

Best Regards,
Guixin Liu



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-10-29  3:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28  6:44 [PATCH] nvmet: Check the admin queue before reading its TLS key in debugfs Guixin Liu
2026-10-28  6:55 ` sashiko-bot
2026-10-28  7:42 ` Hannes Reinecke
2026-10-28  8:24   ` Guixin Liu
2026-10-28 14:48     ` Hannes Reinecke
2026-10-29  3:32       ` Guixin Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox