From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dirk Steinmetz Subject: [PATCH] namei: permit linking with CAP_FOWNER in userns Date: Wed, 30 Sep 2015 02:05:46 +0200 Message-ID: <20150930020546.48aeb78b@pc-dirk.ip> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit To: Alexander Viro , linux-fsdevel@vger.kernel.org Return-path: Received: from mxf912.netcup.net ([46.38.249.18]:43166 "EHLO mxf912.netcup.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751072AbbI3ANW (ORCPT ); Tue, 29 Sep 2015 20:13:22 -0400 Sender: linux-fsdevel-owner@vger.kernel.org List-ID: 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 --- fs/namei.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 726d211..29fc6a6 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