From mboxrd@z Thu Jan 1 00:00:00 1970 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-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 global state") Signed-off-by: David Matlack --- 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_handler *fh, struct liveupdate_flb *flb); 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); #else /* CONFIG_LIVEUPDATE */ @@ -280,6 +282,10 @@ static inline int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, return -EOPNOTSUPP; } +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 = false; int err; - guard(mutex)(&private->incoming.lock); + lockdep_assert_held(&private->incoming.lock); if (private->incoming.finished) return -ENODATA; @@ -206,12 +206,14 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb) return 0; } -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 = luo_flb_get_private(flb); + struct liveupdate_flb_op_args args = {0}; - if (refcount_dec_and_test(&private->incoming.count)) { - struct liveupdate_flb_op_args args = {0}; + scoped_guard(mutex, &private->incoming.lock) { + if (!refcount_dec_and_test(&private->incoming.count)) + return; if (!private->incoming.retrieved) { int err = luo_flb_retrieve_one(flb); @@ -220,16 +222,14 @@ static void luo_flb_file_finish_one(struct liveupdate_flb *flb) return; } - scoped_guard(mutex, &private->incoming.lock) { - args.flb = flb; - args.obj = private->incoming.obj; - flb->ops->finish(&args); + args.flb = flb; + args.obj = private->incoming.obj; + flb->ops->finish(&args); - private->incoming.data = 0; - private->incoming.obj = NULL; - private->incoming.finished = true; - module_put(flb->ops->owner); - } + private->incoming.data = 0; + private->incoming.obj = NULL; + private->incoming.finished = true; + module_put(flb->ops->owner); } } @@ -312,7 +312,7 @@ void luo_flb_file_finish(struct liveupdate_file_handler *fh) 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); } 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; + guard(mutex)(&private->incoming.lock); + if (!private->incoming.obj) { int err = luo_flb_retrieve_one(flb); @@ -516,7 +518,7 @@ int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp) return err; } - guard(mutex)(&private->incoming.lock); + refcount_inc(&private->incoming.count); *objp = private->incoming.obj; 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 = true; } -- 2.54.0.rc2.544.gc7ae2d5bb8-goog