Does Linux Kernel Check File Permissions on Inode or Open File Description?

linux-kernelpermissionsread

I wrote this testing code, and find that this program can always read the file successfully even after I canceled the read permission when running getchar().

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/types.h> 
int main(){
    int f = open("a.txt",O_RDONLY);
    uint8_t data[200];
    printf("Got %d from read", pread(f, (void *)data, 200, 0));
    getchar();
    printf("Got %d from read", pread(f, (void *)data, 200, 0));
}

This program printed

Got 9 from read

twice, even though I use chmod a-r a.txt during pausing.

I'm pretty sure that I'm just a normal user and my process doesn't have CAP_DAC_OVERRIDE; why doesn't the second pread() return any error?

My guess is, when doing read/write, kernel only check file permission on open file description, which is created with open(), and don't change even I changed the file permission on the underlying filesystem.

Is my guess correct?

Extra question:

  • If I'm right about this, then how about mmaped regions?

  • Do kernel only check permissions recorded in page table when I
    read/write/execute that mmaped region?

  • Is that true inode data stored in filesystem is only used when
    creating open file description and mmap region?

Best Answer

Yes, permissions are only checked at open time and recorded. So you can't write to a file descriptor that you opened for read-only access regardless of if you are potentially able to write to the file.

The kernel consults in-memory inodes rather than the ones stored in the filesystem. They differ in the reference count for open files, and mount points get the inode of the mounted file.

If I'm right about this, then how about mmaped regions?

Same. (PROT_* flags passed to mmap() equivalent to O_RDWR / O_RDONLY / O_WRONLY flags passed to open()).

Do kernel only check permissions recorded in page table when I read/write/excute that mmaped region?

I'm not sure when else it could check permissions recorded in the page table :-). As far as I understand your question: yes.

Is that true inode data stored in filesystem is only used when creating open file description and mmap region?

Inode permissions are also checked for metadata operations, e.g. mkdir() (and similarly open() with O_CREAT).

And don't forget chdir(), which is different from any open() call. (Or at least, it is different from any open() call on current Linux).

I'm not sure about SELinux-specific permissions.

Related Question