VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45932

CVE-2026-45932

Description

In the Linux kernel, the following vulnerability has been resolved:

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

This commit fixes a security issue where BPF_PROG_DETACH on tcx or netkit devices could be executed by any user when no program fd was provided, bypassing permission checks. The fix adds a capability check for CAP_NET_ADMIN or CAP_SYS_ADMIN in this case.

Affected products

1

Patches

6
3f04cc1e5374

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitGuillaume GonnetJan 27, 2026Fixed in 6.19.4via kernel-cna
3 files changed · +17 6
  • include/linux/bpf.h+5 0 modified
    diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    index e5be698256d15a..7b2e51216e736a 100644
    --- a/include/linux/bpf.h
    +++ b/include/linux/bpf.h
    @@ -3243,6 +3243,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
     }
     #endif /* CONFIG_BPF_SYSCALL */
     
    +static inline bool bpf_net_capable(void)
    +{
    +	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    +}
    +
     static __always_inline int
     bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
     {
    
  • include/linux/bpf_mprog.h+10 0 modified
    diff --git a/include/linux/bpf_mprog.h b/include/linux/bpf_mprog.h
    index 929225f7b09594..0b9f4caeeb0a32 100644
    --- a/include/linux/bpf_mprog.h
    +++ b/include/linux/bpf_mprog.h
    @@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
     		return false;
     	}
     }
    +
    +static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
    +{
    +	switch (type) {
    +	case BPF_PROG_TYPE_SCHED_CLS:
    +		return bpf_net_capable();
    +	default:
    +		return false;
    +	}
    +}
     #endif /* __BPF_MPROG_H */
    
  • kernel/bpf/syscall.c+2 6 modified
    diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
    index ee116a3b7baf7d..763868d327b4a7 100644
    --- a/kernel/bpf/syscall.c
    +++ b/kernel/bpf/syscall.c
    @@ -1366,11 +1366,6 @@ free_map_tab:
     	return ret;
     }
     
    -static bool bpf_net_capable(void)
    -{
    -	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    -}
    -
     #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
     /* called via syscall */
     static int map_create(union bpf_attr *attr, bpfptr_t uattr)
    @@ -4565,6 +4560,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
     			prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
     			if (IS_ERR(prog))
     				return PTR_ERR(prog);
    +		} else if (!bpf_mprog_detach_empty(ptype)) {
    +			return -EPERM;
     		}
     	} else if (is_cgroup_prog_type(ptype, 0, false)) {
     		if (attr->attach_flags || attr->relative_fd)
    -- 
    cgit 1.3-korg
    
    
    
4e0772cded10

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitGuillaume GonnetJan 27, 2026Fixed in 6.18.14via kernel-cna
3 files changed · +17 6
  • include/linux/bpf.h+5 0 modified
    diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    index d808253f2e945d..e2dd3a6d495afd 100644
    --- a/include/linux/bpf.h
    +++ b/include/linux/bpf.h
    @@ -3200,6 +3200,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
     }
     #endif /* CONFIG_BPF_SYSCALL */
     
    +static inline bool bpf_net_capable(void)
    +{
    +	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    +}
    +
     static __always_inline int
     bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
     {
    
  • include/linux/bpf_mprog.h+10 0 modified
    diff --git a/include/linux/bpf_mprog.h b/include/linux/bpf_mprog.h
    index 929225f7b09594..0b9f4caeeb0a32 100644
    --- a/include/linux/bpf_mprog.h
    +++ b/include/linux/bpf_mprog.h
    @@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
     		return false;
     	}
     }
    +
    +static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
    +{
    +	switch (type) {
    +	case BPF_PROG_TYPE_SCHED_CLS:
    +		return bpf_net_capable();
    +	default:
    +		return false;
    +	}
    +}
     #endif /* __BPF_MPROG_H */
    
  • kernel/bpf/syscall.c+2 6 modified
    diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
    index e9cf69594824c2..f39367765f0c4f 100644
    --- a/kernel/bpf/syscall.c
    +++ b/kernel/bpf/syscall.c
    @@ -1365,11 +1365,6 @@ free_map_tab:
     	return ret;
     }
     
    -static bool bpf_net_capable(void)
    -{
    -	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    -}
    -
     #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
     /* called via syscall */
     static int map_create(union bpf_attr *attr, bpfptr_t uattr)
    @@ -4554,6 +4549,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
     			prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
     			if (IS_ERR(prog))
     				return PTR_ERR(prog);
    +		} else if (!bpf_mprog_detach_empty(ptype)) {
    +			return -EPERM;
     		}
     	} else if (is_cgroup_prog_type(ptype, 0, false)) {
     		if (attr->attach_flags || attr->relative_fd)
    -- 
    cgit 1.3-korg
    
    
    
ae23bc81ddf7

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitGuillaume GonnetJan 27, 2026Fixed in 7.0via kernel-cna
3 files changed · +17 6
  • include/linux/bpf.h+5 0 modified
    diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    index 4427c6e9833196..9272a237cced25 100644
    --- a/include/linux/bpf.h
    +++ b/include/linux/bpf.h
    @@ -3362,6 +3362,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
     }
     #endif /* CONFIG_BPF_SYSCALL */
     
    +static inline bool bpf_net_capable(void)
    +{
    +	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    +}
    +
     static __always_inline int
     bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
     {
    
  • include/linux/bpf_mprog.h+10 0 modified
    diff --git a/include/linux/bpf_mprog.h b/include/linux/bpf_mprog.h
    index 929225f7b09594..0b9f4caeeb0a32 100644
    --- a/include/linux/bpf_mprog.h
    +++ b/include/linux/bpf_mprog.h
    @@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
     		return false;
     	}
     }
    +
    +static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
    +{
    +	switch (type) {
    +	case BPF_PROG_TYPE_SCHED_CLS:
    +		return bpf_net_capable();
    +	default:
    +		return false;
    +	}
    +}
     #endif /* __BPF_MPROG_H */
    
  • kernel/bpf/syscall.c+2 6 modified
    diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
    index b9184545c3fd09..5f59dd47a5b1c3 100644
    --- a/kernel/bpf/syscall.c
    +++ b/kernel/bpf/syscall.c
    @@ -1363,11 +1363,6 @@ free_map_tab:
     	return ret;
     }
     
    -static bool bpf_net_capable(void)
    -{
    -	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    -}
    -
     #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
     /* called via syscall */
     static int map_create(union bpf_attr *attr, bpfptr_t uattr)
    @@ -4579,6 +4574,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
     			prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
     			if (IS_ERR(prog))
     				return PTR_ERR(prog);
    +		} else if (!bpf_mprog_detach_empty(ptype)) {
    +			return -EPERM;
     		}
     	} else if (is_cgroup_prog_type(ptype, 0, false)) {
     		if (attr->attach_flags || attr->relative_fd)
    -- 
    cgit 1.3-korg
    
    
    
3f04cc1e5374

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

3 files changed · +17 6
  • include/linux/bpf.h+5 0 modified
    diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    index e5be698256d15a..7b2e51216e736a 100644
    --- a/include/linux/bpf.h
    +++ b/include/linux/bpf.h
    @@ -3243,6 +3243,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
     }
     #endif /* CONFIG_BPF_SYSCALL */
     
    +static inline bool bpf_net_capable(void)
    +{
    +	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    +}
    +
     static __always_inline int
     bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
     {
    
  • include/linux/bpf_mprog.h+10 0 modified
    diff --git a/include/linux/bpf_mprog.h b/include/linux/bpf_mprog.h
    index 929225f7b09594..0b9f4caeeb0a32 100644
    --- a/include/linux/bpf_mprog.h
    +++ b/include/linux/bpf_mprog.h
    @@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
     		return false;
     	}
     }
    +
    +static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
    +{
    +	switch (type) {
    +	case BPF_PROG_TYPE_SCHED_CLS:
    +		return bpf_net_capable();
    +	default:
    +		return false;
    +	}
    +}
     #endif /* __BPF_MPROG_H */
    
  • kernel/bpf/syscall.c+2 6 modified
    diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
    index ee116a3b7baf7d..763868d327b4a7 100644
    --- a/kernel/bpf/syscall.c
    +++ b/kernel/bpf/syscall.c
    @@ -1366,11 +1366,6 @@ free_map_tab:
     	return ret;
     }
     
    -static bool bpf_net_capable(void)
    -{
    -	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    -}
    -
     #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
     /* called via syscall */
     static int map_create(union bpf_attr *attr, bpfptr_t uattr)
    @@ -4565,6 +4560,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
     			prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
     			if (IS_ERR(prog))
     				return PTR_ERR(prog);
    +		} else if (!bpf_mprog_detach_empty(ptype)) {
    +			return -EPERM;
     		}
     	} else if (is_cgroup_prog_type(ptype, 0, false)) {
     		if (attr->attach_flags || attr->relative_fd)
    -- 
    cgit 1.3-korg
    
    
    
ae23bc81ddf7

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

3 files changed · +17 6
  • include/linux/bpf.h+5 0 modified
    diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    index 4427c6e9833196..9272a237cced25 100644
    --- a/include/linux/bpf.h
    +++ b/include/linux/bpf.h
    @@ -3362,6 +3362,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
     }
     #endif /* CONFIG_BPF_SYSCALL */
     
    +static inline bool bpf_net_capable(void)
    +{
    +	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    +}
    +
     static __always_inline int
     bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
     {
    
  • include/linux/bpf_mprog.h+10 0 modified
    diff --git a/include/linux/bpf_mprog.h b/include/linux/bpf_mprog.h
    index 929225f7b09594..0b9f4caeeb0a32 100644
    --- a/include/linux/bpf_mprog.h
    +++ b/include/linux/bpf_mprog.h
    @@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
     		return false;
     	}
     }
    +
    +static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
    +{
    +	switch (type) {
    +	case BPF_PROG_TYPE_SCHED_CLS:
    +		return bpf_net_capable();
    +	default:
    +		return false;
    +	}
    +}
     #endif /* __BPF_MPROG_H */
    
  • kernel/bpf/syscall.c+2 6 modified
    diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
    index b9184545c3fd09..5f59dd47a5b1c3 100644
    --- a/kernel/bpf/syscall.c
    +++ b/kernel/bpf/syscall.c
    @@ -1363,11 +1363,6 @@ free_map_tab:
     	return ret;
     }
     
    -static bool bpf_net_capable(void)
    -{
    -	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    -}
    -
     #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
     /* called via syscall */
     static int map_create(union bpf_attr *attr, bpfptr_t uattr)
    @@ -4579,6 +4574,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
     			prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
     			if (IS_ERR(prog))
     				return PTR_ERR(prog);
    +		} else if (!bpf_mprog_detach_empty(ptype)) {
    +			return -EPERM;
     		}
     	} else if (is_cgroup_prog_type(ptype, 0, false)) {
     		if (attr->attach_flags || attr->relative_fd)
    -- 
    cgit 1.3-korg
    
    
    
4e0772cded10

bpf: Fix tcx/netkit detach permissions when prog fd isn't given

3 files changed · +17 6
  • include/linux/bpf.h+5 0 modified
    diff --git a/include/linux/bpf.h b/include/linux/bpf.h
    index d808253f2e945d..e2dd3a6d495afd 100644
    --- a/include/linux/bpf.h
    +++ b/include/linux/bpf.h
    @@ -3200,6 +3200,11 @@ static inline void bpf_prog_report_arena_violation(bool write, unsigned long add
     }
     #endif /* CONFIG_BPF_SYSCALL */
     
    +static inline bool bpf_net_capable(void)
    +{
    +	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    +}
    +
     static __always_inline int
     bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
     {
    
  • include/linux/bpf_mprog.h+10 0 modified
    diff --git a/include/linux/bpf_mprog.h b/include/linux/bpf_mprog.h
    index 929225f7b09594..0b9f4caeeb0a32 100644
    --- a/include/linux/bpf_mprog.h
    +++ b/include/linux/bpf_mprog.h
    @@ -340,4 +340,14 @@ static inline bool bpf_mprog_supported(enum bpf_prog_type type)
     		return false;
     	}
     }
    +
    +static inline bool bpf_mprog_detach_empty(enum bpf_prog_type type)
    +{
    +	switch (type) {
    +	case BPF_PROG_TYPE_SCHED_CLS:
    +		return bpf_net_capable();
    +	default:
    +		return false;
    +	}
    +}
     #endif /* __BPF_MPROG_H */
    
  • kernel/bpf/syscall.c+2 6 modified
    diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
    index e9cf69594824c2..f39367765f0c4f 100644
    --- a/kernel/bpf/syscall.c
    +++ b/kernel/bpf/syscall.c
    @@ -1365,11 +1365,6 @@ free_map_tab:
     	return ret;
     }
     
    -static bool bpf_net_capable(void)
    -{
    -	return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN);
    -}
    -
     #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
     /* called via syscall */
     static int map_create(union bpf_attr *attr, bpfptr_t uattr)
    @@ -4554,6 +4549,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
     			prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
     			if (IS_ERR(prog))
     				return PTR_ERR(prog);
    +		} else if (!bpf_mprog_detach_empty(ptype)) {
    +			return -EPERM;
     		}
     	} else if (is_cgroup_prog_type(ptype, 0, false)) {
     		if (attr->attach_flags || attr->relative_fd)
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing permission check in BPF_PROG_DETACH for tcx/netkit when no program file descriptor is provided."

Attack vector

An unprivileged local user can invoke the BPF_PROG_DETACH operation on a tcx or netkit device without providing a program file descriptor (attr->attach_bpf_fd == 0). In the original code, when no fd was given, the kernel skipped the bpf_prog_get_type() call (which performs permission checks via the file descriptor) and proceeded directly to detachment without any capability check. This allowed any local user to detach BPF programs from tcx/netkit interfaces, bypassing the intended CAP_NET_ADMIN or CAP_SYS_ADMIN requirement [patch_id=2661231].

Affected code

The vulnerable code path is in kernel/bpf/syscall.c within the bpf_prog_detach() function. When attr->attach_bpf_fd is 0 (no program fd provided) and the program type is BPF_PROG_TYPE_SCHED_CLS (tcx/netkit), the original code performed no permission check before detaching. The fix adds a call to bpf_mprog_detach_empty() defined in include/linux/bpf_mprog.h, which invokes bpf_net_capable() (moved to include/linux/bpf.h) to enforce capability checks [patch_id=2661231].

What the fix does

The patch adds a new helper function bpf_mprog_detach_empty() in include/linux/bpf_mprog.h that returns bpf_net_capable() (which checks for CAP_NET_ADMIN or CAP_SYS_ADMIN) when the program type is BPF_PROG_TYPE_SCHED_CLS (used by tcx/netkit). In kernel/bpf/syscall.c, the bpf_prog_detach() function now calls this helper when no program fd is provided; if the check fails, it returns -EPERM. The bpf_net_capable() function was also moved from being a local static in syscall.c to an inline function in include/linux/bpf.h so it can be reused by the new mprog helper [patch_id=2661231][patch_id=2661228].

Preconditions

  • inputThe attacker must have local access to the system and be able to invoke the BPF_PROG_DETACH syscall.
  • configA tcx or netkit device must have at least one BPF program attached.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.