From patchwork Fri Apr 22 15:38:31 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Seth Forshee X-Patchwork-Id: 8913701 Return-Path: X-Original-To: patchwork-selinux@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 055F59F39A for ; Fri, 22 Apr 2016 15:55:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 217852014A for ; Fri, 22 Apr 2016 15:55:25 +0000 (UTC) Received: from emvm-gh1-uea08.nsa.gov (emvm-gh1-uea08.nsa.gov [8.44.101.8]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DE7DA20149 for ; Fri, 22 Apr 2016 15:55:23 +0000 (UTC) X-TM-IMSS-Message-ID: <61c139b800000a78@nsa.gov> Received: from tarius.tycho.ncsc.mil ([144.51.242.1]) by nsa.gov ([10.208.42.193]) with ESMTP (TREND IMSS SMTP Service 7.1) id 61c139b800000a78 ; Fri, 22 Apr 2016 11:50:48 -0400 Received: from prometheus.infosec.tycho.ncsc.mil (prometheus [192.168.25.40]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u3MFpNir008647; Fri, 22 Apr 2016 11:51:23 -0400 Received: from tarius.tycho.ncsc.mil (tarius.infosec.tycho.ncsc.mil [144.51.242.1]) by prometheus.infosec.tycho.ncsc.mil (8.15.2/8.15.2) with ESMTP id u3MFdlf1105308 for ; Fri, 22 Apr 2016 11:39:47 -0400 Received: from goalie.tycho.ncsc.mil (goalie [144.51.242.250]) by tarius.tycho.ncsc.mil (8.14.4/8.14.4) with ESMTP id u3MFdlDT004476 for ; Fri, 22 Apr 2016 11:39:47 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0CqBABlRRpX/yUp0ApeHYJwgXu3d4QQhg4CgXQBAQEBAQFmJ4RCAQEBAxIVGQEBNwEPUTQBBQEcBgESIogIAaBwgTE+MYpPhSgBBIxcAQEBAQEBBAIBFwYKhA2CCo5gAY5LiUiBVYxBiSmFZY1xMIEOYoF4DRsWgVNOAYh6AQEB X-IPAS-Result: A0CqBABlRRpX/yUp0ApeHYJwgXu3d4QQhg4CgXQBAQEBAQFmJ4RCAQEBAxIVGQEBNwEPUTQBBQEcBgESIogIAaBwgTE+MYpPhSgBBIxcAQEBAQEBBAIBFwYKhA2CCo5gAY5LiUiBVYxBiSmFZY1xMIEOYoF4DRsWgVNOAYh6AQEB X-IronPort-AV: E=Sophos;i="5.24,517,1454994000"; d="scan'208";a="5402625" Received: from emsm-gh1-uea11.corp.nsa.gov (HELO emsm-gh1-uea11.nsa.gov) ([10.208.41.37]) by goalie.tycho.ncsc.mil with ESMTP; 22 Apr 2016 11:39:24 -0400 IronPort-PHdr: =?us-ascii?q?9a23=3AcNNzLBF73zBib7zwtR76OZ1GYnF86YWxBRYc798d?= =?us-ascii?q?s5kLTJ74r82wAkXT6L1XgUPTWs2DsrQf27qQ7PirCTBIyK3CmU5BWaQEbwUCh8?= =?us-ascii?q?QSkl5oK+++Imq/EsTXaTcnFt9JTl5v8iLzG0FUHMHjew+a+SXqvnYsExnyfTB4?= =?us-ascii?q?Ov7yUtaLyZ/nh6bto9aDP01hv3mUX/BbFF2OtwLft80b08NJC50a7V/3mEZOYP?= =?us-ascii?q?lc3mhyJFiezF7W78a0+4N/oWwL46pyv+YJa6jxfrw5QLpEF3xmdjltvIy4/SXE?= =?us-ascii?q?GEGi/HoXGlpQ2jBJDgTI9hTzWN255ibwt+dx1TOfFd3zTKsvWDOkqaxsTUmswA?= =?us-ascii?q?4DOi4w9m3akIROjbhc6Ea/pgZ465zZZoCLcv5/eL7NO9QASixcXZAVHwNbD4z0?= =?us-ascii?q?TJEIBupEHe9Cs4z0oRNaogGzCgqsLOfuzCJYiHjr26Ezz+UmF0fBxgN2TPwUt3?= =?us-ascii?q?GBl9jpNO88VvquzKTFhWHYYu9Wnzn68pPIfx0JqviKWrRxesPVj0IoElWW3R2r?= =?us-ascii?q?tYX5MmbNhaw2uG+B4r8lDLr3hg=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A1EiAQCfQhpXj7DWVdFeHYJwgXu3d4QIC?= =?us-ascii?q?BeBdoQBAoF0AQEBAQEBAgIPAQEBAQcLCwkhglx9Wz0BAQEDEhUZAQE3AQ9RNAE?= =?us-ascii?q?FARwGARIiiAgBoGyBMT4xik+FKAEEjF0BAQEBAQEEAgEXBgqEDYIKi1ILQIJDj?= =?us-ascii?q?kyJSIFVjEGJKYVljXEwgQ6CWg0RChaBU04BiHoBAQE?= X-IPAS-Result: =?us-ascii?q?A1EiAQCfQhpXj7DWVdFeHYJwgXu3d4QICBeBdoQBAoF0AQE?= =?us-ascii?q?BAQEBAgIPAQEBAQcLCwkhglx9Wz0BAQEDEhUZAQE3AQ9RNAEFARwGARIiiAgBo?= =?us-ascii?q?GyBMT4xik+FKAEEjF0BAQEBAQEEAgEXBgqEDYIKi1ILQIJDjkyJSIFVjEGJKYV?= =?us-ascii?q?ljXEwgQ6CWg0RChaBU04BiHoBAQE?= X-IronPort-AV: E=Sophos;i="5.24,517,1454976000"; d="scan'208";a="15532495" Received: from emvm-gh1-uea09.nsa.gov ([10.208.42.194]) by emsm-gh1-uea11.nsa.gov with ESMTP/TLS/DHE-RSA-AES256-SHA; 22 Apr 2016 15:39:23 +0000 X-TM-IMSS-Message-ID: Received: from mail-ob0-f176.google.com (mail-ob0-f176.google.com [209.85.214.176]) by nsa.gov ([10.208.42.194]) with ESMTP (TREND IMSS SMTP Service 7.1; TLSv1/SSLv3 AES128-SHA (128/128)) id ad94928e0000063b ; Fri, 22 Apr 2016 11:38:56 -0400 Received: by mail-ob0-f176.google.com with SMTP id tz8so50757040obc.0 for ; Fri, 22 Apr 2016 08:39:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=x2P1/0RD8m9ay9I52eeAoiRAAQIOn3SSJRt3LvafO1I=; b=gFEUvlRL+K86teCbOg8U/SRf8/C9meboQYHIdPemdElHCfO44QoMq7z8yDAALvrozy qhnEUQqb+lAmQEu64ICL8aUlVVg0eLtV2tiGv9AUkc9/Yz8UZLRcSAlapNkSsbLJ9bJZ hQTTdYuolGK9Ed3wCDnP7Dzm90LnEwx5QLpIJqvpajdZYAO/sai5QX9YlBYQh0GuYA87 VjvXpwvc8ER4YiG3j71DIbDqC24r1yfIoYsViqySp8D0YKN6U+i/PdCrjjDQdsWKQ1vu l0iL3l9mQFjPXwrdB9FemaTE1RRwdMB8v0iF349STiNx19Q2C0w/uO9U2KKcwtpn6Dju 4eGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=x2P1/0RD8m9ay9I52eeAoiRAAQIOn3SSJRt3LvafO1I=; b=KRG832ZzfPld4KRdh5gUdTw0jQ4sW3bhdmv3Q33evGXRIJw6657nDMiB0kAjO1Cc1o pUaAWS+MJ8TsVCBUgG+rA4M1lrFzoMPL2WzM93ApxiRewfCtsi1a4Glm3E1i/XcNYfqW 92Uxlk1Zzzj74+hqW2erDMc+XMLar6z9dA8pXoaqBvmJ9bpvKKn6mjpb3ZpQGaKv2qnO C7sFZDCO7CJDebiET7epv7REEQEImXu2nM39sEslNEOPteTSZ0IpQP9Jfi611lEna127 3bSNCmJerhJTJqAsfcIZovfFFoDLqHpvhqiPd3+NnUvnxxwDGizH5Uv75Wk3ssGBkuKQ qCMg== X-Gm-Message-State: AOPr4FVb+ljX6Eq9OO7fQPgOPpyKN+hGHw6vSvphSa8d6/K0XYl23KImYqftB8/FPXbfcbvT X-Received: by 10.60.174.72 with SMTP id bq8mr8955997oec.43.1461339561889; Fri, 22 Apr 2016 08:39:21 -0700 (PDT) Received: from localhost ([2605:a601:aab:f920:ad1c:41df:dcb1:a4a0]) by smtp.gmail.com with ESMTPSA id r10sm2093299oih.15.2016.04.22.08.39.21 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Fri, 22 Apr 2016 08:39:21 -0700 (PDT) From: Seth Forshee To: "Eric W. Biederman" , Alexander Viro , Greg Kroah-Hartman Subject: [PATCH v3 14/21] fs: Allow superblock owner to change ownership of inodes with unmappable ids Date: Fri, 22 Apr 2016 10:38:31 -0500 Message-Id: <1461339521-123191-15-git-send-email-seth.forshee@canonical.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1461339521-123191-1-git-send-email-seth.forshee@canonical.com> References: <1461339521-123191-1-git-send-email-seth.forshee@canonical.com> X-TM-AS-MML: disable X-Mailman-Approved-At: Fri, 22 Apr 2016 11:40:27 -0400 X-BeenThere: selinux@tycho.nsa.gov X-Mailman-Version: 2.1.20 Precedence: list List-Id: "Security-Enhanced Linux \(SELinux\) mailing list" List-Post: List-Help: Cc: linux-bcache@vger.kernel.org, Serge Hallyn , Seth Forshee , dm-devel@redhat.com, Miklos Szeredi , Richard Weinberger , linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, linux-raid@vger.kernel.org, fuse-devel@lists.sourceforge.net, Austin S Hemmelgarn , linux-mtd@lists.infradead.org, selinux@tycho.nsa.gov, linux-fsdevel@vger.kernel.org, cgroups@vger.kernel.org, Pavel Tikhomirov MIME-Version: 1.0 Errors-To: selinux-bounces@tycho.nsa.gov Sender: "Selinux" X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP In a userns mount some on-disk inodes may have ids which do not map into s_user_ns, in which case the in-kernel inodes are owned by invalid users. The superblock owner should be able to change attributes of these inodes but cannot. However it is unsafe to grant the superblock owner privileged access to all inodes in the superblock since proc, sysfs, etc. use DAC to protect files which may not belong to s_user_ns. The problem is restricted to only inodes where the owner or group is an invalid user. We can work around this by allowing users with CAP_CHOWN in s_user_ns to change an invalid owner or group id, so long as the other id is either invalid or mappable in s_user_ns. After changing ownership the user will be privileged towards the inode and thus able to change other attributes. As an precaution, checks for invalid ids are added to the proc and kernfs setattr interfaces. These filesystems are not expected to have inodes with invalid ids, but if it does happen any setattr operations will return -EPERM. Signed-off-by: Seth Forshee Acked-by: Serge Hallyn --- fs/attr.c | 47 +++++++++++++++++++++++++++++++++++++++-------- fs/kernfs/inode.c | 2 ++ fs/proc/base.c | 2 ++ fs/proc/generic.c | 3 +++ fs/proc/proc_sysctl.c | 2 ++ 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index 3cfaaac4a18e..a8b0931654a5 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -16,6 +16,43 @@ #include #include +static bool chown_ok(const struct inode *inode, kuid_t uid) +{ + struct user_namespace *user_ns; + + if (uid_eq(current_fsuid(), inode->i_uid) && uid_eq(uid, inode->i_uid)) + return true; + if (capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + return true; + + user_ns = inode->i_sb->s_user_ns; + if (!uid_valid(inode->i_uid) && + (!gid_valid(inode->i_gid) || kgid_has_mapping(user_ns, inode->i_gid)) && + ns_capable(user_ns, CAP_CHOWN)) + return true; + + return false; +} + +static bool chgrp_ok(const struct inode *inode, kgid_t gid) +{ + struct user_namespace *user_ns; + + if (uid_eq(current_fsuid(), inode->i_uid) && + (in_group_p(gid) || gid_eq(gid, inode->i_gid))) + return true; + if (capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + return true; + + user_ns = inode->i_sb->s_user_ns; + if (!gid_valid(inode->i_gid) && + (!uid_valid(inode->i_uid) || kuid_has_mapping(user_ns, inode->i_uid)) && + ns_capable(user_ns, CAP_CHOWN)) + return true; + + return false; +} + /** * inode_change_ok - check if attribute changes to an inode are allowed * @inode: inode to check @@ -58,17 +95,11 @@ int inode_change_ok(const struct inode *inode, struct iattr *attr) return 0; /* Make sure a caller can chown. */ - if ((ia_valid & ATTR_UID) && - (!uid_eq(current_fsuid(), inode->i_uid) || - !uid_eq(attr->ia_uid, inode->i_uid)) && - !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + if ((ia_valid & ATTR_UID) && !chown_ok(inode, attr->ia_uid)) return -EPERM; /* Make sure caller can chgrp. */ - if ((ia_valid & ATTR_GID) && - (!uid_eq(current_fsuid(), inode->i_uid) || - (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && - !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + if ((ia_valid & ATTR_GID) && !chgrp_ok(inode, attr->ia_gid)) return -EPERM; /* Make sure a caller can chmod. */ diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 16405ae88d2d..2e97a337ee5f 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -117,6 +117,8 @@ int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr) if (!kn) return -EINVAL; + if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) + return -EPERM; mutex_lock(&kernfs_mutex); error = inode_change_ok(inode, iattr); diff --git a/fs/proc/base.c b/fs/proc/base.c index b1755b23893e..648d623e2158 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -711,6 +711,8 @@ int proc_setattr(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid & ATTR_MODE) return -EPERM; + if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) + return -EPERM; error = inode_change_ok(inode, attr); if (error) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index ff3ffc76a937..1461570c552c 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -105,6 +105,9 @@ static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) struct proc_dir_entry *de = PDE(inode); int error; + if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) + return -EPERM; + error = inode_change_ok(inode, iattr); if (error) return error; diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index fe5b6e6c4671..f5d575157194 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -752,6 +752,8 @@ static int proc_sys_setattr(struct dentry *dentry, struct iattr *attr) if (attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) return -EPERM; + if (!uid_valid(inode->i_uid) || !gid_valid(inode->i_gid)) + return -EPERM; error = inode_change_ok(inode, attr); if (error)