CVE-2021-44731 linux snap 本地提权漏洞分析
一.漏洞简述
1.snap简述
ubuntu官方对snap的解释:https://cn.ubuntu.com/blog/what-is-snap-application
Snap是Canonical为使用Linux内核的操作系统开发的软件打包和部署系统。这些包(称为 snaps)和使用它们的工具 snapd 可在一系列 Linux 发行版中工作。
Canonical科能软件有限公司(主业FOSS开源项目的):
Snap可包含一个或多个服务,支持cli(命令行)应用,GUI图形应用以及无单进程限制。因此,你可以单个snap下调用一个或多个服务。对于某些多服务的应用来说,非常方便。snap间相互隔离,可以通过interface(接口)定义来做资源交换。interface被用于让snap可访问OpenGL加速,声卡播放、录制,网络和HOME目录。Interface由slot和plug组成即提供者和消费者。
snap command:
列出已经安装的snap包
sudo snap list
搜索要安装的snap包
sudo snap find <text to search>
安装一个snap包
sudo snap install <snap name>
更新一个snap包,如果你后面不加包的名字的话那就是更新所有的snap包
sudo snap refresh <snap name>
把一个包还原到以前安装的版本
sudo snap revert <snap name>
删除一个snap包
sudo snap remove <snap name>
二.影响版本:
1.漏洞披露先后:
CVE-2021-44731 snap-confine 的 setup_private_mount() 中的竞争条件
CVE-2021-44730 snap-confine 的 sc_open_snapd_tool() 中的硬链接攻击
CVE-2021-3996 util-linux 的 libmount 中未经授权的卸载
CVE-2021-3995 util-linux 的 libmount 中未经授权的卸载
CVE-2021-3998 来自 glibc 的 realpath() 的意外返回值
CVE-2021-3999 glibc 的 getcwd() 中的一个缓冲区溢出/下溢
CVE-2021-3997 systemd 的 systemd-tmpfiles 中不受控制的递归的挖掘
竞争条件
竞争条件发生在当多个进程或者线程在读写数据时,其最终的的结果依赖于多个进程的指令执行顺序。
例如:考虑下面的例子
假设两个进程P1和P2共享了变量a。在某一执行时刻,P1更新a为1,在另一时刻,P2更新a为2。
因此两个任务竞争地写变量a。在这个例子中,竞争的“失败者”(最后更新的进程)决定了变量a的最终值。
多个进程并发访问和操作同一数据且执行结果与访问的特定顺序有关,称为竞争条件。
对应时间线的挖洞大佬
James Troup 发现 snap 没有正确管理
snap 目录的权限。本地攻击者可能会利用此问题来暴露
敏感信息。( CVE-2021-3155 )
Ian Johnson 发现 snapd 没有正确验证内容界面
和布局路径。本地攻击者可能会利用此问题注入
任意 AppArmor 策略规则,从而绕过预期的访问
限制。( CVE-2021-4120 )
Qualys 研究团队发现 snapd 没有正确验证
snap-confine 二进制文件的位置。本地攻击者可能会使用此
问题来执行其他任意二进制文件并提升权限。
( CVE-2021-44730 )
Qualys 研究团队在为snap 准备私有挂载命名空间时发现 snapd snap-confine 二进制文件中存在竞争条件。
本地攻击者可能会使用此问题来提升权限并执行
任意代码。( CVE-2021-44731 )
2.受影响版本
该漏洞目前主要影响范围为ubuntu发行版:
Ubuntu 21.10 snapd/snap-confine < 2.54.3+21.10.1
Ubuntu 20.04 LTS snapd/snap-confine < 2.54.3+20.04
Ubuntu 18.04 LTS snapd/snap-confine < 2.54.3+18.04
Ubuntu 16.04 ESM 待官方更新
3.不受影响版本
安全版本
Ubuntu 21.10 snapd/snap-confine >= 2.54.3+21.10.1
Ubuntu 20.04 LTS snapd/snap-confine >= 2.54.3+20.04
Ubuntu 18.04 LTS snapd/snap-confine >= 2.54.3+18.04
Ubuntu 16.04 ESM 待官方更新
三.漏洞分析
1.反向分析(补丁版本 snap-confine 2.54.3),先了解snap-confine的大致结构:
核心分析/usr/lib/snapd/snap-confine文件,该文件是一个二进制文件,搞成文本下来看下:
xxd snap-confine > snap-confine.txt
(1)file查看文件类型
root@VM-0-5-ubuntu:/usr/lib/snapd# file snap-confine
snap-confine: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=f946d2d193895203adbd114d6b9aad311a211a46, for GNU/Linux 3.2.0, stripped
(2)ldd查看调用库关系
root@VM-0-5-ubuntu:/usr/lib/snapd# ldd snap-confine
linux-vdso.so.1 (0x00007ffd1cca9000)
libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f513097a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5130974000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f5130951000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f513075f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f51309e3000)
(3)ltrace查看函数调用关系
root@VM-0-5-ubuntu:/usr/lib/snapd# ltrace /usr/lib/snapd/snap-confine
Usage: snap-confine <security-tag> <executable>
application or hook security tag was not provided
(4)readelf查看elf信息
root@VM-0-5-ubuntu:/usr/lib/snapd# readelf -h snap-confine
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x60c0
Start of program headers: 64 (bytes into file)
Start of section headers: 140776 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 29
(5)objdump从对象文件中显示信息
root@VM-0-5-ubuntu:/usr/lib/snapd# objdump -d snap-confine | head
snap-confine: file format elf64-x86-64
Disassembly of section .init:
0000000000004000 <.init>:
4000: f3 0f 1e fa endbr64
4004: 48 83 ec 08 sub $0x8,%rsp
4008: 48 8b 05 c9 ef 01 00 mov 0x1efc9(%rip),%rax # 22fd8 <__gmon_start__>
(6)strace:
root@VM-0-5-ubuntu:/usr/lib/snapd# strace -f /usr/lib/snapd/snap-confine
execve("/usr/lib/snapd/snap-confine", ["/usr/lib/snapd/snap-confine"], 0x7fffa6ec0368 /* 21 vars */) = 0
brk(NULL) = 0x560d7306f000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe7b9f6ae0) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=87696, ...}) = 0
mmap(NULL, 87696, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fda927f9000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libudev.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\\177ELF\\2\\1\\1\\0\\0\\0\\0\\0\\0\\0\\0\\0\\3\\0>\\0\\1\\0\\0\\0\\0`\\0\\0\\0\\0\\0\\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=178528, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fda927f7000
mmap(NULL, 182536, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fda927ca000
mmap(0x7fda927cf000, 114688, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x5000) = 0x7fda927cf000
mmap(0x7fda927eb000, 40960, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x21000) = 0x7fda927eb000
mmap(0x7fda927f5000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2a000) = 0x7fda927f5000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\\177ELF\\2\\1\\1\\0\\0\\0\\0\\0\\0\\0\\0\\0\\3\\0>\\0\\1\\0\\0\\0 \\22\\0\\0\\0\\0\\0\\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=18816, ...}) = 0
mmap(NULL, 20752, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fda927c4000
mmap(0x7fda927c5000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1000) = 0x7fda927c5000
mmap(0x7fda927c7000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7fda927c7000
mmap(0x7fda927c8000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7fda927c8000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\\177ELF\\2\\1\\1\\0\\0\\0\\0\\0\\0\\0\\0\\0\\3\\0>\\0\\1\\0\\0\\0\\220\\201\\0\\0\\0\\0\\0\\0"..., 832) = 832
pread64(3, "\\4\\0\\0\\0\\24\\0\\0\\0\\3\\0\\0\\0GNU\\0\\345Ga\\367\\265T\\320\\374\\301V)Yf]\\223\\337"..., 68, 824) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=157224, ...}) = 0
pread64(3, "\\4\\0\\0\\0\\24\\0\\0\\0\\3\\0\\0\\0GNU\\0\\345Ga\\367\\265T\\320\\374\\301V)Yf]\\223\\337"..., 68, 824) = 68
mmap(NULL, 140408, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fda927a1000
mmap(0x7fda927a8000, 69632, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7fda927a8000
mmap(0x7fda927b9000, 20480, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7fda927b9000
mmap(0x7fda927be000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c000) = 0x7fda927be000
mmap(0x7fda927c0000, 13432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fda927c0000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\\177ELF\\2\\1\\1\\3\\0\\0\\0\\0\\0\\0\\0\\0\\3\\0>\\0\\1\\0\\0\\0\\360q\\2\\0\\0\\0\\0\\0"..., 832) = 832
pread64(3, "\\6\\0\\0\\0\\4\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0"..., 784, 64) = 784
pread64(3, "\\4\\0\\0\\0\\20\\0\\0\\0\\5\\0\\0\\0GNU\\0\\2\\0\\0\\300\\4\\0\\0\\0\\3\\0\\0\\0\\0\\0\\0\\0", 32, 848) = 32
pread64(3, "\\4\\0\\0\\0\\24\\0\\0\\0\\3\\0\\0\\0GNU\\0\\t\\233\\222%\\274\\260\\320\\31\\331\\326\\10\\204\\276X>\\263"..., 68, 880) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2029224, ...}) = 0
pread64(3, "\\6\\0\\0\\0\\4\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0@\\0\\0\\0\\0\\0\\0\\0"..., 784, 64) = 784
pread64(3, "\\4\\0\\0\\0\\20\\0\\0\\0\\5\\0\\0\\0GNU\\0\\2\\0\\0\\300\\4\\0\\0\\0\\3\\0\\0\\0\\0\\0\\0\\0", 32, 848) = 32
pread64(3, "\\4\\0\\0\\0\\24\\0\\0\\0\\3\\0\\0\\0GNU\\0\\t\\233\\222%\\274\\260\\320\\31\\331\\326\\10\\204\\276X>\\263"..., 68, 880) = 68
mmap(NULL, 2036952, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fda925af000
mprotect(0x7fda925d4000, 1847296, PROT_NONE) = 0
mmap(0x7fda925d4000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7fda925d4000
mmap(0x7fda9274c000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7fda9274c000
mmap(0x7fda92797000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7fda92797000
mmap(0x7fda9279d000, 13528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fda9279d000
close(3) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fda925ad000
arch_prctl(ARCH_SET_FS, 0x7fda925adc00) = 0
mprotect(0x7fda92797000, 12288, PROT_READ) = 0
mprotect(0x7fda927be000, 4096, PROT_READ) = 0
mprotect(0x7fda927c8000, 4096, PROT_READ) = 0
mprotect(0x7fda927f5000, 4096, PROT_READ) = 0
mprotect(0x560d713b9000, 4096, PROT_READ) = 0
mprotect(0x7fda9283c000, 4096, PROT_READ) = 0
munmap(0x7fda927f9000, 87696) = 0
set_tid_address(0x7fda925aded0) = 4055346
set_robust_list(0x7fda925adee0, 24) = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7fda927a8bf0, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7fda927b63c0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7fda927a8c90, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7fda927b63c0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
prctl(PR_CAPBSET_READ, CAP_MAC_OVERRIDE) = 1
prctl(PR_CAPBSET_READ, 0x30 /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, 0x28 /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, CAP_BLOCK_SUSPEND) = 1
prctl(PR_CAPBSET_READ, 0x26 /* CAP_??? */) = -1 EINVAL (Invalid argument)
prctl(PR_CAPBSET_READ, CAP_AUDIT_READ) = 1
brk(NULL) = 0x560d7306f000
brk(0x560d73090000) = 0x560d73090000
write(2, "Usage: snap-confine <security-ta"..., 99Usage: snap-confine <security-tag> <executable>
application or hook security tag was not provided
) = 99
exit_group(1) = ?
+++ exited with 1 +++
7.radare2分析
r2 snap-confine
[0x000060c0]> afl
0x0000b060 5 237 fcn.0000b060
0x000060f0 4 41 -> 34 fcn.000060f0
0x00006330 19 352 -> 345 fcn.00006330
0x00006490 7 208 -> 203 fcn.00006490
0x00006560 12 512 -> 506 fcn.00006560
0x00006760 42 1776 -> 1752 fcn.00006760
0x00007150 77 2744 -> 2704 fcn.00007150
0x00007c10 11 192 fcn.00007c10
0x00008880 14 240 fcn.00008880
0x00008c00 0 0 fcn.00008c00
0x00008970 7 320 fcn.00008970
0x00008ab0 7 336 fcn.00008ab0
0x0000a230 9 176 fcn.0000a230
0x0000a2e0 15 464 -> 453 fcn.0000a2e0
0x0000a750 1 39 fcn.0000a750
0x0000c340 24 443 -> 441 fcn.0000c340
0x0000ca70 3 128 fcn.0000ca70
0x0000d280 0 0 fcn.0000d280
0x0000caf0 48 1936 -> 1909 fcn.0000caf0
0x0000d3a0 4 122 fcn.0000d3a0
0x0000d420 3 62 -> 57 fcn.0000d420
0x0000d460 18 576 -> 573 fcn.0000d460
0x0000e1b0 5 128 fcn.0000e1b0
0x0000e230 1 22 fcn.0000e230
0x0000e600 4 156 -> 152 fcn.0000e600
0x0000ecf0 12 544 -> 538 fcn.0000ecf0
0x0000ff10 17 209 -> 192 fcn.0000ff10
0x0000fff0 4 55 fcn.0000fff0
0x00011320 23 448 -> 436 fcn.00011320
0x000128e0 3 65 -> 55 fcn.000128e0
0x00012890 3 79 -> 75 fcn.00012890
0x000133b0 28 392 -> 378 fcn.000133b0
0x00013540 5 116 -> 110 fcn.00013540
0x00014290 22 209 -> 190 fcn.00014290
0x00014370 15 268 -> 260 fcn.00014370
0x00015c20 4 46 -> 36 fcn.00015c20
0x00015a60 31 447 -> 438 fcn.00015a60
0x00015980 9 212 -> 206 fcn.00015980
0x0000d280 8 288 fcn.0000d280
0x00008c00 11 224 fcn.00008c00
2.正向patch分析:核心漏洞函数setup_private_mount()竞争条件分析
snapd_2.54.2漏洞版本链接:http://launchpadlibrarian.net/586584361/snapd_2.54.2+20.04ubuntu2_2.54.3+20.04.diff.gz
查询对应补丁(patch)版本 snapd-2.54.3 比较的代码,分析下patch修复的是哪一部分?
记录下函数所在文件路径 /ubuntu2/cmd/snap-confine/mount-support.c
diff -Nru snapd-2.54.2+20.04ubuntu2/cmd/snap-confine/mount-support.c snapd-2.54.3+20.04/cmd/snap-confine/mount-support.c
--- snapd-2.54.2+20.04ubuntu2/cmd/snap-confine/mount-support.c 2022-01-06 21:25:16.000000000 +0000
+++ snapd-2.54.3+20.04/cmd/snap-confine/mount-support.c 2022-02-15 16:45:13.000000000 +0000
—————————————————————————————————————————————分割线———————————————————————————————————————————————————
@@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -51,6 +52,91 @@
static void sc_detach_views_of_writable(sc_distro distro, bool normal_mode);
+static int must_mkdir_and_open_with_perms(const char *dir, uid_t uid, gid_t gid,
+ mode_t mode)
+{
+ int retries = 10;
+ int fd;
+
+ mkdir:
+ if (--retries == 0) {
+ die("lost race to create dir %s too many times", dir);
+ }
+ // Ignore EEXIST since we want to reuse and we will open with
+ // O_NOFOLLOW, below.
+ if (mkdir(dir, 0700) < 0 && errno != EEXIST) {
+ die("cannot create directory %s", dir);
+ }
+ fd = open(dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
+ if (fd < 0) {
+ // if is not a directory then remove it and try again
+ if (errno == ENOTDIR && unlink(dir) == 0) {
+ goto mkdir;
+ }
+ die("cannot open directory %s", dir);
+ }
+ // ensure base_dir has the expected permissions since it may have
+ // already existed
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ die("cannot stat base directory %s", dir);
+ }
+ if (st.st_uid != uid || st.st_gid != gid
+ || st.st_mode != (S_IFDIR | mode)) {
+ unsigned char random[10] = { 0 };
+ char random_dir[MAX_BUF] = { 0 };
+ int offset;
+ size_t i;
+
+ // base_dir isn't what we expect - create a random
+ // directory name and rename the existing erroneous
+ // base_dir to this then try recreating it again - NOTE we
+ // don't use mkdtemp() here since we don't want to actually
+ // create the directory yet as we want rename() to do that
+ // for us
+#ifdef SYS_getrandom
+ // use syscall(SYS_getrandom) since getrandom() is
+ // not available on older glibc
+ if (syscall(SYS_getrandom, random, sizeof(random), 0) !=
+ sizeof(random)) {
+ die("cannot get random bytes");
+ }
+#else
+ // use /dev/urandom on older systems which don't support
+ // SYS_getrandom
+ int rfd = open("/dev/urandom", O_RDONLY);
+ if (rfd < 0) {
+ die("cannot open /dev/urandom");
+ }
+ if (read(rfd, random, sizeof(random)) != sizeof(random)) {
+ die("cannot get random bytes");
+ }
+ close(rfd);
+#endif
+ offset =
+ sc_must_snprintf(random_dir, sizeof(random_dir), "%s.",
+ dir);
+ for (i = 0; i < sizeof(random); i++) {
+ offset +=
+ sc_must_snprintf(random_dir + offset,
+ sizeof(random_dir) - offset,
+ "%02x", (unsigned int)random[i]);
+ }
+ // try and get dir which we own by renaming it to something
+ // else then creating it again
+
+ // TODO - change this to use renameat2(RENAME_EXCHANGE)
+ // once we can use a newer version of glibc for snapd
+ if (rename(dir, random_dir) < 0) {
+ die("cannot rename base_dir to random_dir '%s'",
+ random_dir);
+ }
+ close(fd);
+ goto mkdir;
+ }
+ return fd;
+}
+
// TODO: simplify this, after all it is just a tmpfs
// TODO: fold this into bootstrap
—————————————————————————————————————————————分割线———————————————————————————————————————————————————
/*以下是漏洞函数setup_private_mount()*/
static void setup_private_mount(const char *snap_name)
@@ -86,29 +172,8 @@
/* Switch to root group so that mkdir and open calls below create filesystem
* elements that are not owned by the user calling into snap-confine. */
/* 切换到根组,以便 mkdir 和 open 调用在下面创建文件系统
* 调用 snap-confine 的用户不拥有的元素。 *
sc_identity old = sc_set_effective_identity(sc_root_group_identity());
- // Create /tmp/snap.$SNAP_NAME/ 0700 root.root. Ignore EEXIST since we want
- // to reuse and we will open with O_NOFOLLOW, below.
- // 创建 /tmp/snap.$SNAP_NAME/0700 root.root。忽略 EEXIST,因为我们想要
- // 重用,我们将使用 O_NOFOLLOW 打开,如下所示。
- if (mkdir(base_dir, 0700) < 0 && errno != EEXIST) {
- die("cannot create base directory %s", base_dir);
- }
- base_dir_fd = open(base_dir,
- O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
- if (base_dir_fd < 0) {
- die("cannot open base directory %s", base_dir);
- }
-
/* This seems redundant on first read but it has the non-obvious
- * property of changing existing directories that have already existed
- * but had incorrect ownership or permission. This is possible due to
- * earlier bugs in snap-confine and due to the fact that some systems
- * use persistent /tmp directory and may not clean up leftover files
- * for arbitrarily long. This comment applies the following two pairs
- * of fchmod and fchown. */
/* 这在第一次阅读时似乎是多余的,但它有不明显的
- * 更改已存在的现有目录的属性
- * 但拥有不正确的所有权或权限。这是可能的,因为
- * snap-confine 中的早期错误以及由于某些系统
- * 使用持久化/tmp 目录并且可能不会清理剩余文件
- * 任意长。此评论适用以下两对
- * fchmod 和 fchown。 */
- if (fchmod(base_dir_fd, 0700) < 0) {
- die("cannot chmod base directory %s to 0700", base_dir);
- }
- if (fchown(base_dir_fd, 0, 0) < 0) {
- die("cannot chown base directory %s to root.root", base_dir);
- }
+ // Create /tmp/snap.$SNAP_NAME/ 0700 root.root.
+ // 创建 /tmp/snap.$SNAP_NAME/ 0700 root.root。
+ base_dir_fd = must_mkdir_and_open_with_perms(base_dir, 0, 0, 0700);
// Create /tmp/snap.$SNAP_NAME/tmp 01777 root.root Ignore EEXIST since we
// want to reuse and we will open with O_NOFOLLOW, below.
// 创建 /tmp/snap.$SNAP_NAME/tmp 01777 root.root 忽略 EEXIST,因为我们
// 想要重用,我们将使用 O_NOFOLLOW 打开,如下所示。
if (mkdirat(base_dir_fd, "tmp", 01777) < 0 && errno != EEXIST) {
@@ -120,14 +185,14 @@
if (tmp_dir_fd < 0) {
die("cannot open private tmp directory %s/tmp", base_dir);
}
- if (fchmod(tmp_dir_fd, 01777) < 0) {
- die("cannot chmod private tmp directory %s/tmp to 01777",
- base_dir);
- }
if (fchown(tmp_dir_fd, 0, 0) < 0) {
die("cannot chown private tmp directory %s/tmp to root.root",
base_dir);
}
+ if (fchmod(tmp_dir_fd, 01777) < 0) {
+ die("cannot chmod private tmp directory %s/tmp to 01777",
+ base_dir);
+ }
sc_do_mount(tmp_dir, "/tmp", NULL, MS_BIND, NULL);
sc_do_mount("none", "/tmp", NULL, MS_PRIVATE, NULL);
}
@@ -464,7 +529,8 @@
sc_identity old = sc_set_effective_identity(sc_root_group_identity());
if (mkdir(SC_HOSTFS_DIR, 0755) < 0) {
if (errno != EEXIST) {
- die("cannot perform operation: mkdir %s", SC_HOSTFS_DIR);
+ die("cannot perform operation: mkdir %s",
+ SC_HOSTFS_DIR);
}
}
(void)sc_set_effective_identity(old);