@@ -167,6 +167,11 @@ static inline int process_ip4(struct iphdr *ip4, void *data_end, statkey *key) {
167167 return NOK ;
168168 }
169169
170+ // Skip packets with both source and destination addresses zero
171+ if (ip4 -> saddr == 0 && ip4 -> daddr == 0 ) {
172+ return NOK ;
173+ }
174+
170175 // convert to V4MAPPED address
171176 __builtin_memcpy (key -> srcip .s6_addr , ip4in6 , sizeof (ip4in6 ));
172177 __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) {
223228 }
224229 }
225230
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+
226237 return OK ;
227238}
228239
@@ -249,6 +260,16 @@ static inline int process_ip6(struct ipv6hdr *ip6, void *data_end,
249260 key -> dstip = ip6 -> daddr ;
250261 key -> proto = ip6 -> nexthdr ;
251262
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+
252273 switch (ip6 -> nexthdr ) {
253274 case IPPROTO_TCP : {
254275 struct tcphdr * tcp = (void * )ip6 + sizeof (* ip6 );
@@ -293,6 +314,11 @@ static inline int process_ip6(struct ipv6hdr *ip6, void *data_end,
293314 }
294315 }
295316
317+ // Skip packets with destination IPv6 unspecified and destination port 0
318+ if (dst_empty && key -> dst_port == 0 ) {
319+ return NOK ;
320+ }
321+
296322 return OK ;
297323}
298324
@@ -584,18 +610,43 @@ int cgroup_skb_egress(struct __sk_buff *skb) {
584610 *
585611 * @throws none
586612 */
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+
588619 __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+ }
589625
590626 switch (family ) {
591627 case AF_INET : {
592628 // convert to V4MAPPED address
593629 __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+
594647 key -> srcip .s6_addr16 [5 ] = bpf_htons (0xffff );
595648 __builtin_memcpy (& key -> srcip .s6_addr32 [3 ], & ip4_src , sizeof (ip4_src ));
596649
597- // convert to V4MAPPED address
598- __be32 ip4_dst = BPF_CORE_READ (sk , __sk_common .skc_daddr );
599650 key -> dstip .s6_addr16 [5 ] = bpf_htons (0xffff );
600651 __builtin_memcpy (& key -> dstip .s6_addr32 [3 ], & ip4_dst , sizeof (ip4_dst ));
601652
@@ -605,23 +656,38 @@ static inline void process_tcp(struct sock *sk, statkey *key, pid_t pid) {
605656 BPF_CORE_READ_INTO (& key -> srcip , sk , __sk_common .skc_v6_rcv_saddr );
606657 BPF_CORE_READ_INTO (& key -> dstip , sk , __sk_common .skc_v6_daddr );
607658
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+
608669 break ;
609670 }
610671 default : {
611- return ;
672+ return -1 ;
612673 }
613674 }
614675
615676 __u16 sport = BPF_CORE_READ (sk , __sk_common .skc_num );
677+ __u16 dport = BPF_CORE_READ (sk , __sk_common .skc_dport );
678+
616679 if (sport == 0 ) {
617680 struct inet_sock * isk = (struct inet_sock * )sk ;
618681 BPF_CORE_READ_INTO (& sport , isk , inet_sport );
619682 }
683+
620684 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 );
622686
623687 key -> proto = IPPROTO_TCP ;
624688 key -> pid = pid ;
689+
690+ return 0 ;
625691}
626692
627693/**
@@ -948,7 +1014,9 @@ int BPF_KPROBE(tcp_sendmsg, struct sock *sk, struct msghdr *msg, size_t size) {
9481014 bpf_get_current_comm (& key .comm , sizeof (key .comm ));
9491015 }
9501016
951- process_tcp (sk , & key , pid );
1017+ if (process_tcp (sk , & key , pid ) != 0 ) {
1018+ return 0 ; // Skip invalid socket
1019+ }
9521020 update_val (& key , size );
9531021
9541022 return 0 ;
@@ -982,7 +1050,9 @@ int BPF_KPROBE(tcp_cleanup_rbuf, struct sock *sk, int copied) {
9821050 bpf_get_current_comm (& key .comm , sizeof (key .comm ));
9831051 }
9841052
985- process_tcp (sk , & key , pid );
1053+ if (process_tcp (sk , & key , pid ) != 0 ) {
1054+ return 0 ; // Skip invalid socket
1055+ }
9861056 update_val (& key , copied );
9871057
9881058 return 0 ;
@@ -1281,7 +1351,9 @@ int BPF_KPROBE(ip_local_out_fn, struct sk_buff *skb, struct net *net) {
12811351 if (sk ) {
12821352 // Let's use the safer process_tcp function which already works in existing
12831353 // kprobes
1284- process_tcp (sk , & key , pid );
1354+ if (process_tcp (sk , & key , pid ) != 0 ) {
1355+ return 0 ; // Skip invalid socket
1356+ }
12851357 update_val (& key , len );
12861358 return 0 ;
12871359 }
@@ -1328,7 +1400,9 @@ int BPF_KPROBE(ip_output_fn, struct net *net, struct sock *sk,
13281400 if (sk ) {
13291401 // Use the existing process_tcp function which already works in other
13301402 // kprobes
1331- process_tcp (sk , & key , pid );
1403+ if (process_tcp (sk , & key , pid ) != 0 ) {
1404+ return 0 ; // Skip invalid socket
1405+ }
13321406 update_val (& key , len );
13331407 return 0 ;
13341408 }
0 commit comments