Skip to content

Commit bf2ae2e

Browse files
lxindavem330
authored andcommitted
sock_diag: request _diag module only when the family or proto has been registered
Now when using 'ss' in iproute, kernel would try to load all _diag modules, which also causes corresponding family and proto modules to be loaded as well due to module dependencies. Like after running 'ss', sctp, dccp, af_packet (if it works as a module) would be loaded. For example: $ lsmod|grep sctp $ ss $ lsmod|grep sctp sctp_diag 16384 0 sctp 323584 5 sctp_diag inet_diag 24576 4 raw_diag,tcp_diag,sctp_diag,udp_diag libcrc32c 16384 3 nf_conntrack,nf_nat,sctp As these family and proto modules are loaded unintentionally, it could cause some problems, like: - Some debug tools use 'ss' to collect the socket info, which loads all those diag and family and protocol modules. It's noisy for identifying issues. - Users usually expect to drop sctp init packet silently when they have no sense of sctp protocol instead of sending abort back. - It wastes resources (especially with multiple netns), and SCTP module can't be unloaded once it's loaded. ... In short, it's really inappropriate to have these family and proto modules loaded unexpectedly when just doing debugging with inet_diag. This patch is to introduce sock_load_diag_module() where it loads the _diag module only when it's corresponding family or proto has been already registered. Note that we can't just load _diag module without the family or proto loaded, as some symbols used in _diag module are from the family or proto module. v1->v2: - move inet proto check to inet_diag to avoid a compiling err. v2->v3: - define sock_load_diag_module in sock.c and export one symbol only. - improve the changelog. Reported-by: Sabrina Dubroca <[email protected]> Acked-by: Marcelo Ricardo Leitner <[email protected]> Acked-by: Phil Sutter <[email protected]> Acked-by: Sabrina Dubroca <[email protected]> Signed-off-by: Xin Long <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9e5fb72 commit bf2ae2e

File tree

6 files changed

+33
-10
lines changed

6 files changed

+33
-10
lines changed

include/linux/net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ enum {
222222
int sock_wake_async(struct socket_wq *sk_wq, int how, int band);
223223
int sock_register(const struct net_proto_family *fam);
224224
void sock_unregister(int family);
225+
bool sock_is_registered(int family);
225226
int __sock_create(struct net *net, int family, int type, int proto,
226227
struct socket **res, int kern);
227228
int sock_create(int family, int type, int proto, struct socket **res);

include/net/sock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,7 @@ struct proto {
11371137

11381138
int proto_register(struct proto *prot, int alloc_slab);
11391139
void proto_unregister(struct proto *prot);
1140+
int sock_load_diag_module(int family, int protocol);
11401141

11411142
#ifdef SOCK_REFCNT_DEBUG
11421143
static inline void sk_refcnt_debug_inc(struct sock *sk)

net/core/sock.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3261,6 +3261,27 @@ void proto_unregister(struct proto *prot)
32613261
}
32623262
EXPORT_SYMBOL(proto_unregister);
32633263

3264+
int sock_load_diag_module(int family, int protocol)
3265+
{
3266+
if (!protocol) {
3267+
if (!sock_is_registered(family))
3268+
return -ENOENT;
3269+
3270+
return request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
3271+
NETLINK_SOCK_DIAG, family);
3272+
}
3273+
3274+
#ifdef CONFIG_INET
3275+
if (family == AF_INET &&
3276+
!rcu_access_pointer(inet_protos[protocol]))
3277+
return -ENOENT;
3278+
#endif
3279+
3280+
return request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK,
3281+
NETLINK_SOCK_DIAG, family, protocol);
3282+
}
3283+
EXPORT_SYMBOL(sock_load_diag_module);
3284+
32643285
#ifdef CONFIG_PROC_FS
32653286
static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
32663287
__acquires(proto_list_mutex)

net/core/sock_diag.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,7 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh)
220220
return -EINVAL;
221221

222222
if (sock_diag_handlers[req->sdiag_family] == NULL)
223-
request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
224-
NETLINK_SOCK_DIAG, req->sdiag_family);
223+
sock_load_diag_module(req->sdiag_family, 0);
225224

226225
mutex_lock(&sock_diag_table_mutex);
227226
hndl = sock_diag_handlers[req->sdiag_family];
@@ -247,8 +246,7 @@ static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
247246
case TCPDIAG_GETSOCK:
248247
case DCCPDIAG_GETSOCK:
249248
if (inet_rcv_compat == NULL)
250-
request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
251-
NETLINK_SOCK_DIAG, AF_INET);
249+
sock_load_diag_module(AF_INET, 0);
252250

253251
mutex_lock(&sock_diag_table_mutex);
254252
if (inet_rcv_compat != NULL)
@@ -281,14 +279,12 @@ static int sock_diag_bind(struct net *net, int group)
281279
case SKNLGRP_INET_TCP_DESTROY:
282280
case SKNLGRP_INET_UDP_DESTROY:
283281
if (!sock_diag_handlers[AF_INET])
284-
request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
285-
NETLINK_SOCK_DIAG, AF_INET);
282+
sock_load_diag_module(AF_INET, 0);
286283
break;
287284
case SKNLGRP_INET6_TCP_DESTROY:
288285
case SKNLGRP_INET6_UDP_DESTROY:
289286
if (!sock_diag_handlers[AF_INET6])
290-
request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,
291-
NETLINK_SOCK_DIAG, AF_INET6);
287+
sock_load_diag_module(AF_INET6, 0);
292288
break;
293289
}
294290
return 0;

net/ipv4/inet_diag.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ static DEFINE_MUTEX(inet_diag_table_mutex);
5353
static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
5454
{
5555
if (!inet_diag_table[proto])
56-
request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK,
57-
NETLINK_SOCK_DIAG, AF_INET, proto);
56+
sock_load_diag_module(AF_INET, proto);
5857

5958
mutex_lock(&inet_diag_table_mutex);
6059
if (!inet_diag_table[proto])

net/socket.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2587,6 +2587,11 @@ void sock_unregister(int family)
25872587
}
25882588
EXPORT_SYMBOL(sock_unregister);
25892589

2590+
bool sock_is_registered(int family)
2591+
{
2592+
return family < NPROTO && rcu_access_pointer(net_families[family]);
2593+
}
2594+
25902595
static int __init sock_init(void)
25912596
{
25922597
int err;

0 commit comments

Comments
 (0)