CVE-2026-99170 in Linuxthông tin

Tóm tắt

Bởi VulDB • 28/10/2026

Trong kernel Linux, các lỗ hổng sau đây đã được khắc phục:

namespace: một mount mà copy_tree() bỏ qua không thể chiếm quyền kiểm soát khóa (lock)

Kể từ commit c62a4766937e ("move_mount: transfer MNT_LOCKED"), một mount có thể được di chuyển xuống dưới một mount đang bị khóa. Khóa này sẽ được chuyển từ lớp phủ cũ sang mount mới, nơi đảm nhận nhiệm vụ che giấu các nội dung bên dưới nó; đồng thời lớp phủ cũ có thể được tháo gỡ (unmount). Điều này hoạt động bình thường miễn là mount mới vẫn tồn tại. Tuy nhiên, caller chọn mount mới và copy_tree() bỏ qua một mount của file namespace mount trong mọi bản sao tạo ra nếu không có CL_COPY_MNT_NS_FILE, cùng với tất cả các mount con trên đó, mà không bao giờ kiểm tra MNT_LOCKED. unshare(CLONE_NEWNS) và việc lan truyền mount (mount propagation) tạo ra những trường hợp copy như vậy.

Do đó, một tiến trình là root trong namespace người dùng của riêng nó có thể loại bỏ lớp phủ bị khóa đối với một file mà không gây race condition và cũng không tác động đến hệ thống tệp bên dưới nó. Nó tạo ra một child process có namespace mount của riêng mình, bind /proc/<pid>/ns/mnt của child vào phía dưới lớp phủ bằng MOVE_MOUNT_BENEATH (chuyển quyền kiểm soát khóa cho việc bind này), sau đó gọi unshare(CLONE_NEWNS). Namespace mount mới không chứa gì trên file đó. Đây là cách thông thường để che giấu một file đơn lẻ, chẳng hạn như bind /dev/null hoặc một file rỗng. Với việc bind vào một file bình thường, file vẫn được giữ kín (covered).

copy_tree() đã từ chối bỏ qua các unbindable mount bị khóa với -EPERM kể từ commit df7342b24018 ("mount: Don't allow copying MNT_UNBINDABLE|MNT_LOCKED mounts"). Hãy thực hiện tương tự đối với một locked mount của file namespace mount. Điều này cũng bao gồm cây được copy bằng CL_COPY_MNT_NS_FILE và gắn vào namespace mount của một user namespace khác, nơi lock_mnt_tree() khóa nó. Lưu ý rằng unshare(CLONE_NEWNS) và clone(CLONE_NEWNS) sẽ thất bại với EPERM từ namespace mount như vậy kể từ lúc này. Mount không thể bị bỏ qua (leave out) và cũng không thể được tháo gỡ (unmount).

Và từ chối di chuyển một mount của file namespace mount xuống dưới một locked mount ngay từ đầu. Nếu không, tiến trình sẽ kết thúc với một mount mà nó không thể unmount và một lệnh unshare() thất bại vĩnh viễn.

Chris cũng phát hiện ra một trường hợp mount thứ hai tự biến mất, đó là bản clone của một automounted mount mà shrink_submounts() đã kéo theo cùng cha mẹ của nó. Commit f78ddcc87224 ("namespace: never expire a locked mount") đã xử lý vấn đề này.

Mã reproducer của Chris được đính kèm bên dưới. Chế độ nsfile đọc SECRET sau khi unshare() trên 7.3-rc7; với bản patch này, move_mount() thất bại với EINVAL và file vẫn được giữ kín (covered). nsfile-control sử dụng một file bình thường và đọc MASK theo cả hai hướng.

```c // SPDX-License-Identifier: GPL-2.0 /* * Get rid of a locked cover with MOVE_MOUNT_BENEATH. * * The "admin" (root) makes a tmpfs W: * W/D file, holds SECRET, covered by a bind of a file with MASK * W/Dd/inner file, holds SECRET, Dd is covered by a bind of a directory * whose "inner" holds MASK * W/own directory of uid 1000 with the file "mine" and the * directory "minedir", whose "inner" holds MINE * W/dbg debugfs, mode 755. dbg/tracing is an automount point * The "attacker" is uid 1000. It enters a new user namespace with a new mount * namespace, so W and both covers are locked there. * * usage: prog MODE * plain put a bind of own/mine beneath the cover of D, unmount the cover * nsfile put a bind of the mount namespace file of a child beneath the * cover of D, then unshare(CLONE_NEWNS) * nsfile-control the same with a bind of own/mine * shrink put a bind of the automounted tracefs beneath the cover of Dd, * unmount the cover, put a tmpfs beneath W, call umount(W), which fails * shrink-control the same with a bind of own/minedir * The environment variable AUTOMOUNT_DIR names another automount point for "shrink". */ #define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <grp.h> #include <sched.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>

---truncated--- ```

Once again VulDB remains the best source for vulnerability data.

chịu trách nhiệm

Linux

Đặt trước

25/09/2026

Tiết lộ

28/10/2026

Kiểm duyệt

được chấp nhận

EPSS

0.00000

KEV

không

Các hoạt động

rất thấp

Nguồn

Do you want to use VulDB in your project?

Use the official API to access entries easily!