提交 6c8f7e70 编写于 作者: T Thomas Graf 提交者: David S. Miller

netlink: hold nl_sock_hash_lock during diag dump

Although RCU protection would be possible during diag dump, doing
so allows for concurrent table mutations which can render the
in-table offset between individual Netlink messages invalid and
thus cause legitimate sockets to be skipped in the dump.

Since the diag dump is relatively low volume and consistency is
more important than performance, the table mutex is held during
dump.
Reported-by: NAndrey Wagin <avagin@gmail.com>
Signed-off-by: NThomas Graf <tgraf@suug.ch>
Fixes: e341694e ("netlink: Convert netlink_lookup() to use RCU protected hash table")
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 9ea88a15
...@@ -104,6 +104,7 @@ static atomic_t nl_table_users = ATOMIC_INIT(0); ...@@ -104,6 +104,7 @@ static atomic_t nl_table_users = ATOMIC_INIT(0);
/* Protects netlink socket hash table mutations */ /* Protects netlink socket hash table mutations */
DEFINE_MUTEX(nl_sk_hash_lock); DEFINE_MUTEX(nl_sk_hash_lock);
EXPORT_SYMBOL_GPL(nl_sk_hash_lock);
static int lockdep_nl_sk_hash_is_held(void) static int lockdep_nl_sk_hash_is_held(void)
{ {
......
...@@ -73,5 +73,6 @@ struct netlink_table { ...@@ -73,5 +73,6 @@ struct netlink_table {
extern struct netlink_table *nl_table; extern struct netlink_table *nl_table;
extern rwlock_t nl_table_lock; extern rwlock_t nl_table_lock;
extern struct mutex nl_sk_hash_lock;
#endif #endif
...@@ -170,6 +170,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -170,6 +170,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
req = nlmsg_data(cb->nlh); req = nlmsg_data(cb->nlh);
mutex_lock(&nl_sk_hash_lock);
read_lock(&nl_table_lock); read_lock(&nl_table_lock);
if (req->sdiag_protocol == NDIAG_PROTO_ALL) { if (req->sdiag_protocol == NDIAG_PROTO_ALL) {
...@@ -183,6 +184,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -183,6 +184,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
} else { } else {
if (req->sdiag_protocol >= MAX_LINKS) { if (req->sdiag_protocol >= MAX_LINKS) {
read_unlock(&nl_table_lock); read_unlock(&nl_table_lock);
mutex_unlock(&nl_sk_hash_lock);
return -ENOENT; return -ENOENT;
} }
...@@ -190,6 +192,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -190,6 +192,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
} }
read_unlock(&nl_table_lock); read_unlock(&nl_table_lock);
mutex_unlock(&nl_sk_hash_lock);
return skb->len; return skb->len;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册