
लिनक्स कर्नेल CVE-2026-31431 (कॉपी फेल) का गहन तकनीकी विश्लेषण, जो AF_ALG इन-प्लेस स्कैटरलिस्ट बग के माध्यम से स्थानीय विशेषाधिकार वृद्धि है, जिसमें मूल कारण, शोषण पथ, और पैच सबमिशन गाइड शामिल है।
गंभीरता: CVSS 7.8 (उच्च)
श्रेणी: स्थानीय विशेषाधिकार वृद्धि
परिचय: Linux 4.14 (2017)
समाधान: कमिट a664bf3d603d
CVE-2026-31431 Linux कर्नेल के algif_aead मॉड्यूल में एक स्थानीय विशेषाधिकार वृद्धि दोष है — कर्नेल के उपयोगकर्ता-स्थान क्रिप्टो API (AF_ALG) का AEAD सॉकेट इंटरफ़ेस।
यह भेद्यता एक अन-विशेषाधिकार प्राप्त उपयोगकर्ता को Linux कर्नेल के क्रिप्टो API में AF_ALG एड्रेस फ़ैमिली का उपयोग करके पेज कैश में नियंत्रित 4-बाइट लेखन करने की अनुमति देती है, जो फ़ाइलों की मेमोरी-में प्रतियों को समर्थन करता है। पेज कैश में संग्रहीत एक पठनीय निष्पादन योग्य की मेमोरी-में प्रति में कोड को प्रतिस्थापित करके, एक हमलावर उपयोगकर्ता विशेषाधिकार बढ़ा सकता है जब कोई विशेषाधिकार प्राप्त प्रक्रिया बाद में उस फ़ाइल के दूषित संस्करण को चलाती है।
Dirty Cow (CVE-2016-5195) के विपरीत, जिसमें रेस कंडीशन जीतने की आवश्यकता थी, Copy Fail एक सीधी-रेखा तर्क दोष है। यह बिना रेस, पुनः प्रयास, या क्रैश-प्रवण समय विंडो के ट्रिगर होता है।
कमिट 72548b093ee3 ("crypto: algif_aead - switch to in-place processing") ने एक अनुकूलन पेश किया जिसने aead_recvmsg() के अंदर req->src == req->dst सेट किया, जिससे एक अलग आउटपुट बफ़र आवंटन समाप्त हो गया।
इस अनुकूलन के कारण req->src और req->dst एक संयुक्त स्कैटरलिस्ट की ओर इंगित करने लगे। इसके कारण, splice() कॉल से पेज कैश पेज अनुचित रूप से सीधे लिखने योग्य गंतव्य स्कैटरलिस्ट में जुड़ गए।
कर्नेल का AEAD API एक स्पष्ट आउटपुट अनुबंध परिभाषित करता है: गंतव्य बफ़र AAD || plaintext प्राप्त करता है, बिल्कुल assoclen + (cryptlen - authsize) बाइट्स। API में कुछ भी इस अनुबंध को लागू नहीं करता है, और कुछ भी इसे आवश्यकता के रूप में दस्तावेज़ित नहीं करता है। डिज़ाइन मानता है कि हर AEAD एल्गोरिदम अपने लेखन को इच्छित गंतव्य तक सीमित रखेगा। एक एल्गोरिदम ने ऐसा नहीं किया।
crypto/
├── algif_aead.c ← इन-प्लेस स्कैटरलिस्ट बग (प्राथमिक)
└── authencesn.c ← आउट-ऑफ-बाउंड स्क्रैच लेखन (ट्रिगर)
crypto/algif_aead.c — इन-प्लेस असाइनमेंट/* VULNERABLE — post-2017 in-place path */
static int aead_recvmsg(struct socket *sock, struct msghdr *msg,
size_t ignored, int flags)
{
/* ... */
/*
* When userspace calls splice(2) on a file, areq->tsgl contains
* page cache pages of that file. Setting dst = src hands those
* page cache pages to the crypto engine as a writable output
* buffer.
*/
aead_request_set_crypt(req,
areq->tsgl, /* src */
areq->tsgl, /* dst — identical pointer; root cause */
areq->cryptlen, iv);
}
crypto/authencesn.c — आउट-ऑफ-बाउंड स्क्रैच लेखनauthencesn टेम्पलेट एक AEAD रैपर है जिसका उपयोग IPsec द्वारा विस्तारित अनुक्रम संख्या (ESN) समर्थन के लिए किया जाता है। IPsec 64-बिट अनुक्रम संख्याओं का उपयोग करता है जो एक उच्च आधे (seqno_hi, AAD के बाइट 0–3) और एक निम्न आधे (seqno_lo, बाइट 4–7) में विभाजित होती हैं। वायर प्रारूप केवल seqno_lo ले जाता है; seqno_hi निहित है।
/* crypto/authencesn.c — scratch write past output boundary */
static int crypto_authenc_esn_decrypt(struct aead_request *req)
{
/* ... */
/*
* authencesn temporarily stores seqno_hi at offset
* (assoclen + cryptlen) in req->dst — one word past the
* legitimate output region.
*
* Under normal operation: hits kernel-owned memory.
* With in-place scatterlist: hits a page cache page.
*/
scatterwalk_map_and_copy(&seqno_hi,
req->dst,
req->assoclen + req->cryptlen, /* out-of-bounds offset */
sizeof(seqno_hi), /* 4 bytes */
1 /* write */);
/* authencesn does not restore these bytes on the failing path */
}
अपस्ट्रीम समाधान: कमिट a664bf3d603d — 2017 के अनुकूलन को वापस लेता है।
crypto/algif_aead.c — अलग स्कैटरलिस्ट/* FIXED — separate src and dst */
aead_request_set_crypt(req,
areq->tsgl, /* src — may contain page cache pages; read-only */
areq->rsgl, /* dst — freshly allocated kernel buffer; writable */
areq->cryptlen, iv);
प्रभाव: पेज कैश पेज src में रहते हैं, जिसे क्रिप्टो इंजन केवल पढ़ता है। assoclen + cryptlen पर authencesn स्क्रैच लेखन अब एक कर्नेल-आवंटित बफ़र में समाप्त होता है जो प्रक्रिया के स्वामित्व में है। कोई भी पेज कैश पेज लेखन पथ से कभी पहुंच योग्य नहीं है।
निम्नलिखित वर्णन करता है कि 4-बाइट लेखन पूर्ण विशेषाधिकार वृद्धि कैसे प्राप्त करता है।
| चरण | क्रिया |
|---|---|
| 1 | authencesn(hmac(sha256),cbc(aes)) के लिए कॉन्फ़िगर किया गया AF_ALG सॉकेट खोलें |
| 2 | सॉकेट में एक पठनीय setuid बाइनरी (जैसे, /usr/bin/sudo) को splice() करें — यह इसके पेज कैश पेज को areq->tsgl में रखता है |
| 3 | assoclen + cryptlen को इस तरह तैयार करें कि स्क्रैच लेखन ऑफ़सेट बाइनरी की कैश्ड छवि के अंदर एक लक्ष्य बाइट के साथ संरेखित हो |
| 4 | recvmsg() कॉल करें — डिक्रिप्ट पथ ट्रिगर करता है, authencesn पेज कैश में 4 हमलावर-नियंत्रित बाइट्स लिखता है |
| 5 | डिस्क पर फ़ाइल अपरिवर्तित है; अखंडता जाँचकर्ता, inotify, और inode टाइमस्टैम्प प्रभावित नहीं होते हैं |
| 6 | बाइनरी का कोई भी बाद का निष्पादन पहले से संशोधित पेज कैश पेज को मैप करता है — पैच किया गया कोड euid=0 के साथ चलता है |
लेखन स्प्लिस्ड फ़ाइल के कैश्ड डेटा के अंदर मेमोरी में समाप्त होता है, फ़ाइल की अनुमतियों को पूरी तरह से दरकिनार करते हुए।
./scripts/get_maintainer.pl crypto/algif_aead.c
# Herbert Xu <[email protected]>
# [email protected]
./scripts/checkpatch.pl 0001-crypto-algif_aead-revert-inplace.patch
crypto: algif_aead - restore separate src/dst scatterlists in recvmsg
Commit 72548b093ee3 ("crypto: algif_aead - switch to in-place
processing") set req->src == req->dst inside aead_recvmsg(). When
the caller uses splice(2), the source scatterlist contains page
cache pages of the spliced file. With the in-place optimization,
those same pages become the writable destination passed to the
AEAD transform.
authencesn writes 4 bytes at offset (assoclen + cryptlen) into
req->dst as scratch space for Extended Sequence Number
rearrangement and does not restore them on the error path. With
page cache pages present in dst, this write bypasses the VFS
permission layer and corrupts the in-memory image of the spliced
file without modifying the on-disk inode.
An unprivileged local user can exploit this to overwrite
arbitrary bytes in the page cache of any readable setuid binary
and escalate privileges to root.
Restore separate src and dst scatterlists so that page cache
pages are confined to the read-only source path.
Fixes: 72548b093ee3 ("crypto: algif_aead - switch to in-place processing")
Cc: [email protected] # 4.14+
Reported-by: Taeyang Lee <[email protected]>
Signed-off-by: Your Name <[email protected]>
git send-email के माध्यम से भेजेंgit send-email \
[email protected] \
[email protected] \
[email protected] \
0001-crypto-algif_aead-revert-inplace.patch
| तत्व | उद्देश्य |
|---|---|
subsystem: file - verb phrase विषय | आवश्यक प्रारूप; 72 वर्णों से कम |
Fixes: <sha> ("original title") | स्वचालित स्थिर बैकपोर्ट टूलिंग ट्रिगर करता है |
Cc: [email protected] | LTS शाखा बैकपोर्ट के लिए पैच को चिह्नित करता है |
Reported-by: | खोजकर्ता को श्रेय |
Signed-off-by: | डेवलपर प्रमाणपत्र मूल — अनिवार्य |
भेद्य कर्नेल Linux 4.14 से 7.0-rc, सभी 6.18.x जो 6.18.22 से पहले हैं, और 6.19.x जो 6.19.12 से पहले हैं, तक फैले हुए हैं।
अंतरिम शमन (अधिकांश सिस्टम पर रीबूट की आवश्यकता नहीं):
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true
यह वर्कअराउंड dm-crypt/LUKS, kTLS, IPsec/XFRM, OpenSSL, GnuTLS, NSS, या SSH को प्रभावित नहीं करता है।
xint.io/blog/copy-fail-linux-distributionsnvd.nist.gov/vuln/detail/CVE-2026-31431a664bf3d603d (मेनलाइन)72548b093ee3 (Linux 4.14, 2017)