我正在试验flock个:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(){
    mode_t m = umask(0);
    int fd = open("/tmp/test.lock", O_RDWR | O_CREAT, 0666);
    if(fd == -1){
        printf("open failed. errno: %d, %s\n", errno, strerror(errno));
    }
    umask(m);
    int res = flock(fd, LOCK_EX);
    if(res != 0){
        printf("flock failed. errno: %d, %s\n", errno, strerror(errno));
    }
}

如果我用sudo运行可执行文件,那么正常情况下,不会出现错误.但是,如果我以普通用户身份运行,我会得到sudo进程的结果:open failed. errno: 13, Permission denied:

r@rvb-my:~/work$ gcc test.cpp
r@rvb-my:~/work$ ./a.out 
r@rvb-my:~/work$ ls -l /tmp/test.lock 
-rw-rw-rw- 1 r r 0 Jan 23 15:09 /tmp/test.lock
r@rvb-my:~/work$ sudo ./a.out 
open failed. errno: 13, Permission denied
flock failed. errno: 9, Bad file descriptor
r@rvb-my:~/work$ rm /tmp/test.lock 
r@rvb-my:~/work$ sudo ./a.out 
r@rvb-my:~/work$ ls -l /tmp/test.lock 
-rw-rw-rw- 1 root root 0 Jan 23 15:09 /tmp/test.lock
r@rvb-my:~/work$ ./a.out 
r@rvb-my:~/work$ ls -l /tmp/test.lock 
-rw-rw-rw- 1 root root 0 Jan 23 15:09 /tmp/test.lock

为什么会发生这种情况,以及如何创建锁定文件以使两个进程在这两种情况下都可以访问?

推荐答案

通常,Linux系统的/tmp个目录由root拥有(和组拥有),并且它具有模式1777/drwxrwxrwt,这意味着设置了"粘滞"位.

之后:

r@rvb-my:~/work$ ./a.out 
r@rvb-my:~/work$ ls -l /tmp/test.lock 
-rw-rw-rw- 1 r r 0 Jan 23 15:09 /tmp/test.lock
r@rvb-my:~/work$ sudo ./a.out 
open failed. errno: 13, Permission denied

open()调用失败,errno设置为EACCES,因为当前用户是root,文件/tmp/test.lock已经存在,文件的所有者r既不是当前用户,也不是包含目录/tmp的所有者,并且包含目录既是全局可写的,也是组可写的且粘滞.Linux open(2)手册页中记录了此错误情况:

       EACCES Where O_CREAT is specified, the protected_fifos or
              protected_regular sysctl is enabled, the file already
              exists and is a FIFO or regular file, the owner of the
              file is neither the current user nor the owner of the
              containing directory, and the containing directory is both
              world- or group-writable and sticky.  For details, see the
              descriptions of /proc/sys/fs/protected_fifos and
              /proc/sys/fs/protected_regular in proc(5).

有问题的文件是常规文件,因此fs.protected_regular sysctl设置控制行为.它记录在Linux proc(5)手册页中:

       /proc/sys/fs/protected_regular (since Linux 4.19)
              The value in this file is/can be set to one of the
              following:

              0   Writing to regular files is unrestricted.

              1   Don't allow O_CREAT open(2) on regular files that the
                  caller doesn't own in world-writable sticky
                  directories, unless the regular file is owned by the
                  owner of the directory.

              2   As for the value 1, but the restriction also applies
                  to group-writable sticky directories.

              The intent of the above protections is similar to
              protected_fifos, but allows an application to avoid writes
              to an attacker-controlled regular file, where the
              application expected to create one.

如有必要,可在运行时使用sysctl命令禁用该设置(请参见sysctl(8)):

sudo sysctl fs.protected_regular=0

该设置可在系统启动期间通过编辑/etc/sysctl.conf/etc/sysctl.d/*.conf文件进行设置(见sysctl.conf(5)):

fs.protected_regular = 0

然而,更改设置会使系统更容易受到攻击.

C++相关问答推荐

为指针 struct 创建宏

数组元素的编号索引

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

VS代码C/C++扩展intellisense无法检测环境特定函数'

返回一个包含数组的 struct

如果dim指定数组中的数据量,使用dim-1会不会潜在地导致丢失一个元素?

struct -未知大小

获取每个循环迭代结束时的当前时间

用C++实现余弦函数

为什么指针运算会产生错误的结果?

如何用C语言为CLI应用程序编写按键检测系统?

如何将大写/小写土耳其字母相互转换?

从BIOS(8086)中读取刻度需要多少?

带有数组指针的 struct 在print_stack()函数中打印随机数

将复合文字数组用作临时字符串缓冲区是否合理?

%g浮点表示的最大字符串长度是多少?

使用 strtok 多次分割一个字符串会导致意外行为

使用 c 中的 write() 函数将非 ASCII 字符写入标准输出

使用替代日历打印日期

将帧从相机 (/dev/video0) 复制到帧缓冲区 (/dev/fb0) 会产生意外结果