summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorChristian Gromm <christian.gromm@microchip.com>2020-01-23 18:38:22 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-24 12:08:41 +0300
commitf9e6b51a998da782cfc201dc9309d3a3d8579fef (patch)
tree237b69ed9111f03a2a046a26f9a199a69e76bf51 /drivers/staging
parentb7935e52dd98696a8c1379f5b67b0c344ee3bc35 (diff)
downloadlinux-f9e6b51a998da782cfc201dc9309d3a3d8579fef.tar.xz
staging: next: configfs: fix release link
The functions link_destroy and link_release are both deleting list items. link_release, however, does not check whether a certain link has already been deleted from the list by function link_destroy. By fixing this this patch prevents a kernel crash when removing the configuration directory of a link that already has been destroyed. Signed-off-by: Christian Gromm <christian.gromm@microchip.com> Link: https://lore.kernel.org/r/1579793906-5054-7-git-send-email-christian.gromm@microchip.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/most/configfs.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/drivers/staging/most/configfs.c b/drivers/staging/most/configfs.c
index 034ab96ef69e..9a961222f458 100644
--- a/drivers/staging/most/configfs.c
+++ b/drivers/staging/most/configfs.c
@@ -128,6 +128,8 @@ static ssize_t mdev_link_create_link_store(struct config_item *item,
return ret;
list_add_tail(&mdev_link->list, &mdev_link_list);
mdev_link->create_link = tmp;
+ mdev_link->destroy_link = false;
+
return count;
}
@@ -143,13 +145,16 @@ static ssize_t mdev_link_destroy_link_store(struct config_item *item,
return ret;
if (!tmp)
return count;
- mdev_link->destroy_link = tmp;
+
ret = most_remove_link(mdev_link->device, mdev_link->channel,
mdev_link->comp);
if (ret)
return ret;
if (!list_empty(&mdev_link_list))
list_del(&mdev_link->list);
+
+ mdev_link->destroy_link = tmp;
+
return count;
}
@@ -378,13 +383,20 @@ static void mdev_link_release(struct config_item *item)
struct mdev_link *mdev_link = to_mdev_link(item);
int ret;
- if (!list_empty(&mdev_link_list)) {
- ret = most_remove_link(mdev_link->device, mdev_link->channel,
- mdev_link->comp);
- if (ret && (ret != -ENODEV))
- pr_err("Removing link failed.\n");
- list_del(&mdev_link->list);
+ if (mdev_link->destroy_link)
+ goto free_item;
+
+ ret = most_remove_link(mdev_link->device, mdev_link->channel,
+ mdev_link->comp);
+ if (ret) {
+ pr_err("Removing link failed.\n");
+ goto free_item;
}
+
+ if (!list_empty(&mdev_link_list))
+ list_del(&mdev_link->list);
+
+free_item:
kfree(to_mdev_link(item));
}