Created attachment 142641 [details] A test case showing how one cannot reopen sockets through /proc/sel/fd Reopening files through /proc/self/fd is needed to unshare file descriptions of file descriptors from other processes. This is nice because it lets one prevent other processes from messing with one's own file descriptions and causing incorrect behaviour. It is important that one can do this generically and with any file so that every file passed in at startup can be sanitized in a uniform and simple way. A test case is attached.
can't even reopen /dev/null
> can't even reopen /dev/null ehh, disregard this --------- /* * In theory you can't get an open on this inode, but /proc provides * a back door. Remember to keep it shut otherwise you'll let the * creepy crawlies in. */ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) { return -ENXIO; }
That comment seems to imply that it is a security problem to let people reopen sockets through /proc/self/fd. Is reopening sockets through /proc/self/fd actually a security issue or were the writers of the code just worried that if implemented improperly there could be a security issue and so didn't want to implement the functionality hastily?
"Back door" refers to /proc/$PID/fd directory where sockets show up as well.
I guess the problem is that sockets are more complex beasts than plain files, and simply reopening them is not going to work, you need to connect() or bind() or something like that.
There are three objects associated with an open handle to a file in a process: the file descriptor, the file description and the file itself. Operations such as dup, or fork share file descriptions between file descriptors and not just files. File description state includes the current file offset, nonblocking status and more. Because I don't want different processes in my multiprocess program to interfere with each other I want to unshare file descriptions between file descriptors. In other words, I want a deep_dup function. Currently, to implement that kind of functionality I reopen files through /proc/self/fd. Although, I am not actually 100 percent sure this approach is the correct approach and actually works correctly for all types of files that this seems to work for I sort of think it is the correct approach. I really think it would be simplest if reopening sockets through /proc/self/fd was allowed but if you really think that just reopening sockets won't work then maybe I could ask the mailing lists and lobby for some other kind of support for my use case such as a possible deep_dup system call.
(In reply to Steven Stewart-Gallus from comment #6) > There are three objects associated with an open handle to a file in a > process: the file descriptor, the file description and the file > itself. Operations such as dup, or fork share file descriptions > between file descriptors and not just files. File description state > includes the current file offset, nonblocking status and more. > Because I don't want different processes in my multiprocess program to > interfere with each other I want to unshare file descriptions between > file descriptors. In other words, I want a deep_dup function. IMHO, this request is very strange. I'd think of a way to achieve the desired result with currently available interfaces. I believe that now any legal desire is achievable in userspace.
Do you think reopening file descriptors through /proc/self/fd is strange or that unsharing file descriptions from file descriptors is strange?
I don't get what profit both may give to application, which wouldn't be achievable without it.
You don't see why one might want to unshare file descriptions between file descriptors? But I already explained above! Because I don't want different processes in my multiprocess program to interfere with each other I want to unshare file descriptions between file descriptors. But I'll give you a concrete example. Suppose, I have a file descriptor for a POSIX message queue and I want to pass it to a child to communicate with. For sandboxing purposes, I want the child to only be able to write to it (so I reopen it as write-only) and I don't want the child to be able to change the blocking status of the parent's handle to the message queue. Similar arguments apply for sockets. Suppose I have a parent with two children that creates SEQPACKET communication channel using socketpair. I might want the children to receive two separate file descriptions that don't share blocking status and other file description state so that they are isolated from each other.
Anyways, I have a found a workaround. I can just reconnect to the socket using /proc/self/fd instead of opening it. This means I have to do an fstat to find if the file is a socket and then open or connect to it which is less simple but it's still somewhat reasonable. Now I only have to find a workaround for binding (this bug is sort of related https://bugzilla.kernel.org/show_bug.cgi?id=82271) which is complicated because only one socket can be bound at a time to an end (I think). SO_REUSEADDR and SO_REUSEPORT sort of complicate or help solve this too.
Nope, my connect workaround doesn't work properly.
Okay, I think I'll just have to wait for the inevitable bind2 interface that fixes a bunch of the awkwardness with bind and UNIX sockets before I can solve my problem.