From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75D5D43B6F2; Mon, 17 Aug 2026 14:56:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786978591; cv=none; b=OoYi23cjuupIN8BD1eqV+HxzITkla8QrDIbWgGiWOIuWZnHx7IOtOsyHcpx82/sCfJ1vnTWQ6eN0z6i0Ws0j4EzMfWMu4fWWt3+WmGFAqaqaZSylkvk3GMBGNn+50pVkbzmtjmKEXJBX60jXkTQEk4mO+OgYu2tojXRgUWcK4Hw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786978591; c=relaxed/simple; bh=8PNUJ4C+3sTW7kuBE6jnz6PD3aJ8N4vb2B0g9zIAj44=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jOSxEZ7HIZ+G2eYlH1eLOyF65YXm1QFhBJ5vVT21Z3VsZQ3tz713MxmWDlFh8RFHsHOKBt56npm1IKZ4M/ZaHi5sG4yul4/PAfp7fMRHrnRMjezvYlQMdsxIaA4ps/dLodxdwGMsSvVpVxvxYkLb00eFNgdHTQMEESDCCXdGvS0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=sdkv7JxX; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="sdkv7JxX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B7FE31F000E9; Mon, 17 Aug 2026 14:56:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1786978590; bh=mgJlCRfo7jrIr6/nEtumiFUXVFSxu09yZcybX7+dcMA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=sdkv7JxXV0fKjd7LOU5C45IFfKGxx9P+VBL70W9o+WeEJiTRa4BcHCRcl4LKCmcNw ymMmmO/mi4++LsxkLodEP7JSqyE6/R3g9QVmWUXD81VxZ66cdsHoXP1Rjy68B6+oiQ Va8H7wHPpuwgRjCsuEGMhHRj1UF2EYFsB41JSyVk= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Christian Borntraeger , Matthew Rosato , Farhan Ali , Sasha Levin Subject: [PATCH 6.6 090/156] KVM: s390: pci: Fix memory accounting for pinned/unpinned pages Date: Mon, 17 Aug 2026 15:33:44 +0200 Message-ID: <20260817132538.135775693@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260817132534.666299318@linuxfoundation.org> References: <20260817132534.666299318@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.6-stable review patch. If anyone has any objections, please let me know. ------------------ From: Farhan Ali [ Upstream commit 36f6999ecde3976731a8bfc0b8e667da6f593069 ] The account_mem() and unaccount_mem() functions call get_uid() which increments the reference count of struct user_struct on every invocation. But we don't decrement the count by calling free_uid(). It also accounted/unaccounted the pages against the current->mm. But its possible the unaccount_mem() can be called from a different process context than the one that originally pinned the pages. Let's fix this by storing the pinning process user_struct and mm_struct when accounting for pinned pages, and subsequently free these resources when the pages are unpinned. Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding") Cc: stable@vger.kernel.org Reviewed-by: Christian Borntraeger Reviewed-by: Matthew Rosato Signed-off-by: Farhan Ali Tested-by: Matthew Rosato [borntraeger@linux.ibm.com: Fixed whitespace] Signed-off-by: Christian Borntraeger [alifm@linux.ibm.com: Resolve merge conflict] Signed-off-by: Farhan Ali Signed-off-by: Sasha Levin --- arch/s390/kvm/pci.c | 48 ++++++++++++++++++++++++++++++++------------- arch/s390/kvm/pci.h | 2 ++ 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c index 17fedfc7bb990..f887e11b0f1ef 100644 --- a/arch/s390/kvm/pci.c +++ b/arch/s390/kvm/pci.c @@ -191,34 +191,54 @@ static int kvm_zpci_clear_airq(struct zpci_dev *zdev) return cc ? -EIO : 0; } -static inline void unaccount_mem(unsigned long nr_pages) +static inline void unaccount_mem(struct kvm_zdev *kzdev, unsigned long nr_pages) { - struct user_struct *user = get_uid(current_user()); + struct user_struct *user = kzdev->user_account; + struct mm_struct *mm_account = kzdev->mm_account; - if (user) + if (user) { atomic_long_sub(nr_pages, &user->locked_vm); - if (current->mm) - atomic64_sub(nr_pages, ¤t->mm->pinned_vm); + free_uid(user); + kzdev->user_account = NULL; + } + + if (mm_account) { + atomic64_sub(nr_pages, &mm_account->pinned_vm); + mmdrop(mm_account); + kzdev->mm_account = NULL; + } } -static inline int account_mem(unsigned long nr_pages) +static inline int account_mem(struct kvm_zdev *kzdev, unsigned long nr_pages) { struct user_struct *user = get_uid(current_user()); unsigned long page_limit, cur_pages, new_pages; + int rc = 0; page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; + cur_pages = atomic_long_read(&user->locked_vm); do { - cur_pages = atomic_long_read(&user->locked_vm); new_pages = cur_pages + nr_pages; - if (new_pages > page_limit) - return -ENOMEM; - } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages, - new_pages) != cur_pages); + if (new_pages > page_limit) { + rc = -ENOMEM; + goto out; + } + } while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages)); + + if (current->mm) { + mmgrab(current->mm); + atomic64_add(nr_pages, ¤t->mm->pinned_vm); + } - atomic64_add(nr_pages, ¤t->mm->pinned_vm); + kzdev->user_account = user; + kzdev->mm_account = current->mm; return 0; + +out: + free_uid(user); + return rc; } static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, @@ -295,7 +315,7 @@ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib, } /* Account for pinned pages, roll back on failure */ - if (account_mem(pcount)) + if (account_mem(zdev->kzdev, pcount)) goto unpin2; /* AISB must be allocated before we can fill in GAITE */ @@ -424,7 +444,7 @@ static int kvm_s390_pci_aif_disable(struct zpci_dev *zdev, bool force) pcount++; } if (pcount > 0) - unaccount_mem(pcount); + unaccount_mem(kzdev, pcount); out: mutex_unlock(&aift->aift_lock); diff --git a/arch/s390/kvm/pci.h b/arch/s390/kvm/pci.h index ff0972dd5e71d..fdf8c7bf4ed08 100644 --- a/arch/s390/kvm/pci.h +++ b/arch/s390/kvm/pci.h @@ -22,6 +22,8 @@ struct kvm_zdev { struct kvm *kvm; struct zpci_fib fib; struct list_head entry; + struct user_struct *user_account; + struct mm_struct *mm_account; }; struct zpci_gaite { -- 2.53.0