Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1535598pxb; Mon, 22 Feb 2021 04:44:23 -0800 (PST) X-Google-Smtp-Source: ABdhPJxz28+QacoORt1+cKssfFtvIJRGRUPU2ZRPf+OWNiIaC+L5gjBvV2r6o+zbw2RpvK7XRGfQ X-Received: by 2002:a17:906:f891:: with SMTP id lg17mr15821159ejb.369.1613997863489; Mon, 22 Feb 2021 04:44:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613997863; cv=none; d=google.com; s=arc-20160816; b=isKcpR1ldUPji2ErUr0CwcnUYWhXfwJVEKlDwndHToRQJ68KV5tM8QpNJf0Sah3RMb 9ARaRoWDCyT7G1KvHjJ77wclbctNxiQdAL0I5CdonFqIn8+IBO4teIVciYXL0xz9HeAQ ZI7YVb3Sao416jatgKNJFfCN+GBI3U4kJB7ooKgliEmwvRTPxFz33+UMUSfpc0ZtV/ZA orwCH0GxiCttXkjPHglEtCa6N5gmVsRoBSv8plbeps4VasKXLjpapeLz5Jn9eozUeH6E M0xvdSyytNkZF/qE1XzYo6QTmnkKgXn/RjfSPdPlwehGRfPUFbIWUCObC5SdIrUm2ZUG 9Mog== 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=s654AhX+JllFp3Sratnpl310PpgKq7yeWbc087h6RvU=; b=Ap+tjMK8mrWluJ1MUzzgB+N475AviLb/BGNlR9leAqM5NCUw2BRUT6efFO0RGdfZGu /RCCdJO7NDPxPVnQ2aBDBX4ILBQwbi21G4DaIBFCCQdHpGMcM6/9c5pGcRj9+FK0XROG JbahdkRQLi1jm2mHdoEntTF0vfKzt4Zk9gYb9G0n/3k5/eId0HCuwvrXXTLCtJLIaQyZ xptMwk3TyjsJ70JCXn3gf4x5f+w80wRcHhceYGpmq/vHgVAks/6do78RI1qK882gqv3d JpLk33FiZ0W6N8OlVBnF9eqo2T+DmmXebg+S0nktK3Y9xgeTO2Lj4hmOmf3j/gCoaaho hmew== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=ZrT+rUUS; 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 n10si11513034ejb.368.2021.02.22.04.44.00; Mon, 22 Feb 2021 04:44:23 -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=ZrT+rUUS; 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 S231508AbhBVMnK (ORCPT + 99 others); Mon, 22 Feb 2021 07:43:10 -0500 Received: from mail.kernel.org ([198.145.29.99]:46976 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230462AbhBVMRm (ORCPT ); Mon, 22 Feb 2021 07:17:42 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 7AD4664E41; Mon, 22 Feb 2021 12:17:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613996221; bh=rVJgB9uoEMske98CMdEnJ6XPfiY1kyWyMRA678gkH4k=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZrT+rUUSSqFdh3TdlCczZVfxCUbccL/ncCoZopcyyWRTwDoeuXfCoP5VERPwh5UP2 H9iDYxe+hI4YQUlHz8sFLiKMDUd7NngCZN8t3wAEWPJlkla8c8Gi9CDrLOg4GVoSSL 3sdjDZOK8fac6CUFS8oWKN1rVrjvjAFzlYSAmAsA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Miklos Szeredi , "Eric W. Biederman" , Sasha Levin Subject: [PATCH 4.19 07/50] cap: fix conversions on getxattr Date: Mon, 22 Feb 2021 13:12:58 +0100 Message-Id: <20210222121021.690228921@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210222121019.925481519@linuxfoundation.org> References: <20210222121019.925481519@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 [ Upstream commit f2b00be488730522d0fb7a8a5de663febdcefe0a ] If a capability is stored on disk in v2 format cap_inode_getsecurity() will currently return in v2 format unconditionally. This is wrong: v2 cap should be equivalent to a v3 cap with zero rootid, and so the same conversions performed on it. If the rootid cannot be mapped, v3 is returned unconverted. Fix this so that both v2 and v3 return -EOVERFLOW if the rootid (or the owner of the fs user namespace in case of v2) cannot be mapped into the current user namespace. Signed-off-by: Miklos Szeredi Acked-by: "Eric W. Biederman" Signed-off-by: Sasha Levin --- security/commoncap.c | 67 ++++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index f86557a8e43f6..a1dee0ab345a2 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -377,10 +377,11 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, { int size, ret; kuid_t kroot; + u32 nsmagic, magic; uid_t root, mappedroot; char *tmpbuf = NULL; struct vfs_cap_data *cap; - struct vfs_ns_cap_data *nscap; + struct vfs_ns_cap_data *nscap = NULL; struct dentry *dentry; struct user_namespace *fs_ns; @@ -402,46 +403,61 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, fs_ns = inode->i_sb->s_user_ns; cap = (struct vfs_cap_data *) tmpbuf; if (is_v2header((size_t) ret, cap)) { - /* If this is sizeof(vfs_cap_data) then we're ok with the - * on-disk value, so return that. */ - if (alloc) - *buffer = tmpbuf; - else - kfree(tmpbuf); - return ret; - } else if (!is_v3header((size_t) ret, cap)) { - kfree(tmpbuf); - return -EINVAL; + root = 0; + } else if (is_v3header((size_t) ret, cap)) { + nscap = (struct vfs_ns_cap_data *) tmpbuf; + root = le32_to_cpu(nscap->rootid); + } else { + size = -EINVAL; + goto out_free; } - nscap = (struct vfs_ns_cap_data *) tmpbuf; - root = le32_to_cpu(nscap->rootid); kroot = make_kuid(fs_ns, root); /* If the root kuid maps to a valid uid in current ns, then return * this as a nscap. */ mappedroot = from_kuid(current_user_ns(), kroot); if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) { + size = sizeof(struct vfs_ns_cap_data); if (alloc) { - *buffer = tmpbuf; + if (!nscap) { + /* v2 -> v3 conversion */ + nscap = kzalloc(size, GFP_ATOMIC); + if (!nscap) { + size = -ENOMEM; + goto out_free; + } + nsmagic = VFS_CAP_REVISION_3; + magic = le32_to_cpu(cap->magic_etc); + if (magic & VFS_CAP_FLAGS_EFFECTIVE) + nsmagic |= VFS_CAP_FLAGS_EFFECTIVE; + memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32); + nscap->magic_etc = cpu_to_le32(nsmagic); + } else { + /* use allocated v3 buffer */ + tmpbuf = NULL; + } nscap->rootid = cpu_to_le32(mappedroot); - } else - kfree(tmpbuf); - return size; + *buffer = nscap; + } + goto out_free; } if (!rootid_owns_currentns(kroot)) { - kfree(tmpbuf); - return -EOPNOTSUPP; + size = -EOVERFLOW; + goto out_free; } /* This comes from a parent namespace. Return as a v2 capability */ size = sizeof(struct vfs_cap_data); if (alloc) { - *buffer = kmalloc(size, GFP_ATOMIC); - if (*buffer) { - struct vfs_cap_data *cap = *buffer; - __le32 nsmagic, magic; + if (nscap) { + /* v3 -> v2 conversion */ + cap = kzalloc(size, GFP_ATOMIC); + if (!cap) { + size = -ENOMEM; + goto out_free; + } magic = VFS_CAP_REVISION_2; nsmagic = le32_to_cpu(nscap->magic_etc); if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE) @@ -449,9 +465,12 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32); cap->magic_etc = cpu_to_le32(magic); } else { - size = -ENOMEM; + /* use unconverted v2 */ + tmpbuf = NULL; } + *buffer = cap; } +out_free: kfree(tmpbuf); return size; } -- 2.27.0