@@ -167,6 +167,11 @@ static inline int process_ip4(struct iphdr *ip4, void *data_end, statkey *key) {
167
167
return NOK ;
168
168
}
169
169
170
+ // Skip packets with both source and destination addresses zero
171
+ if (ip4 -> saddr == 0 && ip4 -> daddr == 0 ) {
172
+ return NOK ;
173
+ }
174
+
170
175
// convert to V4MAPPED address
171
176
__builtin_memcpy (key -> srcip .s6_addr , ip4in6 , sizeof (ip4in6 ));
172
177
__builtin_memcpy (key -> srcip .s6_addr + sizeof (ip4in6 ), & ip4 -> saddr ,
@@ -223,6 +228,12 @@ static inline int process_ip4(struct iphdr *ip4, void *data_end, statkey *key) {
223
228
}
224
229
}
225
230
231
+ // Skip packets with destination IP 0.0.0.0 and destination port 0
232
+ // This catches unconnected/invalid socket states
233
+ if (ip4 -> daddr == 0 && key -> dst_port == 0 ) {
234
+ return NOK ;
235
+ }
236
+
226
237
return OK ;
227
238
}
228
239
@@ -249,6 +260,16 @@ static inline int process_ip6(struct ipv6hdr *ip6, void *data_end,
249
260
key -> dstip = ip6 -> daddr ;
250
261
key -> proto = ip6 -> nexthdr ;
251
262
263
+ // Check if both IPv6 addresses are unspecified (all zeros)
264
+ int src_empty = 1 , dst_empty = 1 ;
265
+ for (int i = 0 ; i < 4 ; i ++ ) {
266
+ if (key -> srcip .s6_addr32 [i ] != 0 ) src_empty = 0 ;
267
+ if (key -> dstip .s6_addr32 [i ] != 0 ) dst_empty = 0 ;
268
+ }
269
+ if (src_empty && dst_empty ) {
270
+ return NOK ;
271
+ }
272
+
252
273
switch (ip6 -> nexthdr ) {
253
274
case IPPROTO_TCP : {
254
275
struct tcphdr * tcp = (void * )ip6 + sizeof (* ip6 );
@@ -293,6 +314,11 @@ static inline int process_ip6(struct ipv6hdr *ip6, void *data_end,
293
314
}
294
315
}
295
316
317
+ // Skip packets with destination IPv6 unspecified and destination port 0
318
+ if (dst_empty && key -> dst_port == 0 ) {
319
+ return NOK ;
320
+ }
321
+
296
322
return OK ;
297
323
}
298
324
@@ -584,18 +610,43 @@ int cgroup_skb_egress(struct __sk_buff *skb) {
584
610
*
585
611
* @throws none
586
612
*/
587
- static inline void process_tcp (struct sock * sk , statkey * key , pid_t pid ) {
613
+ static inline int process_tcp (struct sock * sk , statkey * key , pid_t pid ) {
614
+ // Validate socket pointer
615
+ if (!sk ) {
616
+ return -1 ;
617
+ }
618
+
588
619
__u16 family = BPF_CORE_READ (sk , __sk_common .skc_family );
620
+
621
+ // Only process supported address families
622
+ if (family != AF_INET && family != AF_INET6 ) {
623
+ return -1 ;
624
+ }
589
625
590
626
switch (family ) {
591
627
case AF_INET : {
592
628
// convert to V4MAPPED address
593
629
__be32 ip4_src = BPF_CORE_READ (sk , __sk_common .skc_rcv_saddr );
630
+ __be32 ip4_dst = BPF_CORE_READ (sk , __sk_common .skc_daddr );
631
+
632
+ // Skip sockets with both addresses zero (unconnected/invalid state)
633
+ if (ip4_src == 0 && ip4_dst == 0 ) {
634
+ return -1 ;
635
+ }
636
+
637
+ // Also skip sockets with destination IP 0.0.0.0 and port 0 (unconnected state)
638
+ if (ip4_dst == 0 ) {
639
+ // Need to read ports first to check dst_port
640
+ __u16 sport = BPF_CORE_READ (sk , __sk_common .skc_num );
641
+ __u16 dport = BPF_CORE_READ (sk , __sk_common .skc_dport );
642
+ if (bpf_ntohs (dport ) == 0 ) {
643
+ return -1 ;
644
+ }
645
+ }
646
+
594
647
key -> srcip .s6_addr16 [5 ] = bpf_htons (0xffff );
595
648
__builtin_memcpy (& key -> srcip .s6_addr32 [3 ], & ip4_src , sizeof (ip4_src ));
596
649
597
- // convert to V4MAPPED address
598
- __be32 ip4_dst = BPF_CORE_READ (sk , __sk_common .skc_daddr );
599
650
key -> dstip .s6_addr16 [5 ] = bpf_htons (0xffff );
600
651
__builtin_memcpy (& key -> dstip .s6_addr32 [3 ], & ip4_dst , sizeof (ip4_dst ));
601
652
@@ -605,23 +656,38 @@ static inline void process_tcp(struct sock *sk, statkey *key, pid_t pid) {
605
656
BPF_CORE_READ_INTO (& key -> srcip , sk , __sk_common .skc_v6_rcv_saddr );
606
657
BPF_CORE_READ_INTO (& key -> dstip , sk , __sk_common .skc_v6_daddr );
607
658
659
+ // Check if both IPv6 addresses are unspecified (all zeros)
660
+ int src_empty = 1 , dst_empty = 1 ;
661
+ for (int i = 0 ; i < 4 ; i ++ ) {
662
+ if (key -> srcip .s6_addr32 [i ] != 0 ) src_empty = 0 ;
663
+ if (key -> dstip .s6_addr32 [i ] != 0 ) dst_empty = 0 ;
664
+ }
665
+ if (src_empty && dst_empty ) {
666
+ return -1 ;
667
+ }
668
+
608
669
break ;
609
670
}
610
671
default : {
611
- return ;
672
+ return -1 ;
612
673
}
613
674
}
614
675
615
676
__u16 sport = BPF_CORE_READ (sk , __sk_common .skc_num );
677
+ __u16 dport = BPF_CORE_READ (sk , __sk_common .skc_dport );
678
+
616
679
if (sport == 0 ) {
617
680
struct inet_sock * isk = (struct inet_sock * )sk ;
618
681
BPF_CORE_READ_INTO (& sport , isk , inet_sport );
619
682
}
683
+
620
684
key -> src_port = bpf_ntohs (sport );
621
- key -> dst_port = bpf_ntohs (BPF_CORE_READ ( sk , __sk_common . skc_dport ) );
685
+ key -> dst_port = bpf_ntohs (dport );
622
686
623
687
key -> proto = IPPROTO_TCP ;
624
688
key -> pid = pid ;
689
+
690
+ return 0 ;
625
691
}
626
692
627
693
/**
@@ -948,7 +1014,9 @@ int BPF_KPROBE(tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) {
948
1014
bpf_get_current_comm (& key .comm , sizeof (key .comm ));
949
1015
}
950
1016
951
- process_tcp (sk , & key , pid );
1017
+ if (process_tcp (sk , & key , pid ) != 0 ) {
1018
+ return 0 ; // Skip invalid socket
1019
+ }
952
1020
update_val (& key , size );
953
1021
954
1022
return 0 ;
@@ -982,7 +1050,9 @@ int BPF_KPROBE(tcp_cleanup_rbuf, struct sock *sk, int copied) {
982
1050
bpf_get_current_comm (& key .comm , sizeof (key .comm ));
983
1051
}
984
1052
985
- process_tcp (sk , & key , pid );
1053
+ if (process_tcp (sk , & key , pid ) != 0 ) {
1054
+ return 0 ; // Skip invalid socket
1055
+ }
986
1056
update_val (& key , copied );
987
1057
988
1058
return 0 ;
@@ -1281,7 +1351,9 @@ int BPF_KPROBE(ip_local_out_fn, struct sk_buff *skb, struct net *net) {
1281
1351
if (sk ) {
1282
1352
// Let's use the safer process_tcp function which already works in existing
1283
1353
// kprobes
1284
- process_tcp (sk , & key , pid );
1354
+ if (process_tcp (sk , & key , pid ) != 0 ) {
1355
+ return 0 ; // Skip invalid socket
1356
+ }
1285
1357
update_val (& key , len );
1286
1358
return 0 ;
1287
1359
}
@@ -1328,7 +1400,9 @@ int BPF_KPROBE(ip_output_fn, struct net *net, struct sock *sk,
1328
1400
if (sk ) {
1329
1401
// Use the existing process_tcp function which already works in other
1330
1402
// kprobes
1331
- process_tcp (sk , & key , pid );
1403
+ if (process_tcp (sk , & key , pid ) != 0 ) {
1404
+ return 0 ; // Skip invalid socket
1405
+ }
1332
1406
update_val (& key , len );
1333
1407
return 0 ;
1334
1408
}
0 commit comments