summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorTakamitsu Iwai <takamitz@amazon.co.jp>2025-08-23 11:58:56 +0300
committerJakub Kicinski <kuba@kernel.org>2025-08-27 17:43:08 +0300
commitd860d1faa6b2ce3becfdb8b0c2b048ad31800061 (patch)
treea27770249cfd5066696f5bc917acf37170a632d1 /include
parentdcb34659028f856c423a29ef9b4e2571d203444d (diff)
downloadlinux-d860d1faa6b2ce3becfdb8b0c2b048ad31800061.tar.xz
net: rose: convert 'use' field to refcount_t
The 'use' field in struct rose_neigh is used as a reference counter but lacks atomicity. This can lead to race conditions where a rose_neigh structure is freed while still being referenced by other code paths. For example, when rose_neigh->use becomes zero during an ioctl operation via rose_rt_ioctl(), the structure may be removed while its timer is still active, potentially causing use-after-free issues. This patch changes the type of 'use' from unsigned short to refcount_t and updates all code paths to use rose_neigh_hold() and rose_neigh_put() which operate reference counts atomically. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Takamitsu Iwai <takamitz@amazon.co.jp> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20250823085857.47674-3-takamitz@amazon.co.jp Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/net/rose.h18
1 files changed, 13 insertions, 5 deletions
diff --git a/include/net/rose.h b/include/net/rose.h
index 174b4f605d84..2b5491bbf39a 100644
--- a/include/net/rose.h
+++ b/include/net/rose.h
@@ -8,6 +8,7 @@
#ifndef _ROSE_H
#define _ROSE_H
+#include <linux/refcount.h>
#include <linux/rose.h>
#include <net/ax25.h>
#include <net/sock.h>
@@ -96,7 +97,7 @@ struct rose_neigh {
ax25_cb *ax25;
struct net_device *dev;
unsigned short count;
- unsigned short use;
+ refcount_t use;
unsigned int number;
char restarted;
char dce_mode;
@@ -151,12 +152,19 @@ struct rose_sock {
#define rose_sk(sk) ((struct rose_sock *)(sk))
+static inline void rose_neigh_hold(struct rose_neigh *rose_neigh)
+{
+ refcount_inc(&rose_neigh->use);
+}
+
static inline void rose_neigh_put(struct rose_neigh *rose_neigh)
{
- if (rose_neigh->ax25)
- ax25_cb_put(rose_neigh->ax25);
- kfree(rose_neigh->digipeat);
- kfree(rose_neigh);
+ if (refcount_dec_and_test(&rose_neigh->use)) {
+ if (rose_neigh->ax25)
+ ax25_cb_put(rose_neigh->ax25);
+ kfree(rose_neigh->digipeat);
+ kfree(rose_neigh);
+ }
}
/* af_rose.c */