History

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.

Xin Long committed 8 years ago

Commit bf2ae2e1 parent 9e5fb726 files · +33 −10Browse files

Unified · Split

6 files
  1. include/linux/net.h +1 −0
  2. include/net/sock.h +1 −0
  3. net/core/sock.c +21 −0
  4. net/core/sock_diag.c +4 −8
  5. net/ipv4/inet_diag.c +1 −2
  6. net/socket.c +5 −0
include/linux/net.h+1−0
@@ -222,6 +222,7 @@ enum { · 221 unmodified lines
222int sock_wake_async(struct socket_wq *sk_wq, int how, int band);222int sock_wake_async(struct socket_wq *sk_wq, int how, int band);
223int sock_register(const struct net_proto_family *fam);223int sock_register(const struct net_proto_family *fam);
224void sock_unregister(int family);224void sock_unregister(int family);
225bool sock_is_registered(int family);
225int __sock_create(struct net *net, int family, int type, int proto,226int __sock_create(struct net *net, int family, int type, int proto,
226 struct socket **res, int kern);227 struct socket **res, int kern);
227int sock_create(int family, int type, int proto, struct socket **res);228int sock_create(int family, int type, int proto, struct socket **res);
include/net/sock.h+1−0
@@ -1137,6 +1137,7 @@ struct proto { · 1136 unmodified lines
1137 1137
1138int proto_register(struct proto *prot, int alloc_slab);1138int proto_register(struct proto *prot, int alloc_slab);
1139void proto_unregister(struct proto *prot);1139void proto_unregister(struct proto *prot);
1140int sock_load_diag_module(int family, int protocol);
1140 1141
1141#ifdef SOCK_REFCNT_DEBUG1142#ifdef SOCK_REFCNT_DEBUG
1142static inline void sk_refcnt_debug_inc(struct sock *sk)1143static inline void sk_refcnt_debug_inc(struct sock *sk)
net/core/sock.c+21−0
@@ -3261,6 +3261,27 @@ void proto_unregister(struct proto *prot) · 3260 unmodified lines
3261}3261}
3262EXPORT_SYMBOL(proto_unregister);3262EXPORT_SYMBOL(proto_unregister);
3263 3263
3264int 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}
3283EXPORT_SYMBOL(sock_load_diag_module);
3284
3264#ifdef CONFIG_PROC_FS3285#ifdef CONFIG_PROC_FS
3265static void *proto_seq_start(struct seq_file *seq, loff_t *pos)3286static void *proto_seq_start(struct seq_file *seq, loff_t *pos)
3266 __acquires(proto_list_mutex)3287 __acquires(proto_list_mutex)
net/core/sock_diag.c+4−8
@@ -220,8 +220,7 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh) · 219 unmodified lines
220 return -EINVAL;220 return -EINVAL;
221 221
222 if (sock_diag_handlers[req->sdiag_family] == NULL)222 if (sock_diag_handlers[req->sdiag_family] == NULL)
223 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,223 sock_load_diag_module(req->sdiag_family, 0);
224 NETLINK_SOCK_DIAG, req->sdiag_family);
225 224
226 mutex_lock(&sock_diag_table_mutex);225 mutex_lock(&sock_diag_table_mutex);
227 hndl = sock_diag_handlers[req->sdiag_family];226 hndl = sock_diag_handlers[req->sdiag_family];
@@ -247,8 +246,7 @@ static int sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, · 19 unmodified lines
247 case TCPDIAG_GETSOCK:246 case TCPDIAG_GETSOCK:
248 case DCCPDIAG_GETSOCK:247 case DCCPDIAG_GETSOCK:
249 if (inet_rcv_compat == NULL)248 if (inet_rcv_compat == NULL)
250 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,249 sock_load_diag_module(AF_INET, 0);
251 NETLINK_SOCK_DIAG, AF_INET);
252 250
253 mutex_lock(&sock_diag_table_mutex);251 mutex_lock(&sock_diag_table_mutex);
254 if (inet_rcv_compat != NULL)252 if (inet_rcv_compat != NULL)
@@ -281,14 +279,12 @@ static int sock_diag_bind(struct net *net, int group) · 26 unmodified lines
281 case SKNLGRP_INET_TCP_DESTROY:279 case SKNLGRP_INET_TCP_DESTROY:
282 case SKNLGRP_INET_UDP_DESTROY:280 case SKNLGRP_INET_UDP_DESTROY:
283 if (!sock_diag_handlers[AF_INET])281 if (!sock_diag_handlers[AF_INET])
284 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,282 sock_load_diag_module(AF_INET, 0);
285 NETLINK_SOCK_DIAG, AF_INET);
286 break;283 break;
287 case SKNLGRP_INET6_TCP_DESTROY:284 case SKNLGRP_INET6_TCP_DESTROY:
288 case SKNLGRP_INET6_UDP_DESTROY:285 case SKNLGRP_INET6_UDP_DESTROY:
289 if (!sock_diag_handlers[AF_INET6])286 if (!sock_diag_handlers[AF_INET6])
290 request_module("net-pf-%d-proto-%d-type-%d", PF_NETLINK,287 sock_load_diag_module(AF_INET6, 0);
291 NETLINK_SOCK_DIAG, AF_INET6);
292 break;288 break;
293 }289 }
294 return 0;290 return 0;
net/ipv4/inet_diag.c+1−2
@@ -53,8 +53,7 @@ static DEFINE_MUTEX(inet_diag_table_mutex); · 52 unmodified lines
53static const struct inet_diag_handler *inet_diag_lock_handler(int proto)53static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
54{54{
55 if (!inet_diag_table[proto])55 if (!inet_diag_table[proto])
56 request_module("net-pf-%d-proto-%d-type-%d-%d", PF_NETLINK,56 sock_load_diag_module(AF_INET, proto);
57 NETLINK_SOCK_DIAG, AF_INET, proto);
58 57
59 mutex_lock(&inet_diag_table_mutex);58 mutex_lock(&inet_diag_table_mutex);
60 if (!inet_diag_table[proto])59 if (!inet_diag_table[proto])
net/socket.c+5−0
@@ -2587,6 +2587,11 @@ void sock_unregister(int family) · 2586 unmodified lines
2587}2587}
2588EXPORT_SYMBOL(sock_unregister);2588EXPORT_SYMBOL(sock_unregister);
2589 2589
2590bool sock_is_registered(int family)
2591{
2592 return family < NPROTO && rcu_access_pointer(net_families[family]);
2593}
2594
2590static int __init sock_init(void)2595static int __init sock_init(void)
2591{2596{
2592 int err;2597 int err;