Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp649813iog; Thu, 30 Jun 2022 07:40:30 -0700 (PDT) X-Google-Smtp-Source: AGRyM1uNioSTTy8VAdZPc8pHRoxSAkC5xVOv32Je2Gh7JDz2wjzwcDJRKIbSZzTPrFBopoLpuwta X-Received: by 2002:a17:902:c101:b0:16a:1272:270e with SMTP id 1-20020a170902c10100b0016a1272270emr15959674pli.163.1656600030510; Thu, 30 Jun 2022 07:40:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1656600030; cv=none; d=google.com; s=arc-20160816; b=dm66FVXhZa9XGWZqeqFrNV1h4uerZmfMbwg6mP2FlF2sLm34Qyvtcul74t2O9tHTEv UZdR7fmXkWQEP4o+2vvCslQGOnfW1Qps/b7/NeIAvBkemsxO0T5wcSA4xtpj9GQVI3Zn qZ7Rk65khfWC+ykp2JLGpWMpgXY1oXK/OGZZXHKXwXdNJttfAU0eU3mPeR6Z/VieuJW1 fHnslB79MIpIOiO49APmNfBIZoB2w5yylFRxLADMnrdOKvtnzHHR1DWTxCLTgAoaaM5c AwlKExoAvHaAf2LVqRCTuU0vWrJpHZswQYtmnI4Z38ZxZGTuls6QARkJFLyIWnHkpqmm xYNg== 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=Yi08G5+obkILCB5SKxxcoORVK4DARBZMDBZd2XInvAQ=; b=ZxsuUqWrR+sJyrIwQJgSrqCTSDVEXUVUxWbuw6etiogYdKpLf2oItRaXpykNrHSyXQ 3Wj87Nzm9ek8p081AuWBtIIuDoUYc8Krtkwhsx/msyIQOWVFnDSCVR6FcPliDVMIZ659 MZLXnJ571dbODfrVChXmpLFBliuyY5eNAoI3HGYkj5Sa3TgPr/mZW1d6SAc8Y0ba63xF Vj+3TGo1d/uKq1ZhZtmZW9O94cQFZr5qYlADD3BaoDCQNky3nBp8KC+qQyHZyfMtbUyI xNjBPm/CgjcdxJXsjN3An6IRKN2NpWWpNNQ7ud36mfG38Nr1jCyonzwc8YobN88bJnIP XsLA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=gy+HLNQQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id t21-20020a17090a5d9500b001e8927db60bsi2708797pji.73.2022.06.30.07.40.18; Thu, 30 Jun 2022 07:40:30 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=gy+HLNQQ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 S236800AbiF3OK0 (ORCPT + 99 others); Thu, 30 Jun 2022 10:10:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59694 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236795AbiF3OJd (ORCPT ); Thu, 30 Jun 2022 10:09:33 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0B6FC73911; Thu, 30 Jun 2022 06:55:18 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A863461F5F; Thu, 30 Jun 2022 13:55:09 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B27D5C34115; Thu, 30 Jun 2022 13:55:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1656597309; bh=WaG1nHyRp9gM42Yl11WvQkmWsXZ9kxeW+GdjIh4gZQ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gy+HLNQQUJbel1W12NXfp/BXDWF3SVmlcFSCQ7/aNDP2mFD1AsV6+N87pHA79nCHW kCLUL6M1oCAHfkh83a+QHv9bVObWM9fTk/QYimj/aR3CYfJ+Yl5SPxPJFs9qPCEduO bnsuVeW6k5S1ZtxIrRh2nTa36Kp1MXFsos8/Ir3M= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Seth Forshee , Christoph Hellwig , Aleksa Sarai , Al Viro , linux-fsdevel@vger.kernel.org, "Christian Brauner (Microsoft)" Subject: [PATCH 5.15 24/28] fs: account for group membership Date: Thu, 30 Jun 2022 15:47:20 +0200 Message-Id: <20220630133233.642494810@linuxfoundation.org> X-Mailer: git-send-email 2.37.0 In-Reply-To: <20220630133232.926711493@linuxfoundation.org> References: <20220630133232.926711493@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Christian Brauner commit 168f912893407a5acb798a4a58613b5f1f98c717 upstream. When calling setattr_prepare() to determine the validity of the attributes the ia_{g,u}id fields contain the value that will be written to inode->i_{g,u}id. This is exactly the same for idmapped and non-idmapped mounts and allows callers to pass in the values they want to see written to inode->i_{g,u}id. When group ownership is changed a caller whose fsuid owns the inode can change the group of the inode to any group they are a member of. When searching through the caller's groups we need to use the gid mapped according to the idmapped mount otherwise we will fail to change ownership for unprivileged users. Consider a caller running with fsuid and fsgid 1000 using an idmapped mount that maps id 65534 to 1000 and 65535 to 1001. Consequently, a file owned by 65534:65535 in the filesystem will be owned by 1000:1001 in the idmapped mount. The caller now requests the gid of the file to be changed to 1000 going through the idmapped mount. In the vfs we will immediately map the requested gid to the value that will need to be written to inode->i_gid and place it in attr->ia_gid. Since this idmapped mount maps 65534 to 1000 we place 65534 in attr->ia_gid. When we check whether the caller is allowed to change group ownership we first validate that their fsuid matches the inode's uid. The inode->i_uid is 65534 which is mapped to uid 1000 in the idmapped mount. Since the caller's fsuid is 1000 we pass the check. We now check whether the caller is allowed to change inode->i_gid to the requested gid by calling in_group_p(). This will compare the passed in gid to the caller's fsgid and search the caller's additional groups. Since we're dealing with an idmapped mount we need to pass in the gid mapped according to the idmapped mount. This is akin to checking whether a caller is privileged over the future group the inode is owned by. And that needs to take the idmapped mount into account. Note, all helpers are nops without idmapped mounts. New regression test sent to xfstests. Link: https://github.com/lxc/lxd/issues/10537 Link: https://lore.kernel.org/r/20220613111517.2186646-1-brauner@kernel.org Fixes: 2f221d6f7b88 ("attr: handle idmapped mounts") Cc: Seth Forshee Cc: Christoph Hellwig Cc: Aleksa Sarai Cc: Al Viro Cc: stable@vger.kernel.org # 5.15+ CC: linux-fsdevel@vger.kernel.org Reviewed-by: Seth Forshee Signed-off-by: Christian Brauner (Microsoft) Signed-off-by: Greg Kroah-Hartman --- fs/attr.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) --- a/fs/attr.c +++ b/fs/attr.c @@ -61,9 +61,15 @@ static bool chgrp_ok(struct user_namespa const struct inode *inode, kgid_t gid) { kgid_t kgid = i_gid_into_mnt(mnt_userns, inode); - if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode)) && - (in_group_p(gid) || gid_eq(gid, inode->i_gid))) - return true; + if (uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) { + kgid_t mapped_gid; + + if (gid_eq(gid, inode->i_gid)) + return true; + mapped_gid = mapped_kgid_fs(mnt_userns, i_user_ns(inode), gid); + if (in_group_p(mapped_gid)) + return true; + } if (capable_wrt_inode_uidgid(mnt_userns, inode, CAP_CHOWN)) return true; if (gid_eq(kgid, INVALID_GID) && @@ -123,12 +129,20 @@ int setattr_prepare(struct user_namespac /* Make sure a caller can chmod. */ if (ia_valid & ATTR_MODE) { + kgid_t mapped_gid; + if (!inode_owner_or_capable(mnt_userns, inode)) return -EPERM; + + if (ia_valid & ATTR_GID) + mapped_gid = mapped_kgid_fs(mnt_userns, + i_user_ns(inode), attr->ia_gid); + else + mapped_gid = i_gid_into_mnt(mnt_userns, inode); + /* Also check the setgid bit! */ - if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : - i_gid_into_mnt(mnt_userns, inode)) && - !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID)) + if (!in_group_p(mapped_gid) && + !capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID)) attr->ia_mode &= ~S_ISGID; }