Can I get UNIX file permissions to take effect immediately for all processes?
The kernel doesn't check permissions on file descriptions. They can even be duplicated to other processes that never had access to the original file by fd passing.
The only thing I think you could try would be to manually find out processess with open file descriptors, and pull a sneaky trick to close them1. There's an example of such a "sneaky trick" is to attach a debugger (gdb
) and use that to close the fd.
This is a very extreme thing to do. There's no way to know how a process will behave if it's FD is suddenly closed. In some cases processes may have a file mapped to memory so if you manage to close the file and you managed to remove any memory mapping without the processes expecting it would crash on a segmentation fault.
Much better would be to find which processes are using a file and manually kill them. At least that way you can ask them to shutdown nicely and not corrupt other data.
1 as mentioned in comments, the best shot of making this work would be to call dup2
rather than close
to change the fd to point to /dev/null
instead of the original file. This is because the code won't expect it to have closed and may do some very weird and insecure things when the fd (number) gets recycled.
You can't invalidate the existing file descriptors, except through "sneaky tricks" like those mentioned by Philip Couling. However, you can achieve a similar effect in a (reasonably) portable way.
Let's say that you want to prevent processes that already have foo
open from continuing to write to foo
. What you can do is: cp foo foo2; chmod -w foo2; mv foo2 foo
. Now any processes that had the old foo
open will continue writing to this file, which is no longer known as foo
(has one fewer hard link than before). None of these processes can affect the new foo
, since they cannot open it for writing.
If you want to prevent reading, a similar strategy is cp foo foo2; chmod -r foo2; truncate foo; mv foo2 foo
. Here, the old foo
is truncated in-place (i.e., reduced to zero size without being deleted) so the processes that had foo
open will see no content the next time they attempt to read from it, and they can't open the new foo
. However, this is not guaranteed to work, since if any processes had mmap
ed foo
, then it's unspecified whether the truncation actually affects those mappings.
That is a super-interesting question, and researching it actually provided more fun for a Sunday than watching Netflix :-)
- as other answers have answered, not within posix
- dirty tricks: YMMV, and i am pretty sure that the debugger trick needs to be expanded by unmapping the files (and holy cow, that is evil. File descriptors getting invalid between one system call and another is not nice, but portions of data structures vanishing is impossible to deal with).
- Under Linux: If you look at https://upload.wikimedia.org/wikipedia/commons/f/fb/The_Linux_Storage_Stack_Diagram.svg actually implementing what you suggest in all generality would require you to look up the page cache position for the inodes and personally hunt these down by means unknown (otherwise already mapped memory is still there, without a system call.). (Remark: probably not possible to do it reliably in userspace without locking the access to the page cache and or preventing forking of your process)
- you could (linux) try to use mandatory locking mount options + flock, but I am not sure that you can "steal" the lock
That means:
- we don't like memory mapping
- we don't like to meddle below the FS layer
Depending on your use case I see other possibilities:
- Implement an overlay filesystem. That prevents mapping, and you can filter the calls - should be actually not complicated.
- Use a network file system to do similar things
- And most important: Organize the access to the file via a server process (essentially the same as "implement an overlay file system, but portable" :-))