From: Linkui Xiao <redacted>
devl_sb_unregister() looks the shared buffer up by index and only warns
when it is not on the list. list_del() and kfree() are then called on the
NULL result, so unregistering an index that was never registered, or
unregistering the same index twice, turns the warning into a NULL pointer
dereference. list is the first member of struct devlink_sb, so list_del()
reads the next and prev pointers from address 0 before storing to them.
The register side already fails gracefully: devl_sb_register() returns
-EEXIST when the index is taken. Make the unregister side symmetric and
return after the warning.
Fixes: bf7974710a40 ("devlink: add shared buffer configuration")
Signed-off-by: Linkui Xiao <redacted>
---
net/devlink/sb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/devlink/sb.c b/net/devlink/sb.c
index 129bd016e302..4b444f2ca0f5 100644
--- a/net/devlink/sb.c
+++ b/net/devlink/sb.c
@@ -980,7 +980,8 @@ void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index)
lockdep_assert_held(&devlink->lock);
devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
- WARN_ON(!devlink_sb);
+ if (WARN_ON(!devlink_sb))
+ return;
list_del(&devlink_sb->list);
kfree(devlink_sb);
}
--
2.25.1