From nobody Wed Jun 17 07:26:09 2026 Received: from mail-pf1-f201.google.com (mail-pf1-f201.google.com [209.85.210.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7FA383A9610 for ; Thu, 23 Apr 2026 17:40:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776966043; cv=none; b=FUEH58Op9edURDWru6IC6mBRlWFIhXf5SjJDomOgFqrYpRHEdclW5s0OjUZi76Aj7coOALDz5ucxucXy0gsnxvPR1F2r43s3p1IcxXEGo7/mNIECFquSet+49vBHcREXyoBXyLWRdZryE+MiUhLfPz6uKNO160vZFRvnikV5Jd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776966043; c=relaxed/simple; bh=OdCkp+U7UboftnRj6WMJLwEh7MCo7Yte9AXWP+965JY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KyZswn/B8eu1dsjDa3yFqvn9AtQJK46WQy927exu9cMa8fJZhrVbGLsb8xprYkbVVRtefuOjBT4Ef12VEtnSEU8WRzpRzU62ywku5zhzwD/6XJIoTUEJQ+JQNhXXZlDXbVkcyjA1/dY6EHIpmuHZ9ml/Umiwec0qdCfmzhXjVKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=iRyYcm9A; arc=none smtp.client-ip=209.85.210.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="iRyYcm9A" Received: by mail-pf1-f201.google.com with SMTP id d2e1a72fcca58-82f6b984b3aso3818230b3a.3 for ; Thu, 23 Apr 2026 10:40:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1776966041; x=1777570841; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Dl3LvDDtjuuVJwbcBevbqQWcUiD6cgLHLyDDYMqvvE0=; b=iRyYcm9A244x51SjhIFkyHLG76irZ97gWhzQMkQtD2dRbuT4nv1NFIBcDEzfubbG90 r+d1xrB44ovUmrUCboY9Apz39VurxyO+fBBCD5MVjR+wUIWb9ZaDfWL5J2GGZGbmUv1s 44HI5wjUXt3yLBpVHy7vGvL1ulmKcjZAgiA23ZdOFVSlT2yK8Mx2E/WPqQHaxJAKYL4W 4St73qhEB4XHiFUUKDNzIS6P3sH9Os4L7L1uYEQrKZkU7ioW0/LFqGxds5Cm+5C3wX0m IgG59Uy4M+fnPTbfCWysvS2Pd53XVpSgiN+eN/mPZtj5PRVtZD9SrULemjhD0GTWsypj 4XHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776966041; x=1777570841; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Dl3LvDDtjuuVJwbcBevbqQWcUiD6cgLHLyDDYMqvvE0=; b=Jzfd84PDyjpPPjhpuj1/0SBsXMSkohCo/0tv3M5aUCO0unLRZmqt6hShk7RI9JxXhQ yLkwv9MXR5tRES4ZlG5r/WcE8GJqIW2GZXgLYCfOvR3Yi3hywK4uo0wJBHe96MJOOoBG a7eipYGRj0VeX6kIH/gM98/hQ9Q3ruDrcKQm108cWJPWceLxjl8Phw1bFxoJ1g6DPnDH mj5m4h7iuTYow0hktFobUu2W7aIG11FiiVOWbpdE3STyyGqfloUV7fwuji1kZGrP5sSR YYJNvb6Oe1naXrVRrHkyPlIeoweYEcfbsCjnRpRB3zMmHohmcmwFdqU+MnzUkrjsAatP Vd2A== X-Gm-Message-State: AOJu0YxbpIbZu5d7KCZesCcfB3nbjauLu8jfTGPPL6bH/+qHWranTlS4 zWRH1Ixpv2jwzh7NwpZJG0K5go7GHhBg78X0naDrr0r5gfkpNjLAD7MzEdZHf6RvTl59YCOp2Yd KgEALCBBg+qWLnRHl6duLWqc4y96P/clVUvviT/ZfylgS340KbN0VlwtnNpoChQpeb61TX93/qc wHrIsJ3BHkHfSNmPsMa8vXd0yV5uu1rodckl74MrHPaPW8Kjqm1p2OO9Y= X-Received: from pfkm16.prod.google.com ([2002:a05:6a00:810:b0:82f:ac74:4db5]) (user=dmatlack job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:2d8d:b0:82c:1cd0:2f5e with SMTP id d2e1a72fcca58-82f8c96eb30mr30470988b3a.44.1776966040415; Thu, 23 Apr 2026 10:40:40 -0700 (PDT) Date: Thu, 23 Apr 2026 17:40:28 +0000 In-Reply-To: <20260423174032.3140399-1-dmatlack@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260423174032.3140399-1-dmatlack@google.com> X-Mailer: git-send-email 2.54.0.rc2.544.gc7ae2d5bb8-goog Message-ID: <20260423174032.3140399-2-dmatlack@google.com> Subject: [PATCH 1/2] liveupdate: Use refcount_t for FLB reference counts From: David Matlack To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Mike Rapoport , Pasha Tatashin , Pratyush Yadav , Samiullah Khawaja , David Matlack Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Use refcount_t instead of a raw integer to keep track of references on incoming and outgoing FLBs. Using refcount_t provides protection from overflow, underflow, and other issues. Fixes: cab056f2aae7 ("liveupdate: luo_flb: introduce File-Lifecycle-Bound g= lobal state") Signed-off-by: David Matlack Reviewed-by: Pasha Tatashin =20 Reviewed-by: Samiullah Khawaja --- include/linux/liveupdate.h | 3 ++- kernel/liveupdate/luo_flb.c | 22 ++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h index 30c5a39ff9e9..8d3bbc35c828 100644 --- a/include/linux/liveupdate.h +++ b/include/linux/liveupdate.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -175,7 +176,7 @@ struct liveupdate_flb_ops { * @retrieved: True once the FLB's retrieve() callback has run. */ struct luo_flb_private_state { - long count; + refcount_t count; u64 data; void *obj; struct mutex lock; diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c index 00f5494812c4..59c5f31ab767 100644 --- a/kernel/liveupdate/luo_flb.c +++ b/kernel/liveupdate/luo_flb.c @@ -111,7 +111,7 @@ static int luo_flb_file_preserve_one(struct liveupdate_= flb *flb) struct luo_flb_private *private =3D luo_flb_get_private(flb); =20 scoped_guard(mutex, &private->outgoing.lock) { - if (!private->outgoing.count) { + if (!refcount_read(&private->outgoing.count)) { struct liveupdate_flb_op_args args =3D {0}; int err; =20 @@ -126,8 +126,10 @@ static int luo_flb_file_preserve_one(struct liveupdate= _flb *flb) } private->outgoing.data =3D args.data; private->outgoing.obj =3D args.obj; + refcount_set(&private->outgoing.count, 1); + } else { + refcount_inc(&private->outgoing.count); } - private->outgoing.count++; } =20 return 0; @@ -138,8 +140,7 @@ static void luo_flb_file_unpreserve_one(struct liveupda= te_flb *flb) struct luo_flb_private *private =3D luo_flb_get_private(flb); =20 scoped_guard(mutex, &private->outgoing.lock) { - private->outgoing.count--; - if (!private->outgoing.count) { + if (refcount_dec_and_test(&private->outgoing.count)) { struct liveupdate_flb_op_args args =3D {0}; =20 args.flb =3D flb; @@ -178,7 +179,7 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *= flb) for (int i =3D 0; i < fh->header_ser->count; i++) { if (!strcmp(fh->ser[i].name, flb->compatible)) { private->incoming.data =3D fh->ser[i].data; - private->incoming.count =3D fh->ser[i].count; + refcount_set(&private->incoming.count, fh->ser[i].count); found =3D true; break; } @@ -208,12 +209,8 @@ static int luo_flb_retrieve_one(struct liveupdate_flb = *flb) static void luo_flb_file_finish_one(struct liveupdate_flb *flb) { struct luo_flb_private *private =3D luo_flb_get_private(flb); - u64 count; =20 - scoped_guard(mutex, &private->incoming.lock) - count =3D --private->incoming.count; - - if (!count) { + if (refcount_dec_and_test(&private->incoming.count)) { struct liveupdate_flb_op_args args =3D {0}; =20 if (!private->incoming.retrieved) { @@ -652,12 +649,13 @@ void luo_flb_serialize(void) guard(rwsem_read)(&luo_register_rwlock); list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) { struct luo_flb_private *private =3D luo_flb_get_private(gflb); + long count =3D refcount_read(&private->outgoing.count); =20 - if (private->outgoing.count > 0) { + if (count > 0) { strscpy(fh->ser[i].name, gflb->compatible, sizeof(fh->ser[i].name)); fh->ser[i].data =3D private->outgoing.data; - fh->ser[i].count =3D private->outgoing.count; + fh->ser[i].count =3D count; i++; } } --=20 2.54.0.rc2.544.gc7ae2d5bb8-goog From nobody Wed Jun 17 07:26:09 2026 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B77F3AA1A9 for ; Thu, 23 Apr 2026 17:40:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776966044; cv=none; b=eWWSmE50MXizkqN9vOzEFKerGsm4OCRNUySjpn2MBYImNwIM5YBjAHcIIA3H0ohVjmxWtNsCAwP1x8VYucOZGSLZutpwKEvgZzVGhC0xlJyATP6dlCCEGgXodvV79jSp6N0IX8fpxePrCrAImV+pl/pq5+J6a9XjrXd5qV4I7KM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776966044; c=relaxed/simple; bh=C55t5l0qE5PsMHx2Iz5dwMqChJMEQp4rDPfjch/SFAk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CsOBV10vkUvKraX5cCvZ5J9/KP9rM96HDd5nHSMdGPCmKbohYVvuzPC3SSwFVtqbmhQfe7IItkxiwy7a6y0sr3TAEiEzuf8ToZQyBZOdKsmZirCQ/VvwA6UxPRV/aCEuitvFjYPc0aXg5IgV9saTQSwRYJUm1wmzoC/YRACCj0U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Rxd3K/eu; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--dmatlack.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Rxd3K/eu" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-35d99c2908cso6801394a91.0 for ; Thu, 23 Apr 2026 10:40:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1776966042; x=1777570842; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=g3tVIqNiqY1SODoiHSu0/c0Z333x+GuML1AW7++ze5c=; b=Rxd3K/euFtuZHainRlLqHMb4rt2VJAv4RnAUwTg3G/ReTHNbJH4UjCn+zDtbnsY9n7 gljxyCGwme/wPc1OMNyyW0Ld7qvo0FcSzes5Ws3lZFb6DkxtXBs/DRRYXRZNKP4DAv1s i+Kc1zpQ+I1Xrbo9LyTrVInr9hotNH7af1vVs41a0n/QXkVaSunmRHZz+NjpqOWb8E8B LpHfTPf9puL39t2z1AZDzW+y5A2PfbeGD1ur3tN4Sim/pDfQ0/H82vyt1mGj8uorA35z l48Ij37jL5pkbfhI+oll8qnUlq3xW3xuxAB87qq8PxdBV22km+9dcOcDAQAhT2z2ewSK qF2Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776966042; x=1777570842; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=g3tVIqNiqY1SODoiHSu0/c0Z333x+GuML1AW7++ze5c=; b=ozB4NmlRTRvEeE7S+lXdRZBv529eEhTVec26hOA7RMhUo8m/oyCyuDP7qAvNQHFw1G KWzefRF7uSS1NtnfjEoL410TbcsGCZ+APm3zllXrDxJARCjZm6tiu5NU+TiFXCJ5FJQO sRSh3mgCgLU5m9iGb/EGuJfg4Kmk453JkDA47jx7m+CctQsf3RWwGi4g+IYoWJesP1Us Hva1HCUb7ZuP0VTDlZE7hS7qCVmA4x1GrQT26LLcopkWR5wgFWWRv1d40vC2jIKTXAz3 E2ahcrRj5XbSExx8kfldZmuK/Onu2SSH8deVa3RbNqCDmlnPTe3xC17uFDSbnvzN0U2j dlOg== X-Gm-Message-State: AOJu0Yy86QCH2gABTnIl6wYfCMIhsK81NwwcjttiqXLXk3FCGM30P0cR r0FyjeIJv2+dwFpf8ySyIA3UliC1Bxbx62WP+OGbbMBqGpXme5QO6uD37X4CNKKIA6cB33sYnSB PklWqdoQhvXWkLYF1Urd6OPcKenRRg974NLVMmBIy4+iRovoXCIhc849K7sLXJX8/WMyQrjsjks XfZo/0wJNdDH05rUMTj6XK2J/JIuIxTaz5xKHAh2GCjMVJ09M47KBFDjg= X-Received: from pgbdw18.prod.google.com ([2002:a05:6a02:4492:b0:c79:788d:5b72]) (user=dmatlack job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:4a0a:b0:35e:58d3:3284 with SMTP id 98e67ed59e1d1-361403e083bmr28511272a91.9.1776966042179; Thu, 23 Apr 2026 10:40:42 -0700 (PDT) Date: Thu, 23 Apr 2026 17:40:29 +0000 In-Reply-To: <20260423174032.3140399-1-dmatlack@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260423174032.3140399-1-dmatlack@google.com> X-Mailer: git-send-email 2.54.0.rc2.544.gc7ae2d5bb8-goog Message-ID: <20260423174032.3140399-3-dmatlack@google.com> Subject: [PATCH 2/2] liveupdate: Reference count incoming FLB data From: David Matlack To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Mike Rapoport , Pasha Tatashin , Pratyush Yadav , Samiullah Khawaja , David Matlack Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Increment the incoming FLB refcount in liveupdate_flb_get_incoming() so that the FLB structure cannot be freed while the caller is actively using it. Add an additional liveupdate_flb_put_incoming() function so the caller can explicitly indicate when it is done using the FLB data. During a Live Update, a subsystem might need to hold onto the incoming File-Lifecycle-Bound (FLB) data for an extended period, such as during device enumeration. Incrementing the reference count guarantees that the data remains valid and accessible until the subsystem releases it, preventing future use-after-free bugs. Fixes: cab056f2aae7 ("liveupdate: luo_flb: introduce File-Lifecycle-Bound g= lobal state") Signed-off-by: David Matlack Reviewed-by: Pasha Tatashin =20 Reviewed-by: Samiullah Khawaja --- include/linux/liveupdate.h | 6 ++++++ kernel/liveupdate/luo_flb.c | 32 +++++++++++++++++--------------- lib/tests/liveupdate.c | 3 +++ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h index 8d3bbc35c828..88722e5caf02 100644 --- a/include/linux/liveupdate.h +++ b/include/linux/liveupdate.h @@ -240,6 +240,8 @@ void liveupdate_unregister_flb(struct liveupdate_file_h= andler *fh, struct liveupdate_flb *flb); =20 int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp); +void liveupdate_flb_put_incoming(struct liveupdate_flb *flb); + int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp); =20 #else /* CONFIG_LIVEUPDATE */ @@ -280,6 +282,10 @@ static inline int liveupdate_flb_get_incoming(struct l= iveupdate_flb *flb, return -EOPNOTSUPP; } =20 +static inline void liveupdate_flb_put_incoming(struct liveupdate_flb *flb) +{ +} + static inline int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp) { diff --git a/kernel/liveupdate/luo_flb.c b/kernel/liveupdate/luo_flb.c index 59c5f31ab767..8f5c5dd01cd0 100644 --- a/kernel/liveupdate/luo_flb.c +++ b/kernel/liveupdate/luo_flb.c @@ -165,7 +165,7 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *= flb) bool found =3D false; int err; =20 - guard(mutex)(&private->incoming.lock); + lockdep_assert_held(&private->incoming.lock); =20 if (private->incoming.finished) return -ENODATA; @@ -206,12 +206,14 @@ static int luo_flb_retrieve_one(struct liveupdate_flb= *flb) return 0; } =20 -static void luo_flb_file_finish_one(struct liveupdate_flb *flb) +void liveupdate_flb_put_incoming(struct liveupdate_flb *flb) { struct luo_flb_private *private =3D luo_flb_get_private(flb); + struct liveupdate_flb_op_args args =3D {0}; =20 - if (refcount_dec_and_test(&private->incoming.count)) { - struct liveupdate_flb_op_args args =3D {0}; + scoped_guard(mutex, &private->incoming.lock) { + if (!refcount_dec_and_test(&private->incoming.count)) + return; =20 if (!private->incoming.retrieved) { int err =3D luo_flb_retrieve_one(flb); @@ -220,16 +222,14 @@ static void luo_flb_file_finish_one(struct liveupdate= _flb *flb) return; } =20 - scoped_guard(mutex, &private->incoming.lock) { - args.flb =3D flb; - args.obj =3D private->incoming.obj; - flb->ops->finish(&args); + args.flb =3D flb; + args.obj =3D private->incoming.obj; + flb->ops->finish(&args); =20 - private->incoming.data =3D 0; - private->incoming.obj =3D NULL; - private->incoming.finished =3D true; - module_put(flb->ops->owner); - } + private->incoming.data =3D 0; + private->incoming.obj =3D NULL; + private->incoming.finished =3D true; + module_put(flb->ops->owner); } } =20 @@ -312,7 +312,7 @@ void luo_flb_file_finish(struct liveupdate_file_handler= *fh) =20 guard(rwsem_read)(&luo_register_rwlock); list_for_each_entry_reverse(iter, flb_list, list) - luo_flb_file_finish_one(iter->flb); + liveupdate_flb_put_incoming(iter->flb); } =20 static void luo_flb_unregister_one(struct liveupdate_file_handler *fh, @@ -509,6 +509,8 @@ int liveupdate_flb_get_incoming(struct liveupdate_flb *= flb, void **objp) if (!liveupdate_enabled()) return -EOPNOTSUPP; =20 + guard(mutex)(&private->incoming.lock); + if (!private->incoming.obj) { int err =3D luo_flb_retrieve_one(flb); =20 @@ -516,7 +518,7 @@ int liveupdate_flb_get_incoming(struct liveupdate_flb *= flb, void **objp) return err; } =20 - guard(mutex)(&private->incoming.lock); + refcount_inc(&private->incoming.count); *objp =3D private->incoming.obj; =20 return 0; diff --git a/lib/tests/liveupdate.c b/lib/tests/liveupdate.c index e4b0ecbee32f..4c08a7c6fb78 100644 --- a/lib/tests/liveupdate.c +++ b/lib/tests/liveupdate.c @@ -105,6 +105,9 @@ static void liveupdate_test_init(void) pr_err("liveupdate_flb_get_incoming for %s failed: %pe\n", flb->compatible, ERR_PTR(err)); } + + if (!err) + liveupdate_flb_put_incoming(flb); } initialized =3D true; } --=20 2.54.0.rc2.544.gc7ae2d5bb8-goog