From patchwork Tue Sep 4 14:54:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Shilong X-Patchwork-Id: 965959 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-ext4-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="FyLSbXqK"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 424VGc1mPyz9s3Z for ; Wed, 5 Sep 2018 00:54:16 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727142AbeIDTTl (ORCPT ); Tue, 4 Sep 2018 15:19:41 -0400 Received: from mail-pf1-f196.google.com ([209.85.210.196]:42319 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726004AbeIDTTk (ORCPT ); Tue, 4 Sep 2018 15:19:40 -0400 Received: by mail-pf1-f196.google.com with SMTP id l9-v6so1813902pff.9 for ; Tue, 04 Sep 2018 07:54:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=1LPHuRTogmqg5GBKrEUhlIkL8p3Zq0yNHAlV/hgSBAc=; b=FyLSbXqKDWwxzMNbplGjCx2rhuZYyG6TY937sBefQSjxPGg4EcMVNpFhSEbZH9xhhK 0+Xb1RxdTkdTA6tlWhrKUzcB37tX5p4tEUivTaaA6CZw7vUQboFyz/mfzBHxE1WZZhMr RxwGHM2tLnkRBoehWByFn8YN/xf7oA+UY7Fp169HQdfhCzY0GJRRJmbAeZ6JxmMxzVcw 7L93BNV9/1WIdh5Okon8hFK+vpxRZkrYXxUDAUmQgFNQebGTH195Rv99eTRPU+eCTMet 27MhE/FMbiLrL+zJIOs5HVZO0EG3Jj65Fq0Oo5LraP9dzn7FqudUZJB36gLnJmGCbgI6 wsEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=1LPHuRTogmqg5GBKrEUhlIkL8p3Zq0yNHAlV/hgSBAc=; b=piTlTbVtmyNmM9iKBa8n01VwzUK92avmO5x8cTFYySNyHvny7HeCav3b1C84i+OQU/ mJtJoipCWWozEtGFOSOGcdCvQU0fIYguYdFDK6ym9HAeEno5aPnE6PuLGcnMFF+C04AS ciy+/qJSyCcgIrhZCy0nSzoRkQkEaRoltr+bu/83alArlCNcuEHFbJNWZOJkvSGSHIRT FHO9zPzshpeuWD6b/LAxszg0ZHzq+o4yB0vqqmmr5ZHgyORAfcbqb+jIauq7JBgfbxPi l2CXzjNw0Dhvbk6z4tLCukTrs3TtWkfwtQpQXIqXZXVzhJRrsMh+Q9M4y9uYUATTfocG 5T/g== X-Gm-Message-State: APzg51BGZdJVA+cl3DJF0b2pPGn7XbfhxGRX5MpH6c7IFTpHaiyRcFaN l82NBreb/ep8z8Vkit1llkZKH8Fu X-Google-Smtp-Source: ANB0VdboG+Y3lM0XxskcJt09MCRAHzx+4I8YGlnGnD49HjorWK63HZcSFUWt4Spdvypvtaqbwh0+Xw== X-Received: by 2002:a62:d544:: with SMTP id d65-v6mr35171318pfg.107.1536072854323; Tue, 04 Sep 2018 07:54:14 -0700 (PDT) Received: from localhost.localdomain (fs276ec80e.tkyc203.ap.nuro.jp. [39.110.200.14]) by smtp.gmail.com with ESMTPSA id r18-v6sm27913735pgj.51.2018.09.04.07.54.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Sep 2018 07:54:13 -0700 (PDT) From: Wang Shilong X-Google-Original-From: Wang Shilong To: linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net Cc: dchinner@redhat.com, adilger@dilger.ca, wshilong@ddn.com Subject: [PATCH 1/2] ext4: fix setattr project check upon fssetxattr ioctl Date: Tue, 4 Sep 2018 23:54:05 +0900 Message-Id: <1536072846-19361-1-git-send-email-wshilong@ddn.com> X-Mailer: git-send-email 1.7.1 Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Currently, project quota could be changed by fssetxattr ioctl, and existed permission check inode_owner_or_capable() is obviously not enough, just think that common users could change project id of file, that could make users to break project quota easily. This patch try to follow same regular of xfs project quota: "Project Quota ID state is only allowed to change from within the init namespace. Enforce that restriction only if we are trying to change the quota ID state. Everything else is allowed in user namespaces." Besides that, check and set project id'state should be an atomic operation, protect whole operation with inode lock. Signed-off-by: Wang Shilong --- fs/ext4/ioctl.c | 62 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index a707411..e860df9 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -339,19 +339,14 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) if (projid_eq(kprojid, EXT4_I(inode)->i_projid)) return 0; - err = mnt_want_write_file(filp); - if (err) - return err; - err = -EPERM; - inode_lock(inode); /* Is it quota file? Do not allow user to mess with it */ if (ext4_is_quota_file(inode)) - goto out_unlock; + return err; err = ext4_get_inode_loc(inode, &iloc); if (err) - goto out_unlock; + return err; raw_inode = ext4_raw_inode(&iloc); if (!EXT4_FITS_IN_INODE(raw_inode, ei, i_projid)) { @@ -359,7 +354,7 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) EXT4_SB(sb)->s_want_extra_isize, &iloc); if (err) - goto out_unlock; + return err; } else { brelse(iloc.bh); } @@ -369,10 +364,8 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) handle = ext4_journal_start(inode, EXT4_HT_QUOTA, EXT4_QUOTA_INIT_BLOCKS(sb) + EXT4_QUOTA_DEL_BLOCKS(sb) + 3); - if (IS_ERR(handle)) { - err = PTR_ERR(handle); - goto out_unlock; - } + if (IS_ERR(handle)) + return PTR_ERR(handle); err = ext4_reserve_inode_write(handle, inode, &iloc); if (err) @@ -400,9 +393,6 @@ static int ext4_ioctl_setproject(struct file *filp, __u32 projid) err = rc; out_stop: ext4_journal_stop(handle); -out_unlock: - inode_unlock(inode); - mnt_drop_write_file(filp); return err; } #else @@ -626,6 +616,32 @@ static long ext4_ioctl_group_add(struct file *file, return err; } +static int +ext4_ioctl_setattr_check_projid(struct inode *inode, + struct fsxattr *fa) +{ + /* + * Project Quota ID state is only allowed to change from within the init + * namespace. Enforce that restriction only if we are trying to change + * the quota ID state. Everything else is allowed in user namespaces. + */ + if (current_user_ns() == &init_user_ns) + return 0; + + if (__kprojid_val(EXT4_I(inode)->i_projid) != fa->fsx_projid) + return -EINVAL; + + if (ext4_test_inode_flag(inode, EXT4_INODE_PROJINHERIT)) { + if (!(fa->fsx_xflags & FS_XFLAG_PROJINHERIT)) + return -EINVAL; + } else { + if (fa->fsx_xflags & FS_XFLAG_PROJINHERIT) + return -EINVAL; + } + + return 0; +} + long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = file_inode(filp); @@ -1025,19 +1041,19 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return err; inode_lock(inode); + err = ext4_ioctl_setattr_check_projid(inode, &fa); + if (err) + goto out; flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) | (flags & EXT4_FL_XFLAG_VISIBLE); err = ext4_ioctl_setflags(inode, flags); - inode_unlock(inode); - mnt_drop_write_file(filp); if (err) - return err; - + goto out; err = ext4_ioctl_setproject(filp, fa.fsx_projid); - if (err) - return err; - - return 0; +out: + inode_unlock(inode); + mnt_drop_write_file(filp); + return err; } case EXT4_IOC_SHUTDOWN: return ext4_shutdown(sb, arg);