
BPF-LSM CVE-2026-31431 (कॉपी फेल) के लिए शमन — पूरे क्लस्टर में AF_ALG सॉकेट निर्माण को अस्वीकार करता है
CVE-2026-31431 ("कॉपी फेल") और RxRPC वैरिएंट Dirty Frag के लिए BPF-LSM शमन, तथा समान विशेषाधिकार-वृद्धि भेद्यताओं के लिए जो AF_ALG या AF_RXRPC सॉकेट परिवारों के माध्यम से पहुंच योग्य कर्नेल-साइड इन-प्लेस क्रिप्टो पथ में यूज़रस्पेस एक्सेस पर निर्भर करती हैं।
एक छोटा DaemonSet हर नोड पर socket_create हुक के लिए एक एकल BPF-LSM प्रोग्राम संलग्न करता है। प्रोग्राम किसी भी यूज़रस्पेस socket(AF_ALG, ...) या socket(AF_RXRPC, ...) कॉल के लिए -EPERM लौटाता है, चाहे प्रक्रिया क्षमताएं, नेमस्पेस, या seccomp प्रोफ़ाइल कुछ भी हों। कर्नेल-आंतरिक sock_create_kern() कॉलर्स (जैसे fs/afs, IPsec स्टैक) को अनुमति दी जाती है, इसलिए वैध इन-कर्नेल उपयोगकर्ता काम करते रहते हैं।
Talos Linux पर परीक्षण किया गया (जो v1.10 से CONFIG_BPF_LSM=y और डिफ़ॉल्ट LSM स्टैक में bpf के साथ आता है), समान कर्नेल कॉन्फ़िगरेशन वाले किसी भी डिस्ट्रीब्यूशन पर काम करता है।
कॉपी फेल (CVE-2026-31431) algif_aead में एक तर्क दोष है जो एक अनविशेषाधिकृत स्थानीय उपयोगकर्ता को किसी भी setuid बाइनरी में 4-बाइट पेज-कैश राइट करने की अनुमति देता है, जिससे 732-बाइट Python स्क्रिप्ट से root प्राप्त होता है। एक्सप्लॉइट को AF_ALG + splice() के अलावा कुछ नहीं चाहिए, जो दोनों डिफ़ॉल्ट रूप से किसी भी अनविशेषाधिकृत प्रक्रिया से पहुंच योग्य हैं। मेनलाइन फिक्स a664bf3d603d है।
Dirty Frag मई 2026 में उसी शोध श्रृंखला द्वारा खुलासा की गई एक अनुवर्ती भेद्यता श्रेणी है। यह दो बगों को जोड़ती है जो sk_buff के frag सदस्य को "गंदा" करते हैं — xfrm-ESP Page-Cache Write और RxRPC Page-Cache Write। RxRPC वैरिएंट rxkad_verify_packet_1() के अंदर splice()-पिन किए गए पेज-कैश पेज पर इन-प्लेस pcbc(fcrypt) डिक्रिप्ट करता है और यूज़र नेमस्पेस निर्माण की आवश्यकता के बिना root तक पहुंचता है, जो इसे कठोर डिस्ट्रीब्यूशन पर श्रृंखला का अधिक सार्वभौमिक रूप से शोषण योग्य आधा बनाता है। xfrm-ESP फिक्स netdev में f4c50a4034e6 (2026-05-07) के रूप में आया; लेखन के समय डिस्ट्रो अभी भी बैकपोर्ट कर रहे हैं, और RxRPC के लिए अभी तक कोई सार्वजनिक फिक्स नहीं है — खुलासा समयरेखा के लिए अपस्ट्रीम राइट-अप देखें।
दोनों एक्सप्लॉइट प्रभावित परिवार में सॉकेट खोलने पर निर्भर करते हैं। जब तक कर्नेल फिक्स आपके डिस्ट्रीब्यूशन में नहीं आते, यूज़रस्पेस को कभी भी AF_ALG या AF_RXRPC सॉकेट बनाने से रोककर हमले की सतह को हटाया जा सकता है। विकल्पों की तुलना में:
यह प्रोजेक्ट नो-रीबूट विकल्प है। इसे क्लस्टर-व्यापी चलाएं, फिर अपनी सामान्य पैच कैडेंस पर स्थायी कर्नेल फिक्स की योजना बनाएं।
Dirty Frag के ESP वैरिएंट पर नोट। Dirty Frag का
xfrm-ESP Page-Cache Writeआधा इस DaemonSet द्वारा बंद नहीं किया गया है — यह एक समर्पित सॉकेट परिवार के माध्यम से नहीं, बल्कि XFRM netlink +UDP_ENCAP_ESPINUDPके माध्यम से ट्रिगर होता है, और इसके लिए एक स्वच्छ BPF-LSM फ़िल्टर या तो होस्ट पर वैध IPsec को तोड़ देगा या यूज़र-नेमस्पेस-जागरूक तर्क की आवश्यकता होगी। यहां वर्तमान में ट्रैक नहीं किया गया — योगदान स्वागत योग्य हैं। कठोर डिस्ट्रीब्यूशन पर जो अनविशेषाधिकृत यूज़र नेमस्पेस को ब्लॉक करते हैं (जैसे Ubuntu की डिफ़ॉल्ट AppArmor नीति), ESP वैरिएंट पहले स्थान पर अप्राप्य है और यहां RxRPC ब्लॉक पर्याप्त है।
bpf/blocker.c एक छोटा BPF-LSM प्रोग्राम है:
SEC("lsm/socket_create")
int BPF_PROG(block_socket_family, int family, int type, int protocol,
int kern, int ret)
{
if (ret)
return ret;
/* kern != 0 means sock_create_kern() — let in-kernel callers through. */
if (!kern && (family == AF_ALG || family == AF_RXRPC)) // 38, 33
return -EPERM;
return 0;
}
Go लोडर (main.go, ~40 लाइनें) प्रोग्राम लोड करता है और इसे bpf(BPF_LINK_CREATE) के माध्यम से संलग्न करता है। लिंक पॉड के जीवनकाल के लिए रखा जाता है। SIGTERM पर, लिंक बंद हो जाता है और हुक अलग हो जाता है।
CONFIG_BPF_LSM=y और सक्रिय LSM स्टैक में bpf (कर्नेल कमांड लाइन पर lsm=...,bpf) के साथ निर्मित कर्नेल की आवश्यकता होती है। Talos Linux v1.10 से डिफ़ॉल्ट रूप से दोनों सक्षम करके आता है।
kubectl apply -f https://raw.githubusercontent.com/cozystack/copy-fail-blocker/v0.3.0/manifests/copy-fail-blocker.yaml
main पर नवीनतम कमिट के लिए (अप्रकाशित परिवर्तन शामिल हो सकते हैं):
kubectl apply -f https://raw.githubusercontent.com/cozystack/copy-fail-blocker/main/manifests/copy-fail-blocker.yaml
चार्ट OCI आर्टिफैक्ट के रूप में प्रकाशित नहीं है (रजिस्ट्री पथ कंटेनर इमेज के साथ साझा किया गया है)। टैग किए गए चेकआउट से इंस्टॉल करें:
git clone --branch v0.3.0 https://github.com/cozystack/copy-fail-blocker
cd copy-fail-blocker
helm upgrade --install copy-fail-blocker charts/copy-fail-blocker \
--namespace kube-system
या Makefile शॉर्टकट के माध्यम से:
make apply # helm upgrade --install into kube-system
make diff # preview changes against the cluster
make delete # uninstall
make manifest # regenerate manifests/copy-fail-blocker.yaml
DaemonSet को विशेषाधिकार प्राप्त चलना चाहिए (यह BPF प्रोग्राम लोड करता है और bpffs में लिखता है)। इसे विशेषाधिकार प्राप्त Pod Security Standard वाले नेमस्पेस में रखें, या kube-system में, जो डिफ़ॉल्ट रूप से विशेषाधिकार प्राप्त है।
कवर किए गए नोड पर किसी भी पॉड से:
python3 -c '
import errno, socket
# Pass each family with a type the family-specific create() actually
# supports (AF_ALG → SOCK_SEQPACKET, AF_RXRPC → SOCK_DGRAM) so that on
# a node WITHOUT this hook the call would either succeed (FAIL: socket
# created) or fail with a non-EPERM errno — both surface as FAIL below.
# With the hook active, security_socket_create() returns -EPERM before
# pf->create() runs, so the type does not matter; we still pass the
# correct one to keep the FAIL diagnostic unambiguous.
for name, family, stype in [("AF_ALG", 38, socket.SOCK_SEQPACKET),
("AF_RXRPC", 33, socket.SOCK_DGRAM)]:
try:
socket.socket(family, stype, 0)
print(f"FAIL: {name} socket created")
except OSError as e:
if e.errno == errno.EPERM:
print(f"OK ({name}): blocked with EPERM")
else:
print(f"FAIL: {name} got {e.errno} ({e.strerror}), expected EPERM")'
अपेक्षित आउटपुट:
OK (AF_ALG): blocked with EPERM
OK (AF_RXRPC): blocked with EPERM
कोई भी अन्य errno (जैसे ESOCKTNOSUPPORT 94, EAFNOSUPPORT 97) का मतलब है कि हुक उस नोड पर सक्रिय नहीं है — यह मानने से पहले जांच करें कि आप कवर हैं।
make image # docker buildx build + push
make image REGISTRY=ghcr.io/myorg TAG=v0.3.0 # custom tag
make image PUSH=0 LOAD=1 # build locally without pushing
make image charts/copy-fail-blocker/values.yaml को हल किए गए इमेज डाइजेस्ट के साथ अपडेट करता है ताकि चार्ट हमेशा डाइजेस्ट द्वारा पिन करे।
बिल्ड निर्भरताएं Containerfile में रहती हैं (clang, libbpf-dev, Go)। स्थानीय होस्ट को केवल docker buildx, helm, yq (mikefarah), kubectl, और helm-diff चाहिए।
charts/copy-fail-blocker/values.yaml:
AF_ALG और AF_RXRPC फिर से पहुंच योग्य होते हैं। अधिकांश खतरे के मॉडल के लिए यह स्वीकार्य है; यदि नहीं, तो BPF लिंक को bpffs में पिन करने पर विचार करें (वर्तमान में लागू नहीं — योगदान स्वागत योग्य हैं)।CAP_BPF और CAP_SYS_ADMIN वाला कोई भी हुक को अलग कर सकता है। यह क्लस्टर-व्यापी विशेषाधिकार प्रतिबंधों का विकल्प नहीं है।algif_skcipher / algif_hash / आदि को ब्लॉक नहीं करता। प्रोग्राम पूरे AF_ALG परिवार को अस्वीकार करता है, लेकिन केवल algif_aead वर्तमान में शोषण योग्य माना जाता है। यदि भविष्य के CVE को बेहतर फ़िल्टर की आवश्यकता होती है (जैसे bind() हुक करना और salg_type का निरीक्षण करना), तो इसे जोड़ना सीधा है।AF_ALG या AF_RXRPC सॉकेट वाली प्रक्रियाओं पर कोई प्रभाव नहीं। मौजूदा सॉकेट बंद होने तक काम करते रहते हैं।Apache License 2.0 — LICENSE देखें।
| शमन | कवरेज | रीबूट? | स्थायी? |
|---|
कर्नेल cmdline module_blacklist=af_alg,rxrpc (परिवार हैंडलर, केवल algif_aead नहीं) | होस्ट-व्यापी | हाँ | हाँ |
/etc/modprobe.d/*.conf जिसमें install af_alg /bin/false + install rxrpc /bin/false और पहले से लोड मॉड्यूल का rmmod (अपस्ट्रीम Dirty Frag मार्गदर्शन से मेल खाता है — ध्यान दें कि सादा blacklist इन-कर्नेल request_module() ऑटोलोड को नहीं रोकता, केवल install … /bin/false रोकता है) | होस्ट-व्यापी | नहीं | हाँ (जब तक फ़ाइल मौजूद है) |
CRYPTO_USER_API / AF_RXRPC के बिना कस्टम कर्नेल | होस्ट-व्यापी | हाँ | हाँ |
| प्रति-पॉड कस्टम seccomp प्रोफ़ाइल | केवल लेबल किए गए वर्कलोड | नहीं | हाँ |
| copy-fail-blocker (यह प्रोजेक्ट) | होस्ट-व्यापी यूज़रस्पेस | नहीं | जब तक DS चलता है |
| कुंजी | डिफ़ॉल्ट | नोट्स |
|---|
image.repository | ghcr.io/cozystack/copy-fail-blocker | make image द्वारा स्वतः अपडेट |
image.tag | vX.Y.Z@sha256:... | डाइजेस्ट द्वारा पिन किया गया, वर्तमान मान values.yaml में |
priorityClassName | system-node-critical | सुनिश्चित करता है कि डेमॉन निष्कासन से बचे |
tolerations | [{operator: Exists}] | हर नोड पर चलता है, जिसमें tainted भी शामिल |
resources.requests | 5m CPU / 16Mi memory | संलग्न करने के बाद निष्क्रिय फुटप्रिंट |
UDP_ENCAP_ESPINUDP के माध्यम से पहुंचा जाता है, समर्पित सॉकेट परिवार के माध्यम से नहीं — वर्तमान में ट्रैक नहीं किया गया, योगदान स्वागत योग्य हैं। क्यों में नोट देखें।AF_RXRPC क्लाइंट ब्लॉक हैं। RxRPC AFS नेटवर्क प्रोटोकॉल है। !kern गार्ड का मतलब है कि इन-ट्री fs/afs (kAFS) मॉड्यूल काम करता रहता है क्योंकि यह अपने सॉकेट sock_create_kern() के माध्यम से खोलता है। यूज़रस्पेस AFS टूलिंग (जैसे OpenAFS यूज़रस्पेस डेमॉन) जो socket(2) के माध्यम से सीधे AF_RXRPC सॉकेट खोलता है, अस्वीकार कर दिया जाएगा — ऐसी टूलिंग चलाने वाले नोड्स पर यह DaemonSet तैनात न करें।