Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp9103314pxu; Mon, 28 Dec 2020 06:43:16 -0800 (PST) X-Google-Smtp-Source: ABdhPJwdR/TzSYL9GWK0Bz9p76jFit1jmHPQ9rRIEK7urL1mHNtgkKVAYnrrmmAjFRAuYVL35oWN X-Received: by 2002:aa7:cb12:: with SMTP id s18mr35494664edt.125.1609166595781; Mon, 28 Dec 2020 06:43:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1609166595; cv=none; d=google.com; s=arc-20160816; b=k0KHDwEY5sjgjEQQDwbtMdAansMFFOrQlh8s9r5m5BYt8i4f+kD3Aa3BOP1q52XxiT oGBSTY/9omR8BVgYqiqpdciZgygO9WEz8rIn08GO4du0YdrO2MyQgQawuJ3PnxojPREr YDvpZqi2LxTNUv3Ce2oS4h20yEVFGel0/8nggbFNu4OhDuiU1yt0si18s3ZaRrUMryHu cJemGjeeqvsM6hTmiWAcBX6lrBhnfxpRalR8J8HZ6+mJYrtlc/HEM8dHjaADGgOf8NrK E+XT4W/xzIPZmIqQ0vacbVRzNfX+KSAQ3/hla5wa5BAOos3UnppwmSrfUcacbXwvrXVj IKsA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=vZ1nMYYwtShqlfLOSKwjw5pvGIndK8CXQ77YrQcZPHI=; b=cJif4YaO28nzhsDT7YafMl3nL/blzXlLVSFm7nuD+AWmgFBaTZnFjBvhqNt2/YKlac MPhUn5ruqWxhdcXZH7o6vHSXOfgIN0wu3qgn4lSnmXXxKc6ptn/9CoeaEkGQhcPNaauQ XG+q5UsK45K3x0ZapHVxqLEp/OUG0BK/p+amffcXYJFCG6qTVO478tVWqxmGv2khCsMc E4ELwXu9NNTEoRBGy/L6XPmlb+NsaBpLs2jqPMwMgfSYNPtRkSdAfxeP9MFa5TbuY+Rw k0s5cOR6ZUj1f3aQ2mPlrWyMzELEQZ0d1BpfM93BFziR8ihEVyYPPkR+GGVQ1r4+lkE9 yxCw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=qvtAMoMh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id cq15si19673935edb.15.2020.12.28.06.42.53; Mon, 28 Dec 2020 06:43:15 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=qvtAMoMh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2502557AbgL1O2s (ORCPT + 99 others); Mon, 28 Dec 2020 09:28:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:36496 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2502527AbgL1O2n (ORCPT ); Mon, 28 Dec 2020 09:28:43 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 853EF21D94; Mon, 28 Dec 2020 14:28:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1609165682; bh=hNDb6AIRg1fqbNpMU55tf8NOw9z3dSfL2qiCAXinYwk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qvtAMoMhkM/Xs3LH3jdiC7gZJRUNcHezXhv9WrB4NKRpmAQslyBnOv6mWDpkLw+0f D40W+dcHk/jlukvniSJmpaIZOVyaOwXyI9MPrsEkuBw9kv3+PrSrmqPkgQduYtuT1g FTaRyAYCaKndIwnP7IMfJKSEu81Mh0xYu+BsHqLA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Dmitry Vyukov , Miklos Szeredi , Amir Goldstein Subject: [PATCH 5.10 618/717] ovl: make ioctl() safe Date: Mon, 28 Dec 2020 13:50:16 +0100 Message-Id: <20201228125050.531661006@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201228125020.963311703@linuxfoundation.org> References: <20201228125020.963311703@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Miklos Szeredi commit 89bdfaf93d9157499c3a0d61f489df66f2dead7f upstream. ovl_ioctl_set_flags() does a capability check using flags, but then the real ioctl double-fetches flags and uses potentially different value. The "Check the capability before cred override" comment misleading: user can skip this check by presenting benign flags first and then overwriting them to non-benign flags. Just remove the cred override for now, hoping this doesn't cause a regression. The proper solution is to create a new setxflags i_op (patches are in the works). Xfstests don't show a regression. Reported-by: Dmitry Vyukov Signed-off-by: Miklos Szeredi Reviewed-by: Amir Goldstein Fixes: dab5ca8fd9dd ("ovl: add lsattr/chattr support") Cc: # v4.19 Signed-off-by: Greg Kroah-Hartman --- fs/overlayfs/file.c | 87 +++++++++------------------------------------------- 1 file changed, 16 insertions(+), 71 deletions(-) --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c @@ -541,46 +541,31 @@ static long ovl_real_ioctl(struct file * unsigned long arg) { struct fd real; - const struct cred *old_cred; long ret; ret = ovl_real_fdget(file, &real); if (ret) return ret; - old_cred = ovl_override_creds(file_inode(file)->i_sb); ret = security_file_ioctl(real.file, cmd, arg); - if (!ret) + if (!ret) { + /* + * Don't override creds, since we currently can't safely check + * permissions before doing so. + */ ret = vfs_ioctl(real.file, cmd, arg); - revert_creds(old_cred); + } fdput(real); return ret; } -static unsigned int ovl_iflags_to_fsflags(unsigned int iflags) -{ - unsigned int flags = 0; - - if (iflags & S_SYNC) - flags |= FS_SYNC_FL; - if (iflags & S_APPEND) - flags |= FS_APPEND_FL; - if (iflags & S_IMMUTABLE) - flags |= FS_IMMUTABLE_FL; - if (iflags & S_NOATIME) - flags |= FS_NOATIME_FL; - - return flags; -} - static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd, - unsigned long arg, unsigned int flags) + unsigned long arg) { long ret; struct inode *inode = file_inode(file); - unsigned int oldflags; if (!inode_owner_or_capable(inode)) return -EACCES; @@ -591,10 +576,13 @@ static long ovl_ioctl_set_flags(struct f inode_lock(inode); - /* Check the capability before cred override */ - oldflags = ovl_iflags_to_fsflags(READ_ONCE(inode->i_flags)); - ret = vfs_ioc_setflags_prepare(inode, oldflags, flags); - if (ret) + /* + * Prevent copy up if immutable and has no CAP_LINUX_IMMUTABLE + * capability. + */ + ret = -EPERM; + if (!ovl_has_upperdata(inode) && IS_IMMUTABLE(inode) && + !capable(CAP_LINUX_IMMUTABLE)) goto unlock; ret = ovl_maybe_copy_up(file_dentry(file), O_WRONLY); @@ -613,46 +601,6 @@ unlock: } -static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd, - unsigned long arg) -{ - unsigned int flags; - - if (get_user(flags, (int __user *) arg)) - return -EFAULT; - - return ovl_ioctl_set_flags(file, cmd, arg, flags); -} - -static unsigned int ovl_fsxflags_to_fsflags(unsigned int xflags) -{ - unsigned int flags = 0; - - if (xflags & FS_XFLAG_SYNC) - flags |= FS_SYNC_FL; - if (xflags & FS_XFLAG_APPEND) - flags |= FS_APPEND_FL; - if (xflags & FS_XFLAG_IMMUTABLE) - flags |= FS_IMMUTABLE_FL; - if (xflags & FS_XFLAG_NOATIME) - flags |= FS_NOATIME_FL; - - return flags; -} - -static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct fsxattr fa; - - memset(&fa, 0, sizeof(fa)); - if (copy_from_user(&fa, (void __user *) arg, sizeof(fa))) - return -EFAULT; - - return ovl_ioctl_set_flags(file, cmd, arg, - ovl_fsxflags_to_fsflags(fa.fsx_xflags)); -} - long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret; @@ -663,12 +611,9 @@ long ovl_ioctl(struct file *file, unsign ret = ovl_real_ioctl(file, cmd, arg); break; - case FS_IOC_SETFLAGS: - ret = ovl_ioctl_set_fsflags(file, cmd, arg); - break; - case FS_IOC_FSSETXATTR: - ret = ovl_ioctl_set_fsxflags(file, cmd, arg); + case FS_IOC_SETFLAGS: + ret = ovl_ioctl_set_flags(file, cmd, arg); break; default: