我试图了解 unix 域套接字的权限,当使用现有文件时,需要更改 umask 以及 dir 权限。
如果我以 root 身份创建一个世界可读的目录并使用 netcat 打开一个套接字:
root$: mkdir /tmp/mydir
root$: chmod 777 /tmp/mydir
root$: nc -l -U /tmp/mydir/sock
然后,作为非 root 用户尝试连接到上述套接字,它会失败,尽管该目录是世界可读的:
https://man7.org/linux/man-pages/man7/unix.7.html
在 Linux 实现中,路径名套接字尊重它们所在目录的权限。如果进程对创建套接字的目录没有写入和搜索(执行)权限,则新套接字的创建将失败。
root$: runuser -u user1 -- nc -U /tmp/mydir/sock
nc: unix connect failed: Permission denied
现在通过执行umask 0
,并再次重新启动同一个套接字,它能从非 root 用户连接到。
root$: umask 0
root$: nc -l -U /tmp/mydir/sock
root$: runuser -u user1 -- nc -U /tmp/mydir/sock
ping
此外,修改/tmp/mydir
权限chmod 600
将阻止非 root 用户再次访问套接字。
root$: chmod 600 /tmp/mydir
root$: runuser -u user1 -- nc -U /tmp/mydir/sock
nc: unix connect failed: Permission denied
很明显,根据手册,目录权限按预期工作,但是如果父目录具有正确的权限,为什么需要 umask 0 ? netcat 是否仍在创建某种其他文件?
答案1
你同样错过了这个UNIX(7)您引用的联机帮助页:
在 Linux 上,连接流套接字对象需要写权限 在那个插座上;向数据报套接字发送数据报同样需要该套接字的写权限。
当然,您还需要对其路径中的所有主要目录进行搜索(执行)权限,就像任何其他文件一样。
你引用的部分指的是创造一个套接字,其中仅有的当bind(2)
ing 到它时会发生,这就是事实nc -l -U /path/to/sock
。同样,就像创建任何其他文件一样,umask 将影响创建的套接字的权限(umask == 022 => 其他用户没有写权限 => 他们无法连接到套接字):
$ umask
0022
$ nc -Ul sock
^C
$ ls -l sock
srwxr-xr-x 1 xxx xxx 0 Oct 16 18:35 sock
^ ^ ^
绑定到 unix 域套接字总是必须从头开始创建它。您无法绑定到现有文件,这将失败并显示EADDRINUSE
.因此,大多数程序(包括nc
)将在绑定到任何同名文件之前强制删除该文件:
$ echo text > file
$ strace nc -l -U file
...
socket(AF_UNIX, SOCK_STREAM, 0) = 3
unlink("file") = 0
bind(3, {sa_family=AF_UNIX, sun_path="file"}, 110) = 0
listen(3, 5) = 0
accept4(3,
注意:两个片段都讨论了磁盘上的“套接字”特殊文件/索引节点,而不是表示活动套接字对象的索引节点(出现在/proc/<pid>/fd
、/proc/net/unix
等中):
$ nc -lU sock &
[1] 4424
$ ls -li sock
20983212 srwxr-xr-x 1 xxx xxx 0 Oct 17 18:01 sock
^^^^^^^^
$ ls -li /proc/4424/fd
total 0
43825 lrwx------ 1 xxx xxx 64 Oct 17 18:02 0 -> /dev/pts/4
43826 lrwx------ 1 xxx xxx 64 Oct 17 18:02 1 -> /dev/pts/4
43827 lrwx------ 1 xxx xxx 64 Oct 17 18:02 2 -> /dev/pts/4
43828 lrwx------ 1 xxx xxx 64 Oct 17 18:02 3 -> socket:[46378]
^^^^^
$ grep 46378 /proc/net/unix
00000000ee8c0faa: 00000002 00000000 00010000 0001 01 46378 sock