From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm2-f8.google.com (mail-wm2-f8.google.com [74.125.225.136]) (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 3CF9C373BE6 for ; Mon, 27 Jul 2026 12:10:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.136 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785154232; cv=none; b=sGnRTHuEpa8v2KVhYJogFYPLL0Oup0VGTtMpVGSC43wZPabVg7JJp+6chHGhkApm+jqk7p97euo6/W9sUHjCXLeEnWvMgVzf95wq6WjBrrG67J5Tu7lXWExgmbmW5e/uM7O8YhFTeXb4+j/eB8bGBeBu9zyRxz8WIS6V1+/ZZTQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785154232; c=relaxed/simple; bh=41m4eZr98ZS4+ChcPMOE6llvIl9fhqsMcrIQxRy1N9w=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=ewwQrFP2nWdas+v1TaXaFIwqX+7e4BpMENeLnBII/T2IZGDnD4yfMJt0cLC4sOVBepCwYx1MgaHGbz5t7dBOvi35JUntnup/12SHnbZgi5heRmHOlEFxyr2DIut6F2zLKHpsrrfS9+5FOlj9CkodE4pGI4e3gQriT1TdpWEjMRc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ovn.org; spf=pass smtp.mailfrom=gmail.com; arc=none smtp.client-ip=74.125.225.136 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=ovn.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wm2-f8.google.com with SMTP id 5b1f17b1804b1-4956bc73c0eso11060835e9.1 for ; Mon, 27 Jul 2026 05:10:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785154228; x=1785759028; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=golEXU1+BL8SymczTDciNAwJvaEVruf5+6aSnIpz30M=; b=kYhACHLfhltpmFCyF7H0rLdS91wACxq8L3JZ5EZj7NSnC4qXI9pNOeCTfRTR2u0O47 UzMAEKdMR4uzlVnHWmHVdJl4Fo9vw9WKt8FREUoLLbWclzNOx7nyJTfzoGda/Pgp8+ZL bJXW2WiAk5qIqXc1osw65wf6QNqfIWL6OSXkewRtbb6d6WMtjzVEq3IzqeUPTj5XJvbG oLDdWprVXnRZY88NGY1qF88TMYN/2dMqStUuNgLRsUFdiEx3NMCbSk53Bp3ADgysfTZ4 nwZZhZ2/3vIkSkfdAuxebJz06X/z5U8ch3Qw3LjsNzzylmrffD3DezdfVPbuGPt783MB +qmw== X-Gm-Message-State: AOJu0YzdtpZ4mv2ljHUFwBcoEdEE+U3QFV7nj6lt9EQku6e/qNbge0Vk 1sp2UB7ELB4V+X8cwpcLcxzfj5vaKi0IQCQHLhMWQoPX31qnJmnipHfWDh8wQ1jT X-Gm-Gg: AR+sD12CrgtHpzY9sbsalIgDAyhNeqw78heO9XpJsiko0/WDElPGy3jNU7GBKBdihut SmekP/8YCKCfS8Dn5if1T6RDKKq+JZizXSEaWxnoVly3fKcVsupYkT34MXkTDdq0iEqkMblWLyK fI5VgVIkPxgIeQp0i0EXtvsep/nu2gjSOEDD2ZQy95EUGvlNuai6YwSGnxlqP2NUvM+durjHbgl 1vod2rjQU8y3tjVl82Eejz2DWLulTmGuCzKvgOr+jBidB1svz0ki4sg140mGzXk9kqT7zKJSgJX CY6S9kIu0VMpGUXWZV52XNWhQ7IlIwE4XSSkox4zmlcXeXS/WeApgxh/eKEisqVYrDuZ+xzobTb 36eTzBlTLAVz5ooP+I7Pm1YN+64prxHVo97oRgD71SwDTBwniqu76b7p9R2a9NShDngvzGCcOGl 6nW2Mg3Z0PmxQwhIweeh0V92uouv58wKX8A8ZV8kU55FX0ssSEIXn//A== X-Received: by 2002:a05:600c:1c07:b0:495:7561:a9ed with SMTP id 5b1f17b1804b1-496b56c89dcmr110977965e9.17.1785154228261; Mon, 27 Jul 2026 05:10:28 -0700 (PDT) Received: from im-t490s.redhat.com (78-80-108-129.customers.tmcz.cz. [78.80.108.129]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-496b4ee0e91sm220012685e9.4.2026.07.27.05.10.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Jul 2026 05:10:27 -0700 (PDT) From: Ilya Maximets To: netdev@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Simon Horman , Tonghao Zhang , Aaron Conole , Eelco Chaudron , dev@openvswitch.org, linux-kernel@vger.kernel.org, Ilya Maximets , stable@vger.kernel.org Subject: [PATCH net] net: openvswitch: fix potential UAF on meter attach failure Date: Mon, 27 Jul 2026 14:10:21 +0200 Message-ID: <20260727121022.198461-1-i.maximets@ovn.org> X-Mailer: git-send-email 2.54.0 Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit While attaching a newly created meter attach_meter() function makes the new meter visible to other CPUs but can still fail afterwards. On failure, it detaches the meter back and returns an error. However, this is an unexpected behavior for the ovs_meter_cmd_set() that uses a plain kfree(meter) on attach failure without waiting for RCU readers to stop using it, assuming it was never visible. This is never a problem for ovs-vswitchd as it always creates meters before creating any flows that use them. But the UAF can be triggered with a custom application using uAPI: BUG: KASAN: slab-use-after-free in ovs_meter_execute (net/openvswitch/meter.c:653) Read of size 8 at addr ffff88810d152650 by task meter/2508 Call Trace: ovs_meter_execute (net/openvswitch/meter.c:653) do_execute_actions (net/openvswitch/actions.c:1407) ovs_execute_actions (net/openvswitch/actions.c:1584) ovs_packet_cmd_execute (net/openvswitch/datapath.c:703) ... netlink_sendmsg (af_netlink.c:1900) Allocated by task 2519: __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415) ovs_meter_cmd_set (net/openvswitch/meter.c:422) ... netlink_sendmsg (af_netlink.c:1900) Freed by task 2519: kfree (mm/slub.c:2705 mm/slub.c:6405 mm/slub.c:6720) ovs_meter_cmd_set (net/openvswitch/meter.c:479) ... netlink_sendmsg (af_netlink.c:1900) Fix that by making sure attach_meter() doesn't make the meter visible until all the checks are done and the function can't fail anymore. This also makes sure the "hash" value is calculated after the potential re-sizing of the table. Reported by Trend Micro's Zero Day Initiative as ZDI-CAN-31642. Fixes: c7c4c44c9a95 ("net: openvswitch: expand the meters supported number") Cc: stable@vger.kernel.org Signed-off-by: Ilya Maximets --- net/openvswitch/meter.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/net/openvswitch/meter.c b/net/openvswitch/meter.c index a02c47277337..4aaeeae3af5b 100644 --- a/net/openvswitch/meter.c +++ b/net/openvswitch/meter.c @@ -133,18 +133,10 @@ static void dp_meter_instance_remove(struct dp_meter_instance *ti, static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter) { - struct dp_meter_instance *ti = rcu_dereference_ovsl(tbl->ti); - u32 hash = meter_hash(ti, meter->id); + struct dp_meter_instance *ti; + u32 hash; int err; - /* In generally, slots selected should be empty, because - * OvS uses id-pool to fetch a available id. - */ - if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash]))) - return -EBUSY; - - dp_meter_instance_insert(ti, meter); - /* That function is thread-safe. */ tbl->count++; if (tbl->count >= tbl->max_meters_allowed) { @@ -152,16 +144,29 @@ static int attach_meter(struct dp_meter_table *tbl, struct dp_meter *meter) goto attach_err; } - if (tbl->count >= ti->n_meters && - dp_meter_instance_realloc(tbl, ti->n_meters * 2)) { - err = -ENOMEM; + ti = rcu_dereference_ovsl(tbl->ti); + if (tbl->count >= ti->n_meters) { + err = dp_meter_instance_realloc(tbl, ti->n_meters * 2); + if (err) + goto attach_err; + + ti = rcu_dereference_ovsl(tbl->ti); + } + + hash = meter_hash(ti, meter->id); + + /* In general, selected slots should be empty, because + * OvS uses id-pool to fetch available ids. + */ + if (unlikely(rcu_dereference_ovsl(ti->dp_meters[hash]))) { + err = -EBUSY; goto attach_err; } + dp_meter_instance_insert(ti, meter); return 0; attach_err: - dp_meter_instance_remove(ti, meter); tbl->count--; return err; } -- 2.55.0