From nobody Sat Feb 7 20:38:44 2026 Received: from out-187.mta1.migadu.com (out-187.mta1.migadu.com [95.215.58.187]) (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 CC31F23C4F3 for ; Tue, 2 Dec 2025 15:31:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.187 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764689478; cv=none; b=BxjSRjQ+wCu0HynGCcivm7XnbFZsIlr6ooB0ieiC3meGG/kyMrVoDgvCXqpHsN8OcHnbBaS2hCvI1Lb5LbbCYPkzi1wmAPMXd4xmvwTn9qy6U6qATyKx7eGEFjJcaZr/fNMJLQi8GkbVqyrJjU2+Ri1Edp4oRRSMk4enlwh45Vo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764689478; c=relaxed/simple; bh=FN2gA8fkIYUS0LqgXHQnxjlfDHzrt8HJx+BMYr314go=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gScfQbTHDMqzjsCJUc4N+IB1ZPo5pOYDDez+YE6Ly+KNqas9HxfP94ChVsBDdvWzWdI4JyUpZAql1ugK2HDxscqjP+BaWvJ6qexBd/wU0D7esSGbipjT5vUcQWRL8ZFKHpo6LV/6StrOfU031KC7gpZb2QadH+ejhnOyhS8neHg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=dC3O3Vn9; arc=none smtp.client-ip=95.215.58.187 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="dC3O3Vn9" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1764689474; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=M4fcPewQ4q2OL49xVGJhdtOlnQP+HPuy19sXc+YDSmk=; b=dC3O3Vn9BkO4H9HHemRWPYpHByHl9wkaxIyAunmFQ9DySvEAOXF9shCbVrYAWvZSuCJquU X1oRv7XfTQKUJVra5Wem6ySlZ8Td41jdlghcnkDwk3XJ4lzBPnlu14fghILr1mg+7T8V7F 4col36Vi8Cid4rAO0dpjNU5MkdnkQXc= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan , Leon Hwang , Saket Kumar Bhaskar , "David S . Miller" , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next 1/3] bpf: Avoid unintended eviction when updating lru_hash maps Date: Tue, 2 Dec 2025 23:30:30 +0800 Message-ID: <20251202153032.10118-2-leon.hwang@linux.dev> In-Reply-To: <20251202153032.10118-1-leon.hwang@linux.dev> References: <20251202153032.10118-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" When updating an existing element in lru_hash maps, the current implementation always calls prealloc_lru_pop() to get a new node before checking if the key already exists. If the map is full, this triggers LRU eviction and removes an existing element, even though the update operation only needs to modify the value of an existing key in-place. This is problematic because: 1. Users may unexpectedly lose entries when doing simple value updates 2. The eviction overhead is unnecessary for existing key updates Fix this by first checking if the key exists before allocating a new node. If the key is found, update the value in-place, refresh the LRU reference, and return immediately without triggering any eviction. Fixes: 29ba732acbee ("bpf: Add BPF_MAP_TYPE_LRU_HASH") Signed-off-by: Leon Hwang --- kernel/bpf/hashtab.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index c8a9b27f8663..fb624aa76573 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -1207,6 +1207,27 @@ static long htab_lru_map_update_elem(struct bpf_map = *map, void *key, void *value b =3D __select_bucket(htab, hash); head =3D &b->head; =20 + ret =3D htab_lock_bucket(b, &flags); + if (ret) + goto err_lock_bucket; + + l_old =3D lookup_elem_raw(head, hash, key, key_size); + + ret =3D check_flags(htab, l_old, map_flags); + if (ret) + goto err; + + if (l_old) { + bpf_lru_node_set_ref(&l_old->lru_node); + copy_map_value(&htab->map, htab_elem_value(l_old, map->key_size), value); + check_and_free_fields(htab, l_old); + } + + htab_unlock_bucket(b, flags); + + if (l_old) + return 0; + /* For LRU, we need to alloc before taking bucket's * spinlock because getting free nodes from LRU may need * to remove older elements from htab and this removal --=20 2.52.0