From 9d2a7b1f6276df2f90fa79353b27e285d60d572d Mon Sep 17 00:00:00 2001 From: Michael Kerrisk Date: Fri, 20 May 2005 12:11:25 +0000 Subject: [PATCH] Noted F_SETOWN bug for socket file descriptor in Linux 2.4 and earlier. Added text on permissions required to send signal to owner. ==== Hello Johannes, > Betreff: Inaccuracy of fcntl man page > Datum: Mon, 2 May 2005 20:07:12 +0200 Thanks for yor note. Sorry for the delay in getting back to you. I needed to find time to set aside to look at the details. Now I've finally got there. > I have attached a simple program Thanks -- a little program is always helpful. > that uses the fcntl system call in order > to kill an arbitrary process of the same user. > According to the fcntl man page, fcntl(fd,F_SETOWN,pid) returns zero if > it has success. Yes. > If you strace the program while killing for exampe man running in another > terminal, you will see that man is killed, but fcntl(fd,F_SETOWN,pid) > will return EPERM, I confirm that I see this problem in 2.4, with both Unix domain and Internet domain sockets. > where you can only find a very confusing explanation > in the fcntl man page. I'm not sure what explanation you mean here. As far as I can tell, the manual page just doesn't cover this point. > I have looked into the kernel source of 2.4.30 and found out, that > net/core/socket::sock_no_fcntl is the culprit if you use fcntl on Unix > sockets. Yes, looks that way to me, as well, And the 2.2 code looks similar. > If pid is not your own pid or not your own process group, > the system call will return EPERM but will also set the pid > as you wanted to. Yes. > In the 2.6 kernel line, fcntl will react according the specification in > the manual page. Yes. > If you also think, that one should clarify the return specification of > fcntl(fd,F_SETOWN,pid) or 2.4.x kernels, please tell me and I will > provide you with a patch for the manual page. In fact I've written some new text under BUGS, which describes the problem: In Linux 2.4 and earlier, there is bug that can occur when an unprivileged process uses F_SETOWN to specify the owner of a socket file descriptor as a process (group) other than the caller. In this case, fcntl() can return -1 with errno set to EPERM, even when the owner process (group) is one that the caller has permission to send signals to. Despite this error return, the file descriptor owner is set, and signals will be sent to the owner. Does that seem okay to you? > Furthermore, it would be interseting to write there, what permissions > one need in order to send signals to processes via fcntl Good idea. I added the following new text: Sending a signal to the owner process (group) specified by F_SETOWN is subject to the same permissions checks as are described for kill(2), where the sending process is the one that employs F_SETOWN (but see BUGS below). ==== #define _GNU_SOURCE /* needed to get the defines */ #include /* in glibc 2.2 this has the needed values defined */ #include #include #include #include #include #include /** * Funnykill kills a program with fcntl **/ int main (int argc, char **argv) { if (argc != 2) { fprintf (stderr, "Usage: funnykill \n"); return 1; } int sockets[2]; socketpair (AF_UNIX, SOCK_STREAM, 0, sockets); if (fcntl (sockets[0], F_SETFL, O_ASYNC | O_NONBLOCK) == -1) errMsg("fcntl-F_SETFL"); if (fcntl (sockets[0], F_SETOWN, atoi (argv[1])) == -1) errMsg("fcntl-F_SETOWN"); // fcntl (sockets[0], F_SETOWN, getpid()); if (fcntl (sockets[0], F_SETSIG, SIGKILL) == -1) errMsg("fcntl-_FSETSIG"); write (sockets[1], "good bye", 9); } --- man2/fcntl.2 | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/man2/fcntl.2 b/man2/fcntl.2 index 43dc92f9a..4b066d79d 100644 --- a/man2/fcntl.2 +++ b/man2/fcntl.2 @@ -49,6 +49,9 @@ .\" Described behaviour of F_SETOWN/F_SETSIG in .\" multi-threaded processes, and generally cleaned .\" up the discussion of F_SETOWN. +.\" 2005-05-20, Johannes Nicolai , +.\" mtk: Noted F_SETOWN bug for socket file descriptor in Linux 2.4 +.\" and earlier. Added text on permissions required to send signal. .\" .TH FCNTL 2 2004-12-08 "Linux 2.6.9" "Linux Programmer's Manual" .SH NAME @@ -347,6 +350,11 @@ and SIGURG signals for events on file descriptor .IR fd . A process ID is specified as a positive value; a process group ID is specified as a negative value. +Most commonly, the calling process specifies itself as the owner +(that is, +.I arg +is specified as +.IR getpid ()). .\" From glibc.info: If you set the @@ -362,6 +370,16 @@ a SIGIO signal is sent whenever input or output becomes possible on that file descriptor. .B F_SETSIG can be used to obtain delivery of a signal other than SIGIO. +If this permission check fails, then the signal is +silently discarded. + +Sending a signal to the owner process (group) specified by +.B F_SETOWN +is subject to the same permissions checks as are described for +.BR kill (2), +where the sending process is the one that employs +.BR F_SETOWN +(but see BUGS below). .sp If the file descriptor .I fd @@ -816,6 +834,23 @@ will contain the (positive) process group ID. .\" indicate that ANY negative PGID value will cause F_GETOWN .\" to misinterpret the return as an error. Some other architectures .\" seem to have the same range check as x86. -- MTK + +In Linux 2.4 and earlier, there is bug that can occur +when an unprivileged process uses +.B F_SETOWN +to specify the owner +of a socket file descriptor +as a process (group) other than the caller. +In this case, +.BR fcntl () +can return \-1 with +.I errno +set to +.BR EPERM , +even when the owner process (group) is one that the caller +has permission to send signals to. +Despite this error return, the file descriptor owner is set, +and signals will be sent to the owner. .SH "CONFORMING TO" SVr4, SVID, POSIX, X/OPEN, BSD 4.3. Only the operations F_DUPFD, F_GETFD, F_SETFD, F_GETFL, F_SETFL, F_GETLK, F_SETLK, F_SETLKW,