Bug 79771 - One cannot reopen a socket through /proc/self/fd
Summary: One cannot reopen a socket through /proc/self/fd
Status: NEW
Alias: None
Product: Other
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: other_other
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-10 04:23 UTC by Steven Stewart-Gallus
Modified: 2014-08-21 18:34 UTC (History)
2 users (show)

See Also:
Kernel Version: 3.13.0
Subsystem:
Regression: No
Bisected commit-id:


Attachments
A test case showing how one cannot reopen sockets through /proc/sel/fd (978 bytes, text/x-csrc)
2014-07-10 04:23 UTC, Steven Stewart-Gallus
Details

Description Steven Stewart-Gallus 2014-07-10 04:23:14 UTC
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.
Comment 1 Alexey Dobriyan 2014-07-10 13:27:18 UTC
can't even reopen /dev/null
Comment 2 Alexey Dobriyan 2014-07-10 14:32:52 UTC
> 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;
}
Comment 3 Steven Stewart-Gallus 2014-07-11 18:56:01 UTC
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?
Comment 4 Alexey Dobriyan 2014-07-14 11:18:25 UTC
"Back door" refers to /proc/$PID/fd directory where sockets show up as well.
Comment 5 Alexey Dobriyan 2014-07-14 19:25:23 UTC
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.
Comment 6 Steven Stewart-Gallus 2014-08-12 04:26:02 UTC
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.
Comment 7 Andrey Utkin 2014-08-12 10:05:52 UTC
(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.
Comment 8 Steven Stewart-Gallus 2014-08-13 01:40:27 UTC
Do you think reopening file descriptors through /proc/self/fd is strange or that unsharing file descriptions from file descriptors is strange?
Comment 9 Andrey Utkin 2014-08-13 08:33:50 UTC
I don't get what profit both may give to application, which wouldn't be achievable without it.
Comment 10 Steven Stewart-Gallus 2014-08-13 19:02:08 UTC
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.
Comment 11 Steven Stewart-Gallus 2014-08-13 19:09:15 UTC
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.
Comment 12 Steven Stewart-Gallus 2014-08-13 19:22:41 UTC
Nope, my connect workaround doesn't work properly.
Comment 13 Steven Stewart-Gallus 2014-08-21 18:34:05 UTC
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.

Note You need to log in before you can comment on or make changes to this bug.