linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Brauner <brauner@kernel.org>
To: Daniel Xu <dxu@dxuuu.xyz>
Cc: viro@zeniv.linux.org.uk, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: Odd interaction with file capabilities and procfs files
Date: Thu, 20 Oct 2022 09:44:40 +0200	[thread overview]
Message-ID: <20221020074440.zdw7gbdjhl4o6z7r@wittgenstein> (raw)
In-Reply-To: <6ddd00bd-87d9-484e-8f2a-06f15a75a4df@app.fastmail.com>

On Wed, Oct 19, 2022 at 03:42:42PM -0600, Daniel Xu wrote:
> Hi Christian,
> 
> On Wed, Oct 19, 2022, at 7:22 AM, Christian Brauner wrote:
> > On Tue, Oct 18, 2022 at 06:42:04PM -0600, Daniel Xu wrote:
> >> Hi,
> >> 
> >> (Going off get_maintainers.pl for fs/namei.c here)
> >> 
> >> I'm seeing some weird interactions with file capabilities and S_IRUSR
> >> procfs files. Best I can tell it doesn't occur with real files on my btrfs
> >> home partition.
> >> 
> >> Test program:
> >> 
> >>         #include <fcntl.h>
> >>         #include <stdio.h>
> >>         
> >>         int main()
> >>         {
> >>                 int fd = open("/proc/self/auxv", O_RDONLY);
> >>                 if (fd < 0) {
> >>                         perror("open");
> >>                         return 1;
> >>                 }
> >>        
> >>                 printf("ok\n");
> >>                 return 0;
> >>         }
> >> 
> >> Steps to reproduce:
> >> 
> >>         $ gcc main.c
> >>         $ ./a.out
> >>         ok
> >>         $ sudo setcap "cap_net_admin,cap_sys_admin+p" a.out
> >>         $ ./a.out
> >>         open: Permission denied
> >> 
> >> It's not obvious why this happens, even after spending a few hours
> >> going through the standard documentation and kernel code. It's
> >> intuitively odd b/c you'd think adding capabilities to the permitted
> >> set wouldn't affect functionality.
> >> 
> >> Best I could tell the -EACCES error occurs in the fallthrough codepath
> >> inside generic_permission().
> >> 
> >> Sorry if this is something dumb or obvious.
> >
> > Hey Daniel,
> >
> > No, this is neither dumb nor obvious. :)
> >
> > Basically, if you set fscaps then /proc/self/auxv will be owned by
> > root:root. You can verify this:
> >
> > #include <fcntl.h>
> > #include <sys/types.h>
> > #include <sys/stat.h>
> > #include <stdio.h>
> > #include <errno.h>
> > #include <unistd.h>
> >
> > int main()
> > {
> >         struct stat st;
> >         printf("%d | %d\n", getuid(), geteuid());
> >
> >         if (stat("/proc/self/auxv", &st)) {
> >                 fprintf(stderr, "stat: %d - %m\n", errno);
> >                 return 1;
> >         }
> >         printf("stat: %d | %d\n", st.st_uid, st.st_gid);
> >
> >         int fd = open("/proc/self/auxv", O_RDONLY);
> >         if (fd < 0) {
> >                 fprintf(stderr, "open: %d - %m\n", errno);
> >                 return 1;
> >         }
> >
> >         printf("ok\n");
> >         return 0;
> > }
> >
> > $ ./a.out
> > 1000 | 1000
> > stat: 1000 | 1000
> > ok
> > $ sudo setcap "cap_net_admin,cap_sys_admin+p" a.out
> > $ ./a.out
> > 1000 | 1000
> > stat: 0 | 0
> > open: 13 - Permission denied
> >
> > So acl_permission_check() fails and returns -EACCESS which will cause
> > generic_permission() to rely on capable_wrt_inode_uidgid() which checks
> > for CAP_DAC_READ_SEARCH which you don't have as an unprivileged user.
> 
> Thanks for checking on this.
> 
> That does explain explain the weirdness but at the expense of another
> question: why do fscaps cause /proc/self/auxv to be owned by root?
> Is that the correct semantics? This also seems rather unexpected.
> 
> I'll take a look tonight and see if I can come up with any answers.

Sorry I didn't explain this in more detail.
You mostly uncovered the reasons as evidenced by the Twitter thread.

Yes, this is expected. When a new process that gains privileges during
exec the kernel will make it non-dumpable. That includes changing of the
e{g,u}id or fs{g,u}id of the process, s{g,u}id binary execution that
results in changed e{g,u}id, or if the executed binary has fscaps set if
the new permitted caps aren't a subset of the currently permitted caps.

The last reason is what causes your sample program's /proc/self to be
owned by root. The culprit here is cred_cap_issubset() which is called
during commit_creds() in begin_new_exec().

If the dumpable attribute is set then all files in /proc/<pid> will be
owned by (userns) root. To get the full picture you'd need to at least
read man proc(5), man execve(2), and man prctl(2).

The reason behind the dumpability change is to prevent unprivileged user
to make privilege-elevating-binaries (e.g., s{g,u}id binaries) crash to
produce (userns-)root-owned coredumps which can be used in exploits. A
fairly recent example of this is e.g.,
https://alephsecurity.com/2021/10/20/sudump/
https://www.openwall.com/lists/oss-security/2021/10/20/2

  reply	other threads:[~2022-10-20  7:45 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-19  0:42 Odd interaction with file capabilities and procfs files Daniel Xu
2022-10-19 13:22 ` Christian Brauner
2022-10-19 21:42   ` Daniel Xu
2022-10-20  7:44     ` Christian Brauner [this message]
2022-10-20 21:35       ` Daniel Xu

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=20221020074440.zdw7gbdjhl4o6z7r@wittgenstein \
    --to=brauner@kernel.org \
    --cc=dxu@dxuuu.xyz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /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;
as well as URLs for NNTP newsgroup(s).