Received: by 2002:a05:6a10:af89:0:0:0:0 with SMTP id iu9csp5501868pxb; Wed, 26 Jan 2022 13:33:00 -0800 (PST) X-Google-Smtp-Source: ABdhPJyAwl70ATbIta9Sfai7fQUGpuIp/M1KK5R+wHvi+q1oFUj99dDG2gvwoYi9QEYzJZtLChPA X-Received: by 2002:a17:902:e852:: with SMTP id t18mr890336plg.49.1643232780490; Wed, 26 Jan 2022 13:33:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1643232780; cv=none; d=google.com; s=arc-20160816; b=PTCKuSBjcNA8nNLwbIZ9ytNCcwHzcjB/FEVaFBCQTafKl/0mR5eAiZIXEE1vVzwbWV rsIJOwT4jF3WrolGQjz6c8rx7W5b8EwYFqJ3hFRUVdiRvewES+Dzm8PThAKR/cuLsYn4 I/5Rp2OV1uILResIsWc/xtP7jQ2MqthctlYhUb9RxWPP5M0lUXzSaSaDzO43nMEaGOhz H9VggzEjc3aUyl3k2nBIczA8GCG7y3AQbxz6ru7rqXWvFOBAcsfVb1uIJjdU1Yf0eFF7 /ceYT9ng+l/3nRW0XH1v7KAC3k6ujg4hB8UyD+BY/v3eLvU0Glg6KN95C4RQUHNesVCy 2eYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:references :in-reply-to:subject:cc:to:dkim-signature:dkim-signature:from; bh=+CxIM7gkfrEm7eO1fyq/strbAVIOXS0ekTc8dUnrpF0=; b=GNOEAW4xC7xdrsRb5BQbEDgzTGrsQCkaw3vrXhVADsUbGzULxySIgJhKbcJuz8Klvs i/1IoksaAxrmlHCfGxklntYbGR7RSvqD9IUCOJZLK72OcFGQTr1/bW3Eg1BOydF9snLp s3SKRW+tDckBd2uJpKNEhsuM2TCxDvQ1XdtYthvLFCjlysDWjihhpRHPubcOfZqHFfnO y4npgPtBcp6Etzeyy5+pl1jwNzQD/47AYAdtQfXOkuyNistNhPNpOtqp1vq7DdmR8kpE ZXfDTya5PXWSeNcOrVAghV06XgOiz30Ipk4zeQTcsaH9pd1W5ummpw7HjAuwhUhZUckq FU0g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=ybzPGcND; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=H1ZP0kFp; 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=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id q4si311195plh.423.2022.01.26.13.32.48; Wed, 26 Jan 2022 13:33:00 -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=@linutronix.de header.s=2020 header.b=ybzPGcND; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=H1ZP0kFp; 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=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241927AbiAZOXq (ORCPT + 99 others); Wed, 26 Jan 2022 09:23:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57524 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241653AbiAZOXp (ORCPT ); Wed, 26 Jan 2022 09:23:45 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B8EF8C06161C for ; Wed, 26 Jan 2022 06:23:44 -0800 (PST) From: Thomas Gleixner DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1643207023; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=+CxIM7gkfrEm7eO1fyq/strbAVIOXS0ekTc8dUnrpF0=; b=ybzPGcND97KBsVfpTfzoFKgMBSYICtgzJR3VssTC4UfKw/WqEAbRx9+Wb+F208QG4x+uQv yq17vYFZGT6L8qLq333jHFZcmMJ0iruHW3tx2m1yzwatsgJ/qwMP0VRSj4I1YbdPlXZ46e FwEGs0qoWkFxBVqTb+AJlsFKjBEGhPyGXc15giGM0i9/8XZPhLOaFCmU+XCwl4SUc3rRnj 0h1FgXc3vBwYU+MzZlHgenXv2stCwggdJCJQRTrFFSSFLstfIaBiO2niFAHoTYR2adFldj 0l7wz9SuCbBx061RJoE9eY52UJKEu64+sDgVY/tgDPYdTClon1h7IWFEJXktGA== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1643207023; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=+CxIM7gkfrEm7eO1fyq/strbAVIOXS0ekTc8dUnrpF0=; b=H1ZP0kFpKfbPGDtTuXUT/DzclpXzWXcuuT3aal34j2J/tEf3i685PKVMCMDcXqj7GcDTIu v6BM1D1XRV/6gmAQ== To: Fenghua Yu Cc: Ingo Molnar , Borislav Petkov , Peter Zijlstra , Andy Lutomirski , Dave Hansen , Tony Luck , Lu Baolu , Joerg Roedel , Josh Poimboeuf , Jacob Pan , Ashok Raj , Ravi V Shankar , iommu@lists.linux-foundation.org, x86 , linux-kernel Subject: Re: [PATCH v2 05/11] iommu/sva: Assign a PASID to mm on PASID allocation and free it on mm exit In-Reply-To: References: <20211217220136.2762116-1-fenghua.yu@intel.com> <20211217220136.2762116-6-fenghua.yu@intel.com> <87ee4w6g1n.ffs@tglx> <87bl006fdb.ffs@tglx> <878rv46eg3.ffs@tglx> Date: Wed, 26 Jan 2022 15:23:42 +0100 Message-ID: <87k0em4lu9.ffs@tglx> MIME-Version: 1.0 Content-Type: text/plain Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Jan 25 2022 at 07:18, Fenghua Yu wrote: > On Mon, Jan 24, 2022 at 09:55:56PM +0100, Thomas Gleixner wrote: > /** > * ioasid_put - Release a reference to an ioasid > * @ioasid: the ID to remove which in turn makes ioasid_put() a misnomer and the whole refcounting of the ioasid a pointless exercise. While looking at ioasid_put() usage I tripped over the following UAF issue: --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4817,8 +4817,10 @@ static int aux_domain_add_dev(struct dma auxiliary_unlink_device(domain, dev); link_failed: spin_unlock_irqrestore(&device_domain_lock, flags); - if (list_empty(&domain->subdevices) && domain->default_pasid > 0) + if (list_empty(&domain->subdevices) && domain->default_pasid > 0) { ioasid_put(domain->default_pasid); + domain->default_pasid = INVALID_IOASID; + } return ret; } @@ -4847,8 +4849,10 @@ static void aux_domain_remove_dev(struct spin_unlock_irqrestore(&device_domain_lock, flags); - if (list_empty(&domain->subdevices) && domain->default_pasid > 0) + if (list_empty(&domain->subdevices) && domain->default_pasid > 0) { ioasid_put(domain->default_pasid); + domain->default_pasid = INVALID_IOASID; + } } static int prepare_domain_attach_device(struct iommu_domain *domain, Vs. ioasid_put() I think we should fold the following: --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4818,7 +4818,7 @@ static int aux_domain_add_dev(struct dma link_failed: spin_unlock_irqrestore(&device_domain_lock, flags); if (list_empty(&domain->subdevices) && domain->default_pasid > 0) { - ioasid_put(domain->default_pasid); + ioasid_free(domain->default_pasid); domain->default_pasid = INVALID_IOASID; } @@ -4850,7 +4850,7 @@ static void aux_domain_remove_dev(struct spin_unlock_irqrestore(&device_domain_lock, flags); if (list_empty(&domain->subdevices) && domain->default_pasid > 0) { - ioasid_put(domain->default_pasid); + ioasid_free(domain->default_pasid); domain->default_pasid = INVALID_IOASID; } } --- a/drivers/iommu/ioasid.c +++ b/drivers/iommu/ioasid.c @@ -2,7 +2,7 @@ /* * I/O Address Space ID allocator. There is one global IOASID space, split into * subsets. Users create a subset with DECLARE_IOASID_SET, then allocate and - * free IOASIDs with ioasid_alloc and ioasid_put. + * free IOASIDs with ioasid_alloc() and ioasid_free(). */ #include #include @@ -15,7 +15,6 @@ struct ioasid_data { struct ioasid_set *set; void *private; struct rcu_head rcu; - refcount_t refs; }; /* @@ -315,7 +314,6 @@ ioasid_t ioasid_alloc(struct ioasid_set data->set = set; data->private = private; - refcount_set(&data->refs, 1); /* * Custom allocator needs allocator data to perform platform specific @@ -348,17 +346,11 @@ ioasid_t ioasid_alloc(struct ioasid_set EXPORT_SYMBOL_GPL(ioasid_alloc); /** - * ioasid_put - Release a reference to an ioasid + * ioasid_free - Free an ioasid * @ioasid: the ID to remove - * - * Put a reference to the IOASID, free it when the number of references drops to - * zero. - * - * Return: %true if the IOASID was freed, %false otherwise. */ -bool ioasid_put(ioasid_t ioasid) +void ioasid_free(ioasid_t ioasid) { - bool free = false; struct ioasid_data *ioasid_data; spin_lock(&ioasid_allocator_lock); @@ -368,10 +360,6 @@ bool ioasid_put(ioasid_t ioasid) goto exit_unlock; } - free = refcount_dec_and_test(&ioasid_data->refs); - if (!free) - goto exit_unlock; - active_allocator->ops->free(ioasid, active_allocator->ops->pdata); /* Custom allocator needs additional steps to free the xa element */ if (active_allocator->flags & IOASID_ALLOCATOR_CUSTOM) { @@ -381,9 +369,8 @@ bool ioasid_put(ioasid_t ioasid) exit_unlock: spin_unlock(&ioasid_allocator_lock); - return free; } -EXPORT_SYMBOL_GPL(ioasid_put); +EXPORT_SYMBOL_GPL(ioasid_free); /** * ioasid_find - Find IOASID data --- a/include/linux/ioasid.h +++ b/include/linux/ioasid.h @@ -34,7 +34,7 @@ struct ioasid_allocator_ops { #if IS_ENABLED(CONFIG_IOASID) ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min, ioasid_t max, void *private); -bool ioasid_put(ioasid_t ioasid); +void ioasid_free(ioasid_t ioasid); void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, bool (*getter)(void *)); int ioasid_register_allocator(struct ioasid_allocator_ops *allocator); @@ -52,10 +52,7 @@ static inline ioasid_t ioasid_alloc(stru return INVALID_IOASID; } -static inline bool ioasid_put(ioasid_t ioasid) -{ - return false; -} +static inline void ioasid_free(ioasid_t ioasid) { } static inline void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid, bool (*getter)(void *)) --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -423,7 +423,7 @@ static inline void mm_pasid_set(struct m static inline void mm_pasid_drop(struct mm_struct *mm) { if (pasid_valid(mm->pasid)) { - ioasid_put(mm->pasid); + ioasid_free(mm->pasid); mm->pasid = INVALID_IOASID; } }