How an unvetted socket creation flags validation bug in security/apparmor/net.c allowed sandboxed snap processes to create arbitrary raw network sockets.
Imagine a prison guard who checks everyone entering the gate. He has a list that says 'Visitors can only bring paper, not knives or keys'. But a sneaky visitor passes a key hidden inside a box with a special label 'Special Fragile'. The guard only checks standard boxes, ignores the special label, and lets the prisoner receive a master key.
A confined application runs under a restrictive AppArmor profile forbidding raw network sockets.
The process calls socket(AF_INET, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_RAW).
AppArmor's check compared raw integer values instead of masking out ancillary flags, skipping the denial.
The restricted app sends spoofed raw packets and sniffs local traffic across the host.
采用清晰易读的高级编程语言展示(不含晦涩汇编或二进制机器码)。
// VULNERABLE: security/apparmor/net.c before patch
int aa_profile_af_perm(struct aa_profile *profile, int family, int type, int protocol) {
// ROOT CAUSE:
// 'type' contains socket creation flags (e.g., SOCK_CLOEXEC, SOCK_NONBLOCK)!
// Direct lookup fails because the policy table only defines base types (SOCK_RAW = 3)!
// If type = (SOCK_RAW | SOCK_CLOEXEC) = 0x80003, rule lookup miss defaults to ALLOW!
return aa_lookup_net(profile, family, type, protocol);
}
// SECURE: security/apparmor/net.c patch
int aa_profile_af_perm(struct aa_profile *profile, int family, int type, int protocol) {
// 1. Mask out socket creation flags to extract purely the fundamental socket type
int base_type = type & SOCK_TYPE_MASK;
// 2. Perform policy mediation lookup using sanitized base type
return aa_lookup_net(profile, family, base_type, protocol);
}