hc
2024-05-16 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb
kernel/net/ipv4/inet_diag.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * inet_diag.c Module for monitoring INET transport protocols sockets.
34 *
45 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/kernel.h>
....@@ -27,6 +23,7 @@
2723 #include <net/inet_hashtables.h>
2824 #include <net/inet_timewait_sock.h>
2925 #include <net/inet6_hashtables.h>
26
+#include <net/bpf_sk_storage.h>
3027 #include <net/netlink.h>
3128
3229 #include <linux/inet.h>
....@@ -46,12 +43,20 @@
4643 u16 userlocks;
4744 u32 ifindex;
4845 u32 mark;
46
+#ifdef CONFIG_SOCK_CGROUP_DATA
47
+ u64 cgroup_id;
48
+#endif
4949 };
5050
5151 static DEFINE_MUTEX(inet_diag_table_mutex);
5252
5353 static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
5454 {
55
+ if (proto < 0 || proto >= IPPROTO_MAX) {
56
+ mutex_lock(&inet_diag_table_mutex);
57
+ return ERR_PTR(-ENOENT);
58
+ }
59
+
5560 if (!inet_diag_table[proto])
5661 sock_load_diag_module(AF_INET, proto);
5762
....@@ -120,6 +125,7 @@
120125 bool net_admin)
121126 {
122127 const struct inet_sock *inet = inet_sk(sk);
128
+ struct inet_diag_sockopt inet_sockopt;
123129
124130 if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
125131 goto errout;
....@@ -165,8 +171,31 @@
165171 goto errout;
166172 }
167173
174
+#ifdef CONFIG_SOCK_CGROUP_DATA
175
+ if (nla_put_u64_64bit(skb, INET_DIAG_CGROUP_ID,
176
+ cgroup_id(sock_cgroup_ptr(&sk->sk_cgrp_data)),
177
+ INET_DIAG_PAD))
178
+ goto errout;
179
+#endif
180
+
168181 r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
169182 r->idiag_inode = sock_i_ino(sk);
183
+
184
+ memset(&inet_sockopt, 0, sizeof(inet_sockopt));
185
+ inet_sockopt.recverr = inet->recverr;
186
+ inet_sockopt.is_icsk = inet->is_icsk;
187
+ inet_sockopt.freebind = inet->freebind;
188
+ inet_sockopt.hdrincl = inet->hdrincl;
189
+ inet_sockopt.mc_loop = inet->mc_loop;
190
+ inet_sockopt.transparent = inet->transparent;
191
+ inet_sockopt.mc_all = inet->mc_all;
192
+ inet_sockopt.nodefrag = inet->nodefrag;
193
+ inet_sockopt.bind_address_no_port = inet->bind_address_no_port;
194
+ inet_sockopt.recverr_rfc4884 = inet->recverr_rfc4884;
195
+ inet_sockopt.defer_connect = inet->defer_connect;
196
+ if (nla_put(skb, INET_DIAG_SOCKOPT, sizeof(inet_sockopt),
197
+ &inet_sockopt))
198
+ goto errout;
170199
171200 return 0;
172201 errout:
....@@ -174,26 +203,54 @@
174203 }
175204 EXPORT_SYMBOL_GPL(inet_diag_msg_attrs_fill);
176205
206
+static int inet_diag_parse_attrs(const struct nlmsghdr *nlh, int hdrlen,
207
+ struct nlattr **req_nlas)
208
+{
209
+ struct nlattr *nla;
210
+ int remaining;
211
+
212
+ nlmsg_for_each_attr(nla, nlh, hdrlen, remaining) {
213
+ int type = nla_type(nla);
214
+
215
+ if (type == INET_DIAG_REQ_PROTOCOL && nla_len(nla) != sizeof(u32))
216
+ return -EINVAL;
217
+
218
+ if (type < __INET_DIAG_REQ_MAX)
219
+ req_nlas[type] = nla;
220
+ }
221
+ return 0;
222
+}
223
+
224
+static int inet_diag_get_protocol(const struct inet_diag_req_v2 *req,
225
+ const struct inet_diag_dump_data *data)
226
+{
227
+ if (data->req_nlas[INET_DIAG_REQ_PROTOCOL])
228
+ return nla_get_u32(data->req_nlas[INET_DIAG_REQ_PROTOCOL]);
229
+ return req->sdiag_protocol;
230
+}
231
+
232
+#define MAX_DUMP_ALLOC_SIZE (KMALLOC_MAX_SIZE - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
233
+
177234 int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
178
- struct sk_buff *skb, const struct inet_diag_req_v2 *req,
179
- struct user_namespace *user_ns,
180
- u32 portid, u32 seq, u16 nlmsg_flags,
181
- const struct nlmsghdr *unlh,
182
- bool net_admin)
235
+ struct sk_buff *skb, struct netlink_callback *cb,
236
+ const struct inet_diag_req_v2 *req,
237
+ u16 nlmsg_flags, bool net_admin)
183238 {
184239 const struct tcp_congestion_ops *ca_ops;
185240 const struct inet_diag_handler *handler;
241
+ struct inet_diag_dump_data *cb_data;
186242 int ext = req->idiag_ext;
187243 struct inet_diag_msg *r;
188244 struct nlmsghdr *nlh;
189245 struct nlattr *attr;
190246 void *info = NULL;
191247
192
- handler = inet_diag_table[req->sdiag_protocol];
248
+ cb_data = cb->data;
249
+ handler = inet_diag_table[inet_diag_get_protocol(req, cb_data)];
193250 BUG_ON(!handler);
194251
195
- nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r),
196
- nlmsg_flags);
252
+ nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
253
+ cb->nlh->nlmsg_type, sizeof(*r), nlmsg_flags);
197254 if (!nlh)
198255 return -EMSGSIZE;
199256
....@@ -204,14 +261,17 @@
204261 r->idiag_state = sk->sk_state;
205262 r->idiag_timer = 0;
206263 r->idiag_retrans = 0;
264
+ r->idiag_expires = 0;
207265
208
- if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns, net_admin))
266
+ if (inet_diag_msg_attrs_fill(sk, skb, r, ext,
267
+ sk_user_ns(NETLINK_CB(cb->skb).sk),
268
+ net_admin))
209269 goto errout;
210270
211271 if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
212272 struct inet_diag_meminfo minfo = {
213273 .idiag_rmem = sk_rmem_alloc_get(sk),
214
- .idiag_wmem = sk->sk_wmem_queued,
274
+ .idiag_wmem = READ_ONCE(sk->sk_wmem_queued),
215275 .idiag_fmem = sk->sk_forward_alloc,
216276 .idiag_tmem = sk_wmem_alloc_get(sk),
217277 };
....@@ -244,20 +304,17 @@
244304 r->idiag_timer = 1;
245305 r->idiag_retrans = icsk->icsk_retransmits;
246306 r->idiag_expires =
247
- jiffies_to_msecs(icsk->icsk_timeout - jiffies);
307
+ jiffies_delta_to_msecs(icsk->icsk_timeout - jiffies);
248308 } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
249309 r->idiag_timer = 4;
250310 r->idiag_retrans = icsk->icsk_probes_out;
251311 r->idiag_expires =
252
- jiffies_to_msecs(icsk->icsk_timeout - jiffies);
312
+ jiffies_delta_to_msecs(icsk->icsk_timeout - jiffies);
253313 } else if (timer_pending(&sk->sk_timer)) {
254314 r->idiag_timer = 2;
255315 r->idiag_retrans = icsk->icsk_probes_out;
256316 r->idiag_expires =
257
- jiffies_to_msecs(sk->sk_timer.expires - jiffies);
258
- } else {
259
- r->idiag_timer = 0;
260
- r->idiag_expires = 0;
317
+ jiffies_delta_to_msecs(sk->sk_timer.expires - jiffies);
261318 }
262319
263320 if ((ext & (1 << (INET_DIAG_INFO - 1))) && handler->idiag_info_size) {
....@@ -302,6 +359,48 @@
302359 goto errout;
303360 }
304361
362
+ /* Keep it at the end for potential retry with a larger skb,
363
+ * or else do best-effort fitting, which is only done for the
364
+ * first_nlmsg.
365
+ */
366
+ if (cb_data->bpf_stg_diag) {
367
+ bool first_nlmsg = ((unsigned char *)nlh == skb->data);
368
+ unsigned int prev_min_dump_alloc;
369
+ unsigned int total_nla_size = 0;
370
+ unsigned int msg_len;
371
+ int err;
372
+
373
+ msg_len = skb_tail_pointer(skb) - (unsigned char *)nlh;
374
+ err = bpf_sk_storage_diag_put(cb_data->bpf_stg_diag, sk, skb,
375
+ INET_DIAG_SK_BPF_STORAGES,
376
+ &total_nla_size);
377
+
378
+ if (!err)
379
+ goto out;
380
+
381
+ total_nla_size += msg_len;
382
+ prev_min_dump_alloc = cb->min_dump_alloc;
383
+ if (total_nla_size > prev_min_dump_alloc)
384
+ cb->min_dump_alloc = min_t(u32, total_nla_size,
385
+ MAX_DUMP_ALLOC_SIZE);
386
+
387
+ if (!first_nlmsg)
388
+ goto errout;
389
+
390
+ if (cb->min_dump_alloc > prev_min_dump_alloc)
391
+ /* Retry with pskb_expand_head() with
392
+ * __GFP_DIRECT_RECLAIM
393
+ */
394
+ goto errout;
395
+
396
+ WARN_ON_ONCE(total_nla_size <= prev_min_dump_alloc);
397
+
398
+ /* Send what we have for this sk
399
+ * and move on to the next sk in the following
400
+ * dump()
401
+ */
402
+ }
403
+
305404 out:
306405 nlmsg_end(skb, nlh);
307406 return 0;
....@@ -312,46 +411,32 @@
312411 }
313412 EXPORT_SYMBOL_GPL(inet_sk_diag_fill);
314413
315
-static int inet_csk_diag_fill(struct sock *sk,
316
- struct sk_buff *skb,
317
- const struct inet_diag_req_v2 *req,
318
- struct user_namespace *user_ns,
319
- u32 portid, u32 seq, u16 nlmsg_flags,
320
- const struct nlmsghdr *unlh,
321
- bool net_admin)
322
-{
323
- return inet_sk_diag_fill(sk, inet_csk(sk), skb, req, user_ns,
324
- portid, seq, nlmsg_flags, unlh, net_admin);
325
-}
326
-
327414 static int inet_twsk_diag_fill(struct sock *sk,
328415 struct sk_buff *skb,
329
- u32 portid, u32 seq, u16 nlmsg_flags,
330
- const struct nlmsghdr *unlh)
416
+ struct netlink_callback *cb,
417
+ u16 nlmsg_flags)
331418 {
332419 struct inet_timewait_sock *tw = inet_twsk(sk);
333420 struct inet_diag_msg *r;
334421 struct nlmsghdr *nlh;
335422 long tmo;
336423
337
- nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r),
338
- nlmsg_flags);
424
+ nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
425
+ cb->nlh->nlmsg_seq, cb->nlh->nlmsg_type,
426
+ sizeof(*r), nlmsg_flags);
339427 if (!nlh)
340428 return -EMSGSIZE;
341429
342430 r = nlmsg_data(nlh);
343431 BUG_ON(tw->tw_state != TCP_TIME_WAIT);
344432
345
- tmo = tw->tw_timer.expires - jiffies;
346
- if (tmo < 0)
347
- tmo = 0;
348
-
349433 inet_diag_msg_common_fill(r, sk);
350434 r->idiag_retrans = 0;
351435
352436 r->idiag_state = tw->tw_substate;
353437 r->idiag_timer = 3;
354
- r->idiag_expires = jiffies_to_msecs(tmo);
438
+ tmo = tw->tw_timer.expires - jiffies;
439
+ r->idiag_expires = jiffies_delta_to_msecs(tmo);
355440 r->idiag_rqueue = 0;
356441 r->idiag_wqueue = 0;
357442 r->idiag_uid = 0;
....@@ -362,16 +447,16 @@
362447 }
363448
364449 static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
365
- u32 portid, u32 seq, u16 nlmsg_flags,
366
- const struct nlmsghdr *unlh, bool net_admin)
450
+ struct netlink_callback *cb,
451
+ u16 nlmsg_flags, bool net_admin)
367452 {
368453 struct request_sock *reqsk = inet_reqsk(sk);
369454 struct inet_diag_msg *r;
370455 struct nlmsghdr *nlh;
371456 long tmo;
372457
373
- nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r),
374
- nlmsg_flags);
458
+ nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
459
+ cb->nlh->nlmsg_type, sizeof(*r), nlmsg_flags);
375460 if (!nlh)
376461 return -EMSGSIZE;
377462
....@@ -385,7 +470,7 @@
385470 offsetof(struct sock, sk_cookie));
386471
387472 tmo = inet_reqsk(sk)->rsk_timer.expires - jiffies;
388
- r->idiag_expires = (tmo >= 0) ? jiffies_to_msecs(tmo) : 0;
473
+ r->idiag_expires = jiffies_delta_to_msecs(tmo);
389474 r->idiag_rqueue = 0;
390475 r->idiag_wqueue = 0;
391476 r->idiag_uid = 0;
....@@ -402,21 +487,18 @@
402487 }
403488
404489 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
490
+ struct netlink_callback *cb,
405491 const struct inet_diag_req_v2 *r,
406
- struct user_namespace *user_ns,
407
- u32 portid, u32 seq, u16 nlmsg_flags,
408
- const struct nlmsghdr *unlh, bool net_admin)
492
+ u16 nlmsg_flags, bool net_admin)
409493 {
410494 if (sk->sk_state == TCP_TIME_WAIT)
411
- return inet_twsk_diag_fill(sk, skb, portid, seq,
412
- nlmsg_flags, unlh);
495
+ return inet_twsk_diag_fill(sk, skb, cb, nlmsg_flags);
413496
414497 if (sk->sk_state == TCP_NEW_SYN_RECV)
415
- return inet_req_diag_fill(sk, skb, portid, seq,
416
- nlmsg_flags, unlh, net_admin);
498
+ return inet_req_diag_fill(sk, skb, cb, nlmsg_flags, net_admin);
417499
418
- return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq,
419
- nlmsg_flags, unlh, net_admin);
500
+ return inet_sk_diag_fill(sk, inet_csk(sk), skb, cb, r, nlmsg_flags,
501
+ net_admin);
420502 }
421503
422504 struct sock *inet_diag_find_one_icsk(struct net *net,
....@@ -464,10 +546,10 @@
464546 EXPORT_SYMBOL_GPL(inet_diag_find_one_icsk);
465547
466548 int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
467
- struct sk_buff *in_skb,
468
- const struct nlmsghdr *nlh,
549
+ struct netlink_callback *cb,
469550 const struct inet_diag_req_v2 *req)
470551 {
552
+ struct sk_buff *in_skb = cb->skb;
471553 bool net_admin = netlink_net_capable(in_skb, CAP_NET_ADMIN);
472554 struct net *net = sock_net(in_skb->sk);
473555 struct sk_buff *rep;
....@@ -484,10 +566,7 @@
484566 goto out;
485567 }
486568
487
- err = sk_diag_fill(sk, rep, req,
488
- sk_user_ns(NETLINK_CB(in_skb).sk),
489
- NETLINK_CB(in_skb).portid,
490
- nlh->nlmsg_seq, 0, nlh, net_admin);
569
+ err = sk_diag_fill(sk, rep, cb, req, 0, net_admin);
491570 if (err < 0) {
492571 WARN_ON(err == -EMSGSIZE);
493572 nlmsg_free(rep);
....@@ -508,20 +587,35 @@
508587
509588 static int inet_diag_cmd_exact(int cmd, struct sk_buff *in_skb,
510589 const struct nlmsghdr *nlh,
590
+ int hdrlen,
511591 const struct inet_diag_req_v2 *req)
512592 {
513593 const struct inet_diag_handler *handler;
514
- int err;
594
+ struct inet_diag_dump_data dump_data;
595
+ int err, protocol;
515596
516
- handler = inet_diag_lock_handler(req->sdiag_protocol);
517
- if (IS_ERR(handler))
597
+ memset(&dump_data, 0, sizeof(dump_data));
598
+ err = inet_diag_parse_attrs(nlh, hdrlen, dump_data.req_nlas);
599
+ if (err)
600
+ return err;
601
+
602
+ protocol = inet_diag_get_protocol(req, &dump_data);
603
+
604
+ handler = inet_diag_lock_handler(protocol);
605
+ if (IS_ERR(handler)) {
518606 err = PTR_ERR(handler);
519
- else if (cmd == SOCK_DIAG_BY_FAMILY)
520
- err = handler->dump_one(in_skb, nlh, req);
521
- else if (cmd == SOCK_DESTROY && handler->destroy)
607
+ } else if (cmd == SOCK_DIAG_BY_FAMILY) {
608
+ struct netlink_callback cb = {
609
+ .nlh = nlh,
610
+ .skb = in_skb,
611
+ .data = &dump_data,
612
+ };
613
+ err = handler->dump_one(&cb, req);
614
+ } else if (cmd == SOCK_DESTROY && handler->destroy) {
522615 err = handler->destroy(in_skb, req);
523
- else
616
+ } else {
524617 err = -EOPNOTSUPP;
618
+ }
525619 inet_diag_unlock_handler(handler);
526620
527621 return err;
....@@ -647,6 +741,16 @@
647741 yes = 0;
648742 break;
649743 }
744
+#ifdef CONFIG_SOCK_CGROUP_DATA
745
+ case INET_DIAG_BC_CGROUP_COND: {
746
+ u64 cgroup_id;
747
+
748
+ cgroup_id = get_unaligned((const u64 *)(op + 1));
749
+ if (cgroup_id != entry->cgroup_id)
750
+ yes = 0;
751
+ break;
752
+ }
753
+#endif
650754 }
651755
652756 if (yes) {
....@@ -697,6 +801,10 @@
697801 entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark;
698802 else
699803 entry.mark = 0;
804
+#ifdef CONFIG_SOCK_CGROUP_DATA
805
+ entry.cgroup_id = sk_fullsock(sk) ?
806
+ cgroup_id(sock_cgroup_ptr(&sk->sk_cgrp_data)) : 0;
807
+#endif
700808
701809 return inet_diag_bc_run(bc, &entry);
702810 }
....@@ -786,6 +894,15 @@
786894 return len >= *min_len;
787895 }
788896
897
+#ifdef CONFIG_SOCK_CGROUP_DATA
898
+static bool valid_cgroupcond(const struct inet_diag_bc_op *op, int len,
899
+ int *min_len)
900
+{
901
+ *min_len += sizeof(u64);
902
+ return len >= *min_len;
903
+}
904
+#endif
905
+
789906 static int inet_diag_bc_audit(const struct nlattr *attr,
790907 const struct sk_buff *skb)
791908 {
....@@ -828,6 +945,12 @@
828945 if (!valid_markcond(bc, len, &min_len))
829946 return -EINVAL;
830947 break;
948
+#ifdef CONFIG_SOCK_CGROUP_DATA
949
+ case INET_DIAG_BC_CGROUP_COND:
950
+ if (!valid_cgroupcond(bc, len, &min_len))
951
+ return -EINVAL;
952
+ break;
953
+#endif
831954 case INET_DIAG_BC_AUTO:
832955 case INET_DIAG_BC_JMP:
833956 case INET_DIAG_BC_NOP:
....@@ -850,23 +973,6 @@
850973 len -= op->yes;
851974 }
852975 return len == 0 ? 0 : -EINVAL;
853
-}
854
-
855
-static int inet_csk_diag_dump(struct sock *sk,
856
- struct sk_buff *skb,
857
- struct netlink_callback *cb,
858
- const struct inet_diag_req_v2 *r,
859
- const struct nlattr *bc,
860
- bool net_admin)
861
-{
862
- if (!inet_diag_bc_sk(bc, sk))
863
- return 0;
864
-
865
- return inet_csk_diag_fill(sk, skb, r,
866
- sk_user_ns(NETLINK_CB(cb->skb).sk),
867
- NETLINK_CB(cb->skb).portid,
868
- cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh,
869
- net_admin);
870976 }
871977
872978 static void twsk_build_assert(void)
....@@ -897,14 +1003,17 @@
8971003
8981004 void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
8991005 struct netlink_callback *cb,
900
- const struct inet_diag_req_v2 *r, struct nlattr *bc)
1006
+ const struct inet_diag_req_v2 *r)
9011007 {
9021008 bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
1009
+ struct inet_diag_dump_data *cb_data = cb->data;
9031010 struct net *net = sock_net(skb->sk);
9041011 u32 idiag_states = r->idiag_states;
9051012 int i, num, s_i, s_num;
1013
+ struct nlattr *bc;
9061014 struct sock *sk;
9071015
1016
+ bc = cb_data->inet_diag_nla_bc;
9081017 if (idiag_states & TCPF_SYN_RECV)
9091018 idiag_states |= TCPF_NEW_SYN_RECV;
9101019 s_i = cb->args[1];
....@@ -940,8 +1049,12 @@
9401049 r->id.idiag_sport)
9411050 goto next_listen;
9421051
943
- if (inet_csk_diag_dump(sk, skb, cb, r,
944
- bc, net_admin) < 0) {
1052
+ if (!inet_diag_bc_sk(bc, sk))
1053
+ goto next_listen;
1054
+
1055
+ if (inet_sk_diag_fill(sk, inet_csk(sk), skb,
1056
+ cb, r, NLM_F_MULTI,
1057
+ net_admin) < 0) {
9451058 spin_unlock(&ilb->lock);
9461059 goto done;
9471060 }
....@@ -1019,11 +1132,8 @@
10191132 res = 0;
10201133 for (idx = 0; idx < accum; idx++) {
10211134 if (res >= 0) {
1022
- res = sk_diag_fill(sk_arr[idx], skb, r,
1023
- sk_user_ns(NETLINK_CB(cb->skb).sk),
1024
- NETLINK_CB(cb->skb).portid,
1025
- cb->nlh->nlmsg_seq, NLM_F_MULTI,
1026
- cb->nlh, net_admin);
1135
+ res = sk_diag_fill(sk_arr[idx], skb, cb, r,
1136
+ NLM_F_MULTI, net_admin);
10271137 if (res < 0)
10281138 num = num_arr[idx];
10291139 }
....@@ -1047,31 +1157,101 @@
10471157 EXPORT_SYMBOL_GPL(inet_diag_dump_icsk);
10481158
10491159 static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
1050
- const struct inet_diag_req_v2 *r,
1051
- struct nlattr *bc)
1160
+ const struct inet_diag_req_v2 *r)
10521161 {
1162
+ struct inet_diag_dump_data *cb_data = cb->data;
10531163 const struct inet_diag_handler *handler;
1054
- int err = 0;
1164
+ u32 prev_min_dump_alloc;
1165
+ int protocol, err = 0;
10551166
1056
- handler = inet_diag_lock_handler(r->sdiag_protocol);
1167
+ protocol = inet_diag_get_protocol(r, cb_data);
1168
+
1169
+again:
1170
+ prev_min_dump_alloc = cb->min_dump_alloc;
1171
+ handler = inet_diag_lock_handler(protocol);
10571172 if (!IS_ERR(handler))
1058
- handler->dump(skb, cb, r, bc);
1173
+ handler->dump(skb, cb, r);
10591174 else
10601175 err = PTR_ERR(handler);
10611176 inet_diag_unlock_handler(handler);
1177
+
1178
+ /* The skb is not large enough to fit one sk info and
1179
+ * inet_sk_diag_fill() has requested for a larger skb.
1180
+ */
1181
+ if (!skb->len && cb->min_dump_alloc > prev_min_dump_alloc) {
1182
+ err = pskb_expand_head(skb, 0, cb->min_dump_alloc, GFP_KERNEL);
1183
+ if (!err)
1184
+ goto again;
1185
+ }
10621186
10631187 return err ? : skb->len;
10641188 }
10651189
10661190 static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
10671191 {
1068
- int hdrlen = sizeof(struct inet_diag_req_v2);
1069
- struct nlattr *bc = NULL;
1192
+ return __inet_diag_dump(skb, cb, nlmsg_data(cb->nlh));
1193
+}
10701194
1071
- if (nlmsg_attrlen(cb->nlh, hdrlen))
1072
- bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE);
1195
+static int __inet_diag_dump_start(struct netlink_callback *cb, int hdrlen)
1196
+{
1197
+ const struct nlmsghdr *nlh = cb->nlh;
1198
+ struct inet_diag_dump_data *cb_data;
1199
+ struct sk_buff *skb = cb->skb;
1200
+ struct nlattr *nla;
1201
+ int err;
10731202
1074
- return __inet_diag_dump(skb, cb, nlmsg_data(cb->nlh), bc);
1203
+ cb_data = kzalloc(sizeof(*cb_data), GFP_KERNEL);
1204
+ if (!cb_data)
1205
+ return -ENOMEM;
1206
+
1207
+ err = inet_diag_parse_attrs(nlh, hdrlen, cb_data->req_nlas);
1208
+ if (err) {
1209
+ kfree(cb_data);
1210
+ return err;
1211
+ }
1212
+ nla = cb_data->inet_diag_nla_bc;
1213
+ if (nla) {
1214
+ err = inet_diag_bc_audit(nla, skb);
1215
+ if (err) {
1216
+ kfree(cb_data);
1217
+ return err;
1218
+ }
1219
+ }
1220
+
1221
+ nla = cb_data->inet_diag_nla_bpf_stgs;
1222
+ if (nla) {
1223
+ struct bpf_sk_storage_diag *bpf_stg_diag;
1224
+
1225
+ bpf_stg_diag = bpf_sk_storage_diag_alloc(nla);
1226
+ if (IS_ERR(bpf_stg_diag)) {
1227
+ kfree(cb_data);
1228
+ return PTR_ERR(bpf_stg_diag);
1229
+ }
1230
+ cb_data->bpf_stg_diag = bpf_stg_diag;
1231
+ }
1232
+
1233
+ cb->data = cb_data;
1234
+ return 0;
1235
+}
1236
+
1237
+static int inet_diag_dump_start(struct netlink_callback *cb)
1238
+{
1239
+ return __inet_diag_dump_start(cb, sizeof(struct inet_diag_req_v2));
1240
+}
1241
+
1242
+static int inet_diag_dump_start_compat(struct netlink_callback *cb)
1243
+{
1244
+ return __inet_diag_dump_start(cb, sizeof(struct inet_diag_req));
1245
+}
1246
+
1247
+static int inet_diag_dump_done(struct netlink_callback *cb)
1248
+{
1249
+ struct inet_diag_dump_data *cb_data = cb->data;
1250
+
1251
+ bpf_sk_storage_diag_free(cb_data->bpf_stg_diag);
1252
+ kfree(cb->data);
1253
+
1254
+ return 0;
10751255 }
10761256
10771257 static int inet_diag_type2proto(int type)
....@@ -1090,9 +1270,7 @@
10901270 struct netlink_callback *cb)
10911271 {
10921272 struct inet_diag_req *rc = nlmsg_data(cb->nlh);
1093
- int hdrlen = sizeof(struct inet_diag_req);
10941273 struct inet_diag_req_v2 req;
1095
- struct nlattr *bc = NULL;
10961274
10971275 req.sdiag_family = AF_UNSPEC; /* compatibility */
10981276 req.sdiag_protocol = inet_diag_type2proto(cb->nlh->nlmsg_type);
....@@ -1100,10 +1278,7 @@
11001278 req.idiag_states = rc->idiag_states;
11011279 req.id = rc->id;
11021280
1103
- if (nlmsg_attrlen(cb->nlh, hdrlen))
1104
- bc = nlmsg_find_attr(cb->nlh, hdrlen, INET_DIAG_REQ_BYTECODE);
1105
-
1106
- return __inet_diag_dump(skb, cb, &req, bc);
1281
+ return __inet_diag_dump(skb, cb, &req);
11071282 }
11081283
11091284 static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
....@@ -1118,7 +1293,8 @@
11181293 req.idiag_states = rc->idiag_states;
11191294 req.id = rc->id;
11201295
1121
- return inet_diag_cmd_exact(SOCK_DIAG_BY_FAMILY, in_skb, nlh, &req);
1296
+ return inet_diag_cmd_exact(SOCK_DIAG_BY_FAMILY, in_skb, nlh,
1297
+ sizeof(struct inet_diag_req), &req);
11221298 }
11231299
11241300 static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
....@@ -1131,22 +1307,12 @@
11311307 return -EINVAL;
11321308
11331309 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1134
- if (nlmsg_attrlen(nlh, hdrlen)) {
1135
- struct nlattr *attr;
1136
- int err;
1137
-
1138
- attr = nlmsg_find_attr(nlh, hdrlen,
1139
- INET_DIAG_REQ_BYTECODE);
1140
- err = inet_diag_bc_audit(attr, skb);
1141
- if (err)
1142
- return err;
1143
- }
1144
- {
1145
- struct netlink_dump_control c = {
1146
- .dump = inet_diag_dump_compat,
1147
- };
1148
- return netlink_dump_start(net->diag_nlsk, skb, nlh, &c);
1149
- }
1310
+ struct netlink_dump_control c = {
1311
+ .start = inet_diag_dump_start_compat,
1312
+ .done = inet_diag_dump_done,
1313
+ .dump = inet_diag_dump_compat,
1314
+ };
1315
+ return netlink_dump_start(net->diag_nlsk, skb, nlh, &c);
11501316 }
11511317
11521318 return inet_diag_get_exact_compat(skb, nlh);
....@@ -1162,25 +1328,16 @@
11621328
11631329 if (h->nlmsg_type == SOCK_DIAG_BY_FAMILY &&
11641330 h->nlmsg_flags & NLM_F_DUMP) {
1165
- if (nlmsg_attrlen(h, hdrlen)) {
1166
- struct nlattr *attr;
1167
- int err;
1168
-
1169
- attr = nlmsg_find_attr(h, hdrlen,
1170
- INET_DIAG_REQ_BYTECODE);
1171
- err = inet_diag_bc_audit(attr, skb);
1172
- if (err)
1173
- return err;
1174
- }
1175
- {
1176
- struct netlink_dump_control c = {
1177
- .dump = inet_diag_dump,
1178
- };
1179
- return netlink_dump_start(net->diag_nlsk, skb, h, &c);
1180
- }
1331
+ struct netlink_dump_control c = {
1332
+ .start = inet_diag_dump_start,
1333
+ .done = inet_diag_dump_done,
1334
+ .dump = inet_diag_dump,
1335
+ };
1336
+ return netlink_dump_start(net->diag_nlsk, skb, h, &c);
11811337 }
11821338
1183
- return inet_diag_cmd_exact(h->nlmsg_type, skb, h, nlmsg_data(h));
1339
+ return inet_diag_cmd_exact(h->nlmsg_type, skb, h, hdrlen,
1340
+ nlmsg_data(h));
11841341 }
11851342
11861343 static
....@@ -1315,11 +1472,7 @@
13151472 kfree(inet_diag_table);
13161473 }
13171474
1318
-#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
1319
-rootfs_initcall(inet_diag_init);
1320
-#else
13211475 module_init(inet_diag_init);
1322
-#endif
13231476 module_exit(inet_diag_exit);
13241477 MODULE_LICENSE("GPL");
13251478 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 2 /* AF_INET */);