file capabilities: don't prevent signaling setuid root programs
authorSerge E. Hallyn <[email protected]>
Thu, 29 Nov 2007 00:21:47 +0000 (16:21 -0800)
committerLinus Torvalds <[email protected]>
Thu, 29 Nov 2007 17:24:53 +0000 (09:24 -0800)
An unprivileged process must be able to kill a setuid root program started
by the same user.  This is legacy behavior needed for instance for xinit to
kill X when the window manager exits.

When an unprivileged user runs a setuid root program in !SECURE_NOROOT
mode, fP, fI, and fE are set full on, so pP' and pE' are full on.  Then
cap_task_kill() prevents the user from signaling the setuid root task.
This is a change in behavior compared to when
!CONFIG_SECURITY_FILE_CAPABILITIES.

This patch introduces a special check into cap_task_kill() just to check
whether a non-root user is signaling a setuid root program started by the
same user.  If so, then signal is allowed.

Signed-off-by: Serge E. Hallyn <[email protected]>
Cc: Andrew Morgan <[email protected]>
Cc: Stephen Smalley <[email protected]>
Cc: Chris Wright <[email protected]>
Cc: James Morris <[email protected]>
Cc: Casey Schaufler <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
security/commoncap.c

index 302e8d0839a9c7afaacff955e4a67874192117be..5bc1895f3f9ce0997afbf59448ad0053cb4aa56b 100644 (file)
@@ -526,6 +526,15 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,
        if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
                return 0;
 
+       /*
+        * Running a setuid root program raises your capabilities.
+        * Killing your own setuid root processes was previously
+        * allowed.
+        * We must preserve legacy signal behavior in this case.
+        */
+       if (p->euid == 0 && p->uid == current->uid)
+               return 0;
+
        /* sigcont is permitted within same session */
        if (sig == SIGCONT && (task_session_nr(current) == task_session_nr(p)))
                return 0;