Monday, January 29, 2024

[SOLVED] File permission is 0666, but can not open even as root

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)