Since even with edge-triggered epoll, multiple events can be generated upon receipt of multiple chunks of data, the caller has the option to specify the EPOLLONESHOT flag, to tell epoll to disable the associated file descriptor after the receipt of an event with epoll_wait(2). When the EPOLLONESHOT flag is specified, it is the caller’s responsibility to rearm the file descriptor using epoll_ctl(2) with EPOLL_CTL_MOD.
原子操作:如果使用 O_APPEND 标志打开一个文件,那么相应的标志也被设置到文件表项的文件状态标志中。每次对文件执行写操作时,文件表项中的当前文件偏移量首先会被设置为 i 节点表项中的文件长度(相对其他进程来说是原子操作,不论是两个独立的进程,还是父子进程)。这就使得每次写入的数据都追加到文件的当前尾端处。这里有一个测试的例子,文章结论不见得正确,请参考评论的讨论。
If the file was open(2)ed with O_APPEND, the file offset is first set to the end of the file before writing. The adjustment of the file offset and the write operation are performed as an atomic step.
lseek:
若一个文件用 lseek 定位到文件当前的尾端,则文件表项中的当前文件偏移量被设置为 i 节点表项中的当前文件长度(注意,此时,设置偏移量和写操作之间不是原子操作)。
然而,系统判断一个进程对一个文件是否有权限时,要验证的 ID 是 effective user ID,而不是 real user ID。
有效用户 ID(EUID, Effective User ID)
Linux 通常都不建议用户使用 root 权限去进行一般的处理,但是普通用户在做很多很多 services 相关的操作的时候,可能需要一个特殊的权限。为 了满足这样的要求,许多 services 相关的 executable 有一个标志,这就是 set-user-ID bit。当这个 set-user-ID bit=ON 的时候,这个 executable 被用 exec 启动之后的进程的 effective user ID 就是这个 executable 的 owner id,而并非 parent process real user id。如果 set-user-ID bit=OFF 的时候,这个被 exec 起来的进程的 effective user ID 应该是等于进程的 user ID 的。 我们以 ping 命令为例。
使用 which 命令搜索二进制位置,然后运行 ls -la:
-rwsr-xr-x 1 root root 64424 Mar 10 2017 ping
可以看到文件的所有者和组是 root. 这是因为该 ping 命令需要打开一个套接字,而 Linux 内核 root 为此需要特权。
$ ls -l testfile -rw-rw-r-- 1 rotem rotem 0 Nov 8 17:12 testfile
为文件添加 set-user-ID 权限:
1 2 3
$ sudo chmod u+s testfile $ ls -l testfile -rwSrw-r-- 1 rotem rotem 0 Nov 8 17:12 testfile
说明:大写 S 表示,有 set-user-ID 权限,但是没有执行权限。
set-group-ID
阅读 Manual:man 2 stat。
The set-group-ID bit (S_ISGID) has several special uses. For a directory, it indicates that BSD semantics is to be used for that directory: files created there inherit their group ID from the directory, not from the effective group ID of the creating process, and directories created there will also get the S_ISGID bit set.
如果目录具有设置组 ID(S_ISGID):
其下创建的文件将从其父目录的继承组 ID,而不能从创建其的进程中继承有效组 ID;
其下创建的子目录将继承设置组 ID 位(S_ISGID)。
For a file that does not have the group execution bit (S_IXGRP) set, the set-group-ID bit indicates mandatory file/record locking.
The sticky bit (S_ISVTX) on a directory means that a file in that directory can be renamed or deleted only by the owner of the file, by the owner of the directory, and by a privileged process.
大写 T 表示,有 restricted deletion flag or sticky bit(粘滞位),但是没有执行权限,t 权限只对目录有效,作用是保护目录项不能被其他用户删除。目录要同时具有 x 和 s 才能保证粘滞位有效。
保存的用户 ID (SUID, Saved User ID)
为什么要设置一个 saved set-user-ID 呢?它的意义是,它相当于是一个 buffer, 在 exec 启动进程之后,它会从 effective user ID 位拷贝信息到自己。
对于非 root 用户,可以在未来使用 setuid() 来将 effective user ID 设置成为 real user ID 和 saved set-user-ID 中的任何一个。但是非 root 用户是不允许用 setuid() 把 effective user ID 设置成为任何第三个 user id。
对于 root 来说,就没有那么大的意义了。因为 root 调用 setuid() 的时候,将会设置所有的这三个 user ID 位。所以可以综合说,这三个位的设置为为了让 unprivilege user 可以获得两种不同的 permission 而设置的。
《Unix 环境高级编程》的例子是,普通用户去执行一个 tip 进程,set-user-ID bit=ON,执行起来的时候,进程可以有 uucp (executable owner) 的权限来写 lock 文件,也有当前普通用户的权限来写数据文件。在两种文件操作之间,使用 setuid() 来切换 effective user id。但是正是因为 setuid() 的限制,该进程无法获得更多的第三种用户的权限。
ls 没有可搜索权限的目录 可以看到文件列表、文件类型,但是不能看到其他信息,比如文件权限、所有者、大小、修改时间等,因为这些信息保存在 inode 中,必须先 cd 进入该目录,才能读取这些信息。同样,ls -R 不能显示没有执行权限的目录下的子目录下的文件,因为这也必须先 cd 该目录,然后执行 ls 显示子目录的文件。
$ chmod -R u+X mydir/ $ ls -lR mydir/ mydir/: total 4 drwxrwxr-x 3 rotem rotem 4096 Nov 9 10:02 dir2 -rwxrw-r-- 1 rotem rotem 0 Nov 9 10:03 file2
mydir/dir2: total 8 -rwxrw-r-- 1 rotem rotem 10 Nov 8 22:55 1.txt -rwxrw-r-- 1 rotem rotem 0 Nov 8 22:55 2.txt drwxrwxr-x 2 rotem rotem 4096 Nov 9 10:05 dir3
mydir/dir2/dir3: total 0 -rwxrw-r-- 1 rotem rotem 0 Nov 9 10:05 3.txt
s:即 set-user-ID 权限,如果可执行文件有 s 权限属性,那么任意进程执行该文件时,将自动获得该文件所有者相同的所有权限。如果文件没有 x 权限,却有 s 权限,那么 ls -l 命令将该文件显示为大写的 S。文件只有同时具备 s 权限和 x 权限,才有意义,因为一个文件要应用 set-user-ID 属性,首先要保证其可执行。
例如 ping 文件:
1 2
$ ls -l /bin/ping -rwsr-xr-x 1 root root 44168 May 8 2014 /bin/ping
由于设置了 s 权限,所以任何文件都能以 root 用户的身份运行,也就被内核允许打开套接字。
t:即 restricted deletion flag or sticky bit,称为 “粘滞位” 或 “限制删除标记”。仅仅对目录有效,对文件无效。在一个目录上设了 t 权限位后,(如 /home,权限为 1777) 任何的用户都能够在这个目录下创建文档,但只能删除自己创建的文档 (root 除外),这就对任何用户能写的目录下的用户文档 启到了保护的作用。如果目录 / 文件没有 x 权限,却有 s 权限,则 ls -l 命令将目录 / 文件显示为大写的 T。目录只有同时具备 t 权限和 x 权限,才有意义,因为一个目录如果本来就不允许增删目录项(x 权限),删除其他用户的文件更无须提了。
A numeric mode is from one to four octal digits (0-7), derived by adding up the bits with values 4, 2, and 1. Omitted digits are assumed to be leading zeros. The first digit selects the set user ID (4) and set group ID (2) and restricted deletion or sticky (1) attributes. The second digit selects permissions for the user who owns the file: read (4), write (2), and execute (1); the third selects permissions for other users in the file’s group, with the same values; and the fourth for other users not in the file’s group, with the same values.
The letters rwxXst select file mode bits for the affected users: read (r), write (w), execute (or search for directories) (x), execute/search only if the file is a directory or already has execute permission for some user (X), set user or group ID on execution (s), restricted deletion flag or sticky bit (t) [^2].
加黑体的话很费解,但是又十分准确,解释如下:
对所有目录赋予执行权限,这意味着可以执行 cd。
对所有文件,如果原来文件的 ugo(user / group / others)任意一个原先有执行权限,那么动作与小写 -x 参数相同;如果原先没有,那么忽略。例如:
1
ls -l
结果:
-rw-rw-r– 1 rotem rotem 0 Nov 9 10:55 file1 -rw-rw-r-x 1 rotem rotem 0 Nov 9 10:56 file2