2

When a process successfully get an fd using open(flags=O_RDWR), it will be able to read/write to that file as long as the fd isn't closed (Regular file on local filesystem), even if some other process use chmod to cancel the read/write permission for the corresponding user. Does Linux kernel check file permissions on inode or open file description? But how about when the process try to execute that file using execveat, will the kernel read the disk to check the x bit and suid bit permission? What kind of permissions are recorded in open file description, does it contain a full ACL or simply readable/writable bit so every operation else(execveat, fchdir, fchmod, etc) will check the on-disk info?

What if I transfer this fd to another process of another whose fsuid doesn't have read/write/execute bit on that file(according to the on-disk filesystem info), will that receiver process be able to read/write/execute the file through the fd?

  • Just trying it out tells me that it will fail "Permission denied", which doesn't answer the rest of the question. – Michael Homer Jun 21 at 6:23
4

execveat is handled by do_open_execat, which specifies that it wants to be able to open the target file for execution. The file opening procedure is handled via do_filp_open and path_openat, with a path-walking process which is documented separately. The result of all this, regardless of how the process starts, is a struct file and its associated struct inode which stores the file’s mode and, if relevant, a point to the ACLs. The inode data structure is shared by all the file descriptions which reference the same inode.

The kernel guarantees that the inode information in memory is up-to-date when retrieved. This can be maintained in the dentry and inode caches in some cases (local file systems, ext4, ext3, XFS, and btrfs in particular), in others it will involve some I/O (in particular over the network).

The permission check itself is performed a little later, by bprm_fill_uid; that takes into account the current permissions on the inode, and the current privileges of the calling user.

As discussed previously, permissions are only verified when a file is opened, mapped, or its metadata altered, not when it’s read or written; so file descriptors can be passed across processes without new permission checks.

  • unix.stackexchange.com/questions/491991/… Then why do I still able to read the file after chmod(it's ext4 or btrfs, not ext3 or xfs)? It really confused me, seems the cached inode data is outdated after on-disk info changing. It seems like all the permission check is only done on the cached inode in memory only, without any disk reading. But if I'm right, wouldn't that be dangerous because cached inode can be outdated. That's the whole point of my question. – 炸鱼薯条德里克 Jun 21 at 11:18
  • ext4 and btrfs have the same caching behaviour as ext3 and XFS. Permissions are checked when a file is opened, as explained in answer to your other question, so if you open a file and then chmod it, you can still read it. Changing permissions goes through the kernel too, and that updates the cached inode as well as the inode on disk. – Stephen Kitt Jun 21 at 11:39
  • I think I misunderstood your question. I read the first sentence as being a statement of fact, not part of the question; I thought that the focus of your question was the exec behaviour. – Stephen Kitt Jun 21 at 11:39
  • Although read/write doesn't do permission check on inode. The permission check process seems to happen not just when creating struct file, I think fchmod, fchdir, mmap(prot=PROT_EXEC) also do permission check without creating new ofdtion. Does this permission check happened on the cached inode of the passed fd or on-disk inode? – 炸鱼薯条德里克 Jun 21 at 12:46
1

What kind of permissions are recorded in open file description, does it contain a full ACL

No. No "permissions" are kept in the "open file description" (struct file) beyond the file access modes and the file status flags which could be retrieved with fcntl(F_GETFL) or via /proc/PID/fdinfo/FD. All the file permissions are held in the struct inode referenced from there (and which is shared between all the processes/users which have that particular file open). A struct file also holds a reference to the opener's credentials.

will that receiver process be able to read/write/execute the file through the fd?

If you're asking about execveat(fd, "", av, env, AT_EMPTY_PATH) that is only using the file descriptor as pointer to the inode, and everything will be checked just as if the file referenced was executed via its path. The flags of fd don't matter a bit; the file descriptor could be an opaque handle opened with O_PATH ( something that will succeed with any file accessible via some path).

  • 1 Uh… I'm also asking about read/write from the receiver process… Because I want to ask some privileged process to offer me a O_RDWR fd(using Unix domain sockets), although I don't have privilege to open that file by myself. 2 What about mmap(prot=PROT_EXEC), will it do some permission check on the cached inode using the current calling process's credential or the f_cred of the passed ofdtion? – 炸鱼薯条德里克 Jun 21 at 13:04
  • 1
    2. mmap(PROT_EXEC) only cares about about the fd and the inode it's referencing being readable. It doesn't have to be executable, and being executable but not readable will not cut it. We've already discussed that -- try it if you don't believe me. – mosvy Jun 21 at 13:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.