public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: daw@cs.berkeley.edu (David Wagner)
To: linux-kernel@vger.kernel.org
Subject: Re: Why can setuid programs regain root after dropping it when using capabilities?
Date: Sat, 31 Dec 2005 20:58:50 +0000 (UTC)	[thread overview]
Message-ID: <dp6rea$kdh$1@taverner.CS.Berkeley.EDU> (raw)
In-Reply-To: 20051129213545.6154ce37@TANG-FOUR-EIGHTY-ONE.MIT.EDU

David Chau  wrote:
>While debugging some code, I found that a setuid program could regain
>root after dropping root if the program used capabilities. (I tested
>this on 2.6.14 and 2.6.9.) Is this the expected behavior? Here's a
>short test case:
>
>/* chown root this program, suid it, and run it as non-root */
>#include <sys/types.h>
>#include <sys/capability.h>
>#include <unistd.h>
>#include <stdio.h>
>int main() {
>   cap_set_proc(cap_from_text("all-eip")); /* drop all caps */
>   setuid(getuid());                       /* drop root. this call succeeds */
>   setuid(0);                              /* this should fail! but doesn't */
>   printf("%d\n", geteuid());              /* we regained root. prints 0 */
>   return 0;
>}
>
>(If we don't use capabilities at all, and take out the cap_set_proc
>line, then the program behaves as expected, and doesn't allow us to
>regain root.)

Yup, that does seem weird, indeed.  The semantics of uid syscalls is
already weird, and when you introduce POSIX capabilities, they get
even weirder.  What is going on here is that setuid(getuid()) will only
modify the saved uid if CAP_SETUID is enabled.  Normally, CAP_SETUID is
enabled if and only if the effective uid is zero.  However, dropping all
capabilities changes this, and consequently your attempt to drop root
still leaves suid==0, which is what enables the subsequent setuid(0)
to succeed.  You can confirm this by reading the source code, which
can be found in kernel/sys.c:sys_setuid().

Nonetheless, even though I can explain what the OS is doing, I can't
explain why it is doing that.  I have no idea why someone decided
that setuid() should leave the saved uid unmodified if CAP_SETUID is
not present.

My recommendation: Use sys_setresuid().  It has by far the most
intuitive semantics, and POSIX capabilities don't trigger any surprising
modifications to its behavior.

  reply	other threads:[~2005-12-31 20:59 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-11-30  2:35 Why can setuid programs regain root after dropping it when using capabilities? David Chau
2005-12-31 20:58 ` David Wagner [this message]
2006-01-01 15:26   ` Jan Engelhardt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='dp6rea$kdh$1@taverner.CS.Berkeley.EDU' \
    --to=daw@cs.berkeley.edu \
    --cc=daw-usenet@taverner.CS.Berkeley.EDU \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox