Received: by 2002:a05:7412:8d1c:b0:fa:4c10:6cad with SMTP id bj28csp32738rdb; Tue, 16 Jan 2024 14:02:34 -0800 (PST) X-Google-Smtp-Source: AGHT+IHZ09g82b/2/1NaEUBPYneRU1pLUdPkWGWSqRbGvrJpLFCndRTtuQ5Y/6XnztxHL/XYhoqt X-Received: by 2002:a05:622a:1c4:b0:429:f453:dcf8 with SMTP id t4-20020a05622a01c400b00429f453dcf8mr3727707qtw.87.1705442553970; Tue, 16 Jan 2024 14:02:33 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1705442553; cv=pass; d=google.com; s=arc-20160816; b=ATWqGG6n6LiSqLrOsv2R1UtF8S+cXydZgLRvjm1gYkBDYqsA9aDL2FuBe9U8j/QV0u hCKPzgnhpiOEfHCtYup0xodMiJX2394IrD1q+rUlm4Wxpv1u85xnkjjJTQm5jp/uljK5 FGE5fW47iuGrjx7wnpbHg1dsHPOmvaXElqplxB2sQkFwW3c/Ot1RRsPVCW7INMGHJFu8 V2wsqRvHqh68lCFNzEcuCuDAO0BkeW/6bb+5HvsXcuw0/l+4N4crXH1BGCKh0YQvBeYh dlbNe5TSF5eXxyDcSJxoTkMpDYqEPNsIOijkCnq36OUFhv94T+e0I01jsDnKYbKZp08x yAvQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=XSdwMiWNVwQgywerYhdQGqBlV5DqMrC6i2KiFVju0+Y=; fh=t9C8SyKTrM+i0OCrW3ZViOupZGC3V28uX53am9xua+g=; b=0qvxt30XXdIuJx+t+EjYmJdezcGFg5R+NLoEmDmCxzB1BiYgRYePz354XNL2/uR5V9 BJcDydjaRVge2xOld+l71U23ZduqUOwAt107h2PpjuAxHkCe2Vs20oiBcV8iUSo9GHz1 M9qbDsCU30oUuAsmmE5XtC4f5JAglaT/5UNrg3rB6Tkez6e2Ql04NYy3jvU0mBUPj9jH OFygBakC4cUEoxw2ejHjtXS7Y32JkM6fXEJBRay7Fpq7Rez/zJi/2X4fbXzVVD0+bQo2 uoc6EYiQvWQrDcGYACraHIfgBgpZrQMdcJXZ4PU7SXFSjEFgsvdBO3pdXt3VLx6zTD2G 2eQg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=fGM2yjgO; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-28218-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-28218-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id a2-20020a05620a102200b00783070846e9si10364004qkk.385.2024.01.16.14.02.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Jan 2024 14:02:33 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-28218-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=fGM2yjgO; arc=pass (i=1 dkim=pass dkdomain=kernel.org); spf=pass (google.com: domain of linux-kernel+bounces-28218-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-28218-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id AA1AF1C26FAC for ; Tue, 16 Jan 2024 22:02:33 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A457C67741; Tue, 16 Jan 2024 20:04:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fGM2yjgO" Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 978DD67729; Tue, 16 Jan 2024 20:04:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705435487; cv=none; b=XiQuUFKtquq+sELmfvEEKHvx4bAoj4LOp0iDPBV8DbeUzJ0Ugovcl3aMdHQws7PWqNpc29alTrdPiz7zz5qemhgY8yDCMQ4sJzVFXtwp2Ua197+sbyFmWu74zSbiinc7IE9cSQpn3/Rvi0LcBjime717E7UikngzKEchLXG2VsA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1705435487; c=relaxed/simple; bh=bnE2wWvjkbJ9xzsnbTTH261tLlfBZGLqvhUGY8+P9mc=; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID: X-Mailer:In-Reply-To:References:MIME-Version:X-stable: X-Patchwork-Hint:X-stable-base:Content-Transfer-Encoding; b=fg+uby55QHNWd77tU4GwbxaAilgzskhYgAENVihbGaVUC9iyr01WMaZfBQGGgqKKaQ+x5oZLgS1A6hhNdALM2HBOTwl6lzoOTUStUFCYcn/Zu7mzY9olW14pIpxeT9kGFm+fdqwxyCFSwIIQNpucJXf7VrCRGlm4uMyl7RCK3xY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fGM2yjgO; arc=none smtp.client-ip=10.30.226.201 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32F2EC43394; Tue, 16 Jan 2024 20:04:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1705435487; bh=bnE2wWvjkbJ9xzsnbTTH261tLlfBZGLqvhUGY8+P9mc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fGM2yjgOS7s0Rgy4YGLujMNYqN9CYkEOfXS1c7vFO9AFIcSxYP4wZhgB1lbDJH7Gp 275i0pchy1hKzkm6u4GLDSOstGNe18PZ/DwmL5KuML3Ff9rtiqsrA4DXH4JIxhFPa+ qwngeM/FAaFleWPA0i2SLDWBbCHAKzydDxg70odq6pGd1FELiUfbEJu3u+VVKjWwDO An9pf+TqumXSJQeSquveYH7ZtxVb+Ndsq57I+eyA8k9FH36AqKHq2fLpr5lCMMRYLo 7fcoU33/O0H4yDzYPe4D+Owsiw+7WSbjLzqFXNmLUZgN1MF9W2AvmK8DUitAoQeFSz zNVDXty49imJw== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Hou Tao , Alexei Starovoitov , Sasha Levin , daniel@iogearbox.net, andrii@kernel.org, bpf@vger.kernel.org Subject: [PATCH AUTOSEL 4.19 07/22] bpf: Add map and need_defer parameters to .map_fd_put_ptr() Date: Tue, 16 Jan 2024 15:04:01 -0500 Message-ID: <20240116200432.260016-7-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240116200432.260016-1-sashal@kernel.org> References: <20240116200432.260016-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 4.19.305 Content-Transfer-Encoding: 8bit From: Hou Tao [ Upstream commit 20c20bd11a0702ce4dc9300c3da58acf551d9725 ] map is the pointer of outer map, and need_defer needs some explanation. need_defer tells the implementation to defer the reference release of the passed element and ensure that the element is still alive before the bpf program, which may manipulate it, exits. The following three cases will invoke map_fd_put_ptr() and different need_defer values will be passed to these callers: 1) release the reference of the old element in the map during map update or map deletion. The release must be deferred, otherwise the bpf program may incur use-after-free problem, so need_defer needs to be true. 2) release the reference of the to-be-added element in the error path of map update. The to-be-added element is not visible to any bpf program, so it is OK to pass false for need_defer parameter. 3) release the references of all elements in the map during map release. Any bpf program which has access to the map must have been exited and released, so need_defer=false will be OK. These two parameters will be used by the following patches to fix the potential use-after-free problem for map-in-map. Signed-off-by: Hou Tao Link: https://lore.kernel.org/r/20231204140425.1480317-3-houtao@huaweicloud.com Signed-off-by: Alexei Starovoitov Signed-off-by: Sasha Levin --- include/linux/bpf.h | 6 +++++- kernel/bpf/arraymap.c | 12 +++++++----- kernel/bpf/hashtab.c | 6 +++--- kernel/bpf/map_in_map.c | 2 +- kernel/bpf/map_in_map.h | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 766ea96bf5b8..269754890879 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -44,7 +44,11 @@ struct bpf_map_ops { /* funcs called by prog_array and perf_event_array map */ void *(*map_fd_get_ptr)(struct bpf_map *map, struct file *map_file, int fd); - void (*map_fd_put_ptr)(void *ptr); + /* If need_defer is true, the implementation should guarantee that + * the to-be-put element is still alive before the bpf program, which + * may manipulate it, exists. + */ + void (*map_fd_put_ptr)(struct bpf_map *map, void *ptr, bool need_defer); u32 (*map_gen_lookup)(struct bpf_map *map, struct bpf_insn *insn_buf); u32 (*map_fd_sys_lookup_elem)(void *ptr); void (*map_seq_show_elem)(struct bpf_map *map, void *key, diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 0c17aab3ce5f..44f53c06629e 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -469,7 +469,7 @@ int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file, old_ptr = xchg(array->ptrs + index, new_ptr); if (old_ptr) - map->ops->map_fd_put_ptr(old_ptr); + map->ops->map_fd_put_ptr(map, old_ptr, true); return 0; } @@ -485,7 +485,7 @@ static int fd_array_map_delete_elem(struct bpf_map *map, void *key) old_ptr = xchg(array->ptrs + index, NULL); if (old_ptr) { - map->ops->map_fd_put_ptr(old_ptr); + map->ops->map_fd_put_ptr(map, old_ptr, true); return 0; } else { return -ENOENT; @@ -509,8 +509,9 @@ static void *prog_fd_array_get_ptr(struct bpf_map *map, return prog; } -static void prog_fd_array_put_ptr(void *ptr) +static void prog_fd_array_put_ptr(struct bpf_map *map, void *ptr, bool need_defer) { + /* bpf_prog is freed after one RCU or tasks trace grace period */ bpf_prog_put(ptr); } @@ -598,8 +599,9 @@ static void *perf_event_fd_array_get_ptr(struct bpf_map *map, return ee; } -static void perf_event_fd_array_put_ptr(void *ptr) +static void perf_event_fd_array_put_ptr(struct bpf_map *map, void *ptr, bool need_defer) { + /* bpf_perf_event is freed after one RCU grace period */ bpf_event_entry_free_rcu(ptr); } @@ -640,7 +642,7 @@ static void *cgroup_fd_array_get_ptr(struct bpf_map *map, return cgroup_get_from_fd(fd); } -static void cgroup_fd_array_put_ptr(void *ptr) +static void cgroup_fd_array_put_ptr(struct bpf_map *map, void *ptr, bool need_defer) { /* cgroup_put free cgrp after a rcu grace period */ cgroup_put(ptr); diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c index 3f3ed33bd2fd..8e379b667a0f 100644 --- a/kernel/bpf/hashtab.c +++ b/kernel/bpf/hashtab.c @@ -677,7 +677,7 @@ static void htab_put_fd_value(struct bpf_htab *htab, struct htab_elem *l) if (map->ops->map_fd_put_ptr) { ptr = fd_htab_map_get_ptr(map, l); - map->ops->map_fd_put_ptr(ptr); + map->ops->map_fd_put_ptr(map, ptr, true); } } @@ -1337,7 +1337,7 @@ static void fd_htab_map_free(struct bpf_map *map) hlist_nulls_for_each_entry_safe(l, n, head, hash_node) { void *ptr = fd_htab_map_get_ptr(map, l); - map->ops->map_fd_put_ptr(ptr); + map->ops->map_fd_put_ptr(map, ptr, false); } } @@ -1378,7 +1378,7 @@ int bpf_fd_htab_map_update_elem(struct bpf_map *map, struct file *map_file, ret = htab_map_update_elem(map, key, &ptr, map_flags); if (ret) - map->ops->map_fd_put_ptr(ptr); + map->ops->map_fd_put_ptr(map, ptr, false); return ret; } diff --git a/kernel/bpf/map_in_map.c b/kernel/bpf/map_in_map.c index 9670ee5ee74e..051c5e40792c 100644 --- a/kernel/bpf/map_in_map.c +++ b/kernel/bpf/map_in_map.c @@ -102,7 +102,7 @@ void *bpf_map_fd_get_ptr(struct bpf_map *map, return inner_map; } -void bpf_map_fd_put_ptr(void *ptr) +void bpf_map_fd_put_ptr(struct bpf_map *map, void *ptr, bool need_defer) { /* ptr->ops->map_free() has to go through one * rcu grace period by itself. diff --git a/kernel/bpf/map_in_map.h b/kernel/bpf/map_in_map.h index 6183db9ec08c..1e652a7bf60e 100644 --- a/kernel/bpf/map_in_map.h +++ b/kernel/bpf/map_in_map.h @@ -18,7 +18,7 @@ bool bpf_map_meta_equal(const struct bpf_map *meta0, const struct bpf_map *meta1); void *bpf_map_fd_get_ptr(struct bpf_map *map, struct file *map_file, int ufd); -void bpf_map_fd_put_ptr(void *ptr); +void bpf_map_fd_put_ptr(struct bpf_map *map, void *ptr, bool need_defer); u32 bpf_map_fd_sys_lookup_elem(void *ptr); #endif -- 2.43.0