Issue
I am experimenting with 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));
}
}
If I run the executable with sudo
, then normally, there is no error. However, if I run as a normal user, I get for the sudo
process: 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
Why is this happening and how can I create the lock file to be accessible for both processes in both cases?
Solution
Typically, Linux systems have the /tmp
directory owned (and group-owned) by root
and it has mode 1777/drwxrwxrwt
, which means that the "sticky" bit is set.
After:
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
The open()
call failed with errno
set to EACCES
because the current user is root
, the file /tmp/test.lock
already exists, the owner r
of the file is neither the current user nor the owner of the containing directory /tmp
, and the containing directory is both world- or group-writable and sticky. This error situation is documented in the Linux open(2) man page:
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).
The file in question is a regular file so the fs.protected_regular
sysctl setting controls the behavior. It is documented in the Linux proc(5) man page:
/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.
If necessary, the setting could be disabled at runtime using the sysctl
command (see sysctl(8)):
sudo sysctl fs.protected_regular=0
The setting may be set during system boot by editing the /etc/sysctl.conf
or /etc/sysctl.d/*.conf
files (see sysctl.conf(5)):
fs.protected_regular = 0
However, changing the setting would make the system more vulnerable to attack.
Answered By - Ian Abbott Answer Checked By - Katrina (WPSolving Volunteer)