diff options
| author | Josef Bacik <josef@toxicpanda.com> | 2026-10-28 10:41:20 -0600 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-10-29 07:23:19 -0600 |
| commit | 81941915d53ef3384ab4e4b68e92673e66cf66d7 (patch) | |
| tree | 2c2c87b79887ec14d059266b9b86e50b268d9808 | |
| parent | d9667ade40f986c565769a900ced6ee95edd33c6 (diff) | |
| download | linux-81941915d53ef3384ab4e4b68e92673e66cf66d7.tar.gz linux-81941915d53ef3384ab4e4b68e92673e66cf66d7.zip | |
block/rnbd-srv: drop the sess_dev kobject unlocked
rnbd_srv_create_dev_session_sysfs() drops the kobject reference when it
fails. The release function is rnbd_destroy_sess_dev(), which takes
srv_dev->lock, and the caller holds that lock: the worker deadlocks on
itself. A client opening one device as "ram0" and "./ram0" gets there
through -EEXIST from kobject_add().
Have process_msg_open() drop the reference after releasing the lock, and
leave the rest of the cleanup to the release function.
Fixes: 8cee532f469b ("block/rnbd: server: sysfs interface functions")
Fixes: d3a95ccaaf4d ("block/rnbd: call kobject_put in the failure path")
Cc: "Md. Haris Iqbal" <haris.iqbal@ionos.com>
Cc: Jack Wang <jinpu.wang@ionos.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Link: https://patch.msgid.link/20261028164415.1262013-18-axboe@kernel.dk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
| -rw-r--r-- | drivers/block/rnbd/rnbd-srv-sysfs.c | 12 | ||||
| -rw-r--r-- | drivers/block/rnbd/rnbd-srv.c | 8 |
2 files changed, 13 insertions, 7 deletions
diff --git a/drivers/block/rnbd/rnbd-srv-sysfs.c b/drivers/block/rnbd/rnbd-srv-sysfs.c index 33d5d1738be5..9d00c42f2624 100644 --- a/drivers/block/rnbd/rnbd-srv-sysfs.c +++ b/drivers/block/rnbd/rnbd-srv-sysfs.c @@ -193,6 +193,10 @@ static const struct kobj_type rnbd_srv_sess_dev_ktype = { .release = rnbd_srv_sess_dev_release, }; +/* + * On failure the caller has to drop the reference of the kobject. The release + * function takes the lock of the device, which the caller holds here. + */ int rnbd_srv_create_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev) { int ret; @@ -200,17 +204,13 @@ int rnbd_srv_create_dev_session_sysfs(struct rnbd_srv_sess_dev *sess_dev) ret = kobject_init_and_add(&sess_dev->kobj, &rnbd_srv_sess_dev_ktype, sess_dev->dev->dev_sessions_kobj, "%s", sess_dev->sess->sessname); - if (ret) { - kobject_put(&sess_dev->kobj); + if (ret) return ret; - } ret = sysfs_create_group(&sess_dev->kobj, &rnbd_srv_default_dev_session_attr_group); - if (ret) { + if (ret) kobject_del(&sess_dev->kobj); - kobject_put(&sess_dev->kobj); - } return ret; } diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c index 2b0619389fc9..1e3de82fd70b 100644 --- a/drivers/block/rnbd/rnbd-srv.c +++ b/drivers/block/rnbd/rnbd-srv.c @@ -590,6 +590,7 @@ rnbd_srv_create_set_sess_dev(struct rnbd_srv_session *srv_sess, return sdev; kref_init(&sdev->kref); + INIT_LIST_HEAD(&sdev->dev_list); strscpy(sdev->pathname, open_msg->dev_name, sizeof(sdev->pathname)); @@ -789,7 +790,12 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess, rnbd_srv_err(srv_sess_dev, "Opening device failed, failed to create dev client sysfs files, err: %d\n", ret); - goto free_srv_sess_dev; + /* + * rnbd_destroy_sess_dev() undoes everything down to the open + * of the block device. + */ + kobject_put(&srv_sess_dev->kobj); + goto free_path; } list_add(&srv_sess_dev->dev_list, &srv_dev->sess_dev_list); |
