aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorDirk Steinmetz <public@rsjtdrjgfuzkfg.com>2015-10-20 10:09:19 -0400
committerEric W. Biederman <ebiederm@xmission.com>2015-10-27 17:12:35 -0400
commitf2ca379642d7a843be972ea4167abdd3c8c9e5d1 (patch)
tree03d03e85a7e38cb732fe09d2ca85baec3bc815d5 /fs/namei.c
parent6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff)
namei: permit linking with CAP_FOWNER in userns
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 hitting us in Ubuntu during some dpkg upgrades in containers. When upgrading a file dpkg creates a hard link to the old file to back it up before overwriting it. When packages upgrade suid files owned by a non-root user the link isn't permitted, and the package upgrade fails. This patch fixes our problem. Tested-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c7
1 files changed, 2 insertions, 5 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 726d211db484..29fc6a657477 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -955,26 +955,23 @@ static bool safe_hardlink_source(struct inode *inode)
955 * - sysctl_protected_hardlinks enabled 955 * - sysctl_protected_hardlinks enabled
956 * - fsuid does not match inode 956 * - fsuid does not match inode
957 * - hardlink source is unsafe (see safe_hardlink_source() above) 957 * - hardlink source is unsafe (see safe_hardlink_source() above)
958 * - not CAP_FOWNER 958 * - not CAP_FOWNER in a namespace with the inode owner uid mapped
959 * 959 *
960 * Returns 0 if successful, -ve on error. 960 * Returns 0 if successful, -ve on error.
961 */ 961 */
962static int may_linkat(struct path *link) 962static int may_linkat(struct path *link)
963{ 963{
964 const struct cred *cred;
965 struct inode *inode; 964 struct inode *inode;
966 965
967 if (!sysctl_protected_hardlinks) 966 if (!sysctl_protected_hardlinks)
968 return 0; 967 return 0;
969 968
970 cred = current_cred();
971 inode = link->dentry->d_inode; 969 inode = link->dentry->d_inode;
972 970
973 /* Source inode owner (or CAP_FOWNER) can hardlink all they like, 971 /* Source inode owner (or CAP_FOWNER) can hardlink all they like,
974 * otherwise, it must be a safe source. 972 * otherwise, it must be a safe source.
975 */ 973 */
976 if (uid_eq(cred->fsuid, inode->i_uid) || safe_hardlink_source(inode) || 974 if (inode_owner_or_capable(inode) || safe_hardlink_source(inode))
977 capable(CAP_FOWNER))
978 return 0; 975 return 0;
979 976
980 audit_log_link_denied("linkat", link); 977 audit_log_link_denied("linkat", link);