]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: change sk_filter_trim_cap() to return a drop_reason by value
authorEric Dumazet <edumazet@google.com>
Thu, 9 Apr 2026 14:56:24 +0000 (14:56 +0000)
committerJakub Kicinski <kuba@kernel.org>
Sun, 12 Apr 2026 21:30:25 +0000 (14:30 -0700)
Current return value can be replaced with the drop_reason,
reducing kernel bloat:

$ scripts/bloat-o-meter -t vmlinux.old vmlinux.new
add/remove: 0/2 grow/shrink: 1/11 up/down: 32/-603 (-571)
Function                                     old     new   delta
tcp_v6_rcv                                  3135    3167     +32
unix_dgram_sendmsg                          1731    1726      -5
netlink_unicast                              957     945     -12
netlink_dump                                1372    1359     -13
sk_filter_trim_cap                           882     858     -24
tcp_v4_rcv                                  3143    3111     -32
__pfx_tcp_filter                              32       -     -32
netlink_broadcast_filtered                  1633    1595     -38
sock_queue_rcv_skb_reason                    126      76     -50
tun_net_xmit                                1127    1074     -53
__sk_receive_skb                             690     632     -58
udpv6_queue_rcv_one_skb                      935     869     -66
udp_queue_rcv_one_skb                        919     853     -66
tcp_filter                                   154       -    -154
Total: Before=29722783, After=29722212, chg -0.00%

Signed-off-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260409145625.2306224-6-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/linux/filter.h
include/net/tcp.h
net/core/filter.c
net/core/sock.c
net/ipv4/udp.c
net/ipv6/udp.c
net/rose/rose_in.c

index 59931e5810b4fcff5788616a3875767421dba3bc..5ac08aa70123cf97ab91dea7e11e47b210a42d4a 100644 (file)
@@ -1092,23 +1092,21 @@ bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
        return set_memory_rox((unsigned long)hdr, hdr->size >> PAGE_SHIFT);
 }
 
-int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap,
-                      enum skb_drop_reason *reason);
+enum skb_drop_reason
+sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
 
 static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
 {
-       enum skb_drop_reason ignore_reason;
+       enum skb_drop_reason drop_reason;
 
-       return sk_filter_trim_cap(sk, skb, 1, &ignore_reason);
+       drop_reason = sk_filter_trim_cap(sk, skb, 1);
+       return drop_reason ? -EPERM : 0;
 }
 
 static inline enum skb_drop_reason
 sk_filter_reason(struct sock *sk, struct sk_buff *skb)
 {
-       enum skb_drop_reason drop_reason;
-
-       sk_filter_trim_cap(sk, skb, 1, &drop_reason);
-       return drop_reason;
+       return sk_filter_trim_cap(sk, skb, 1);
 }
 
 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err);
index 098e52269a04cb8938812a8f43caf11f9d5c68a3..49f45bcff917942e993c627dd3d0017369186f67 100644 (file)
@@ -1687,10 +1687,8 @@ static inline enum skb_drop_reason
 tcp_filter(struct sock *sk, struct sk_buff *skb)
 {
        const struct tcphdr *th = (const struct tcphdr *)skb->data;
-       enum skb_drop_reason reason;
 
-       sk_filter_trim_cap(sk, skb, __tcp_hdrlen(th), &reason);
-       return reason;
+       return sk_filter_trim_cap(sk, skb, __tcp_hdrlen(th));
 }
 
 void tcp_set_state(struct sock *sk, int state);
index 5569d83b8be06dc1fe64ddff2ae338acd1622ed7..bf9c37b27646943e3a6fdad2fadf00f5e1ea8244 100644 (file)
@@ -121,20 +121,20 @@ EXPORT_SYMBOL_GPL(copy_bpf_fprog_from_user);
  *     @sk: sock associated with &sk_buff
  *     @skb: buffer to filter
  *     @cap: limit on how short the eBPF program may trim the packet
- *     @reason: record drop reason
  *
  * Run the eBPF program and then cut skb->data to correct size returned by
  * the program. If pkt_len is 0 we toss packet. If skb->len is smaller
  * than pkt_len we keep whole skb->data. This is the socket level
  * wrapper to bpf_prog_run. It returns 0 if the packet should
- * be accepted or -EPERM if the packet should be tossed.
+ * be accepted or a drop_reason if the packet should be tossed.
  *
  */
-int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
-                      unsigned int cap, enum skb_drop_reason *reason)
+enum skb_drop_reason
+sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap)
 {
-       int err;
+       enum skb_drop_reason drop_reason;
        struct sk_filter *filter;
+       int err;
 
        /*
         * If the skb was allocated from pfmemalloc reserves, only
@@ -143,21 +143,17 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
         */
        if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC)) {
                NET_INC_STATS(sock_net(sk), LINUX_MIB_PFMEMALLOCDROP);
-               *reason = SKB_DROP_REASON_PFMEMALLOC;
-               return -ENOMEM;
+               return SKB_DROP_REASON_PFMEMALLOC;
        }
        err = BPF_CGROUP_RUN_PROG_INET_INGRESS(sk, skb);
-       if (err) {
-               *reason = SKB_DROP_REASON_SOCKET_FILTER;
-               return err;
-       }
+       if (err)
+               return SKB_DROP_REASON_SOCKET_FILTER;
 
        err = security_sock_rcv_skb(sk, skb);
-       if (err) {
-               *reason = SKB_DROP_REASON_SECURITY_HOOK;
-               return err;
-       }
+       if (err)
+               return SKB_DROP_REASON_SECURITY_HOOK;
 
+       drop_reason = 0;
        rcu_read_lock();
        filter = rcu_dereference(sk->sk_filter);
        if (filter) {
@@ -168,11 +164,12 @@ int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb,
                pkt_len = bpf_prog_run_save_cb(filter->prog, skb);
                skb->sk = save_sk;
                err = pkt_len ? pskb_trim(skb, max(cap, pkt_len)) : -EPERM;
+               if (err)
+                       drop_reason = SKB_DROP_REASON_SOCKET_FILTER;
        }
        rcu_read_unlock();
 
-       *reason = err ? SKB_DROP_REASON_SOCKET_FILTER : 0;
-       return err;
+       return drop_reason;
 }
 EXPORT_SYMBOL(sk_filter_trim_cap);
 
index 1ffcb15d0fc5e39201aab24616d40a37aa41c823..367fd7bad4ac2e6557dc73519ac0c04debb43cb3 100644 (file)
@@ -544,11 +544,12 @@ EXPORT_SYMBOL(sock_queue_rcv_skb_reason);
 int __sk_receive_skb(struct sock *sk, struct sk_buff *skb,
                     const int nested, unsigned int trim_cap, bool refcounted)
 {
-       enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
+       enum skb_drop_reason reason;
        int rc = NET_RX_SUCCESS;
        int err;
 
-       if (sk_filter_trim_cap(sk, skb, trim_cap, &reason))
+       reason = sk_filter_trim_cap(sk, skb, trim_cap);
+       if (reason)
                goto discard_and_relse;
 
        skb->dev = NULL;
index ab415de32443c5d32eedca5f093d5d96681f6b48..2fddc7b6b7172045286a8a0902f8bcf41aaca7c4 100644 (file)
@@ -2392,7 +2392,8 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
            udp_lib_checksum_complete(skb))
                        goto csum_error;
 
-       if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr), &drop_reason))
+       drop_reason = sk_filter_trim_cap(sk, skb, sizeof(struct udphdr));
+       if (drop_reason)
                goto drop;
 
        udp_csum_pull_header(skb);
index d7cf4c9508b2c5c92753eddf8de1717f52347fbf..3fac9cb47ae00fe26c60ba2aee61748b4a241221 100644 (file)
@@ -853,7 +853,8 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
            udp_lib_checksum_complete(skb))
                goto csum_error;
 
-       if (sk_filter_trim_cap(sk, skb, sizeof(struct udphdr), &drop_reason))
+       drop_reason = sk_filter_trim_cap(sk, skb, sizeof(struct udphdr));
+       if (drop_reason)
                goto drop;
 
        udp_csum_pull_header(skb);
index 0276b393f0e530ea2d8f689a3dd95364849910ac..3aff3c2d45a956a5c791beb5c2d5c4e4d7063d6a 100644 (file)
@@ -101,7 +101,6 @@ static int rose_state2_machine(struct sock *sk, struct sk_buff *skb, int framety
  */
 static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int frametype, int ns, int nr, int q, int d, int m)
 {
-       enum skb_drop_reason dr; /* ignored */
        struct rose_sock *rose = rose_sk(sk);
        int queued = 0;
 
@@ -163,7 +162,7 @@ static int rose_state3_machine(struct sock *sk, struct sk_buff *skb, int framety
                rose_frames_acked(sk, nr);
                if (ns == rose->vr) {
                        rose_start_idletimer(sk);
-                       if (!sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN, &dr) &&
+                       if (!sk_filter_trim_cap(sk, skb, ROSE_MIN_LEN) &&
                            __sock_queue_rcv_skb(sk, skb) == 0) {
                                rose->vr = (rose->vr + 1) % ROSE_MODULUS;
                                queued = 1;