linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dirk Steinmetz <public@rsjtdrjgfuzkfg.com>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Dirk Steinmetz <public@rsjtdrjgfuzkfg.com>
Subject: [PATCH] namei: permit linking with CAP_FOWNER in userns
Date: Tue, 20 Oct 2015 16:09:19 +0200	[thread overview]
Message-ID: <1445350159-5489-1-git-send-email-public@rsjtdrjgfuzkfg.com> (raw)
In-Reply-To: <1444489163-24266-1-git-send-email-public@rsjtdrjgfuzkfg.com>

Attempting to hardlink to an unsafe file (e.g. a setuid binary) from
within an unprivileged user namespace fails, even if CAP_FOWNER is held
within the namespace. This may cause various failures, such as a gentoo
installation within a lxc container failing to build and install specific
packages.

This change permits hardlinking of files owned by mapped uids, if
CAP_FOWNER is held for that namespace. Furthermore, it improves consistency
by using the existing inode_owner_or_capable(), which is aware of
namespaced capabilities as of 23adbe12ef7d3 ("fs,userns: Change
inode_capable to capable_wrt_inode_uidgid").

Signed-off-by: Dirk Steinmetz <public@rsjtdrjgfuzkfg.com>
---
This is the third time I'm sending the patch, as the first two attempts did
not provoke a reply. Feel free to point out any issues you see with it --
including formal requirements, as this is the first patch I'm submitting.
I'd really appreciate your time.

Maybe a bit of rationale behind it would be helpful as well: some linux
distributions, especially gentoo in which I discovered the behaviour,
rely on root being able to hardlink arbitrary files. In the case of gentoo,
this happens when building and installing 'man': the built binary has the
suid-flag set and is owned by a user 'man'. The installation script
(running as root) then attempts to insert a hardlink towards that binary.

Thanks to user namespaces, a regular user can use subuids to create a user
namespace, and acquire root-like capabilities within said namespace. It is
then possible to install and use arbitrary linux distributions within such
namespaces. When installing gentoo in that manner, building and installing
'man' fails, as may_linkat checks the capabilities in the init namespace,
where the installation process is owned by a regular user.

In my opinion may_linkat should permit linking in this case, as the file to
link to is owned by one of the regular user's mapped subids. Note that, in
the scenario described above, it is already possible to create the hardlink
through other means (the following listing is from an unprivileged user
namespace):
> # cat /proc/$$/status | grep CapEff
> CapEff:	0000003cfdfeffff
> # ls -l
> total 0
> -rwSr--r-- 1 nobody nobody 0 Oct 20 15:40 file
> # ln file link
> ln: failed to create hard link 'link' => 'file': Operation not permitted
> # su nobody -s /bin/bash -c "ln file link"
> # ls -l
> total 0
> -rwSr--r-- 2 nobody nobody 0 Oct 20 15:40 file
> -rwSr--r-- 2 nobody nobody 0 Oct 20 15:40 link
As you can see, the process has CAP_FOWNER in the namespace, but cannot
hardlink the file owned by 'nobody'. It can, however, use su to switch to
'nobody' and then create the link. After applying this patch, linking
works as expected.

Diffstat:
 fs/namei.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 33e9495..0d3340b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -955,26 +955,23 @@ static bool safe_hardlink_source(struct inode *inode)
  *  - sysctl_protected_hardlinks enabled
  *  - fsuid does not match inode
  *  - hardlink source is unsafe (see safe_hardlink_source() above)
- *  - not CAP_FOWNER
+ *  - not CAP_FOWNER in a namespace with the inode owner uid mapped
  *
  * Returns 0 if successful, -ve on error.
  */
 static int may_linkat(struct path *link)
 {
-	const struct cred *cred;
 	struct inode *inode;
 
 	if (!sysctl_protected_hardlinks)
 		return 0;
 
-	cred = current_cred();
 	inode = link->dentry->d_inode;
 
 	/* Source inode owner (or CAP_FOWNER) can hardlink all they like,
 	 * otherwise, it must be a safe source.
 	 */
-	if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(inode) ||
-	    capable(CAP_FOWNER))
+	if (inode_owner_or_capable(inode) || safe_hardlink_source(inode))
 		return 0;
 
 	audit_log_link_denied("linkat", link);
-- 
2.1.4


  reply	other threads:[~2015-10-20 14:10 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-10 14:59 [PATCH] namei: permit linking with CAP_FOWNER in userns Dirk Steinmetz
2015-10-20 14:09 ` Dirk Steinmetz [this message]
2015-10-27 14:33   ` Seth Forshee
2015-10-27 18:08     ` Dirk Steinmetz
2015-10-27 20:28       ` Serge Hallyn
2015-10-28 15:07         ` Dirk Steinmetz
2015-10-28 17:33           ` Serge Hallyn
2015-11-02 15:10             ` Dirk Steinmetz
2015-11-02 18:02               ` Serge Hallyn
2015-11-02 19:57                 ` Andy Lutomirski
2015-11-03  0:39                   ` [RFC] namei: prevent sgid-hardlinks for unmapped gids Dirk Steinmetz
2015-11-03 15:44                     ` Serge Hallyn
2015-11-03 18:20                     ` Kees Cook
2015-11-03 23:21                       ` Dirk Steinmetz
2015-11-03 23:29                         ` Kees Cook
2015-11-04  6:58                           ` Willy Tarreau
2015-11-04 17:59                             ` Andy Lutomirski
2015-11-04 18:15                               ` Willy Tarreau
2015-11-04 18:17                                 ` Andy Lutomirski
2015-11-04 18:28                                   ` Willy Tarreau
2015-11-06 21:59                               ` Kees Cook
2015-11-06 22:30                                 ` Andy Lutomirski
2015-11-07  0:11                                   ` Kees Cook
2015-11-07  0:16                                     ` Kees Cook
2015-11-07  0:48                                       ` Andy Lutomirski
2015-11-07  5:05                                         ` Kees Cook
2015-11-08  2:02                                           ` Theodore Ts'o
2015-11-10 15:08                                             ` Jan Kara
2015-11-19 20:11                                               ` Kees Cook
2015-11-19 21:57                                                 ` Andy Lutomirski
2015-11-19 22:02                                                 ` Dave Chinner
2015-11-20  0:11                                                   ` Kees Cook
2015-11-04 14:46                       ` Serge E. Hallyn
2015-10-27 21:04     ` [PATCH] namei: permit linking with CAP_FOWNER in userns Eric W. Biederman
2015-11-03 17:51 ` Kees Cook

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=1445350159-5489-1-git-send-email-public@rsjtdrjgfuzkfg.com \
    --to=public@rsjtdrjgfuzkfg.com \
    --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).