From patchwork Fri Nov 29 13:28:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888678 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (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 40E8619DF99 for ; Fri, 29 Nov 2024 13:25:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886758; cv=none; b=A96ZVZG6k5LUQxza++HbQmsI6SY6eZX3MeVZGoCtifK/QKD4+PoSnDCi4TMCadtT78slWIQ2o+vnF0faxzR0VC8QlX/egYtrtMKTgEIPSST6+35j5DiE3a9YLaFSRxV5w9qU3SrJRjzRtbAIrvWQMxEk5LVFWtRY0AM4t5Uy3Oc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886758; c=relaxed/simple; bh=+3YHL5ETaHgemL9MKXcPtQyVjffmElI54Yw7T+argj0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=GvQsJHxFgJpDdlpn1cMrwdVsXFN8jpihR+QhkQjYB0H/Yi0xW59tInGt60zaz2zz/WJhCGYrktFmaCCnhQNNPmBU3ksUlmDL1+S+xuo1gfMeZxlBMxmyxTwBCuZamO7/y/jefVMpW87VFxaIC6UU5XMybfcaUA3h/xLbyTJs86k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=YXwPXR8L; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="YXwPXR8L" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-aa5325af6a0so244135966b.2 for ; Fri, 29 Nov 2024 05:25:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886754; x=1733491554; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ggpXSD19Jf6A3piaA1js1qwFVJYAvd9BbmdJF8eAUGg=; b=YXwPXR8LxV/0R3XbiLP2XLKhSNXweKq5fOAVfXpxDdPgYJ1Um2Ql5yOOcqHPEl2Ldl DN0s/F0kFbRizFml91zskX14I4Da01PsKjrtSkZw1Q+HAJ4WohfpaPhF2PnupV/ZVAHk AU+pc1s1N6cQ27AnMoIpQ8Ka/9DDcgcDKyIecjH4KFDt2QOdTrinRoWAmEIkcgxUCBd3 ntkh1Utrjd/o66QeCsra7RAwTA5Ei/T1mbTYMPqpoWbPY7SwovlLfIi987Kh35vit4jI 7nsAbNVFvBoHI1bt6dFPwoMTcuzU4scvpzJWJca6y5JwdAvjaxXCo4ok1DWQEgwGuF+9 t5QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886754; x=1733491554; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ggpXSD19Jf6A3piaA1js1qwFVJYAvd9BbmdJF8eAUGg=; b=TbipzSeL8xIsQeK+0Hc9mMmI553r+G6JJgo4cXne6VO7eMvj2+j9hvZYvwi7LDho4U XQNn0OVOlfgIxYdxAm6G/QpB7SlbKj5B188kTuS2+Q/HUQmsfvZa51m1QYyUvUciHhGp eZb7ZZ1WiOHAsP9X5VL92H/GOIR+Rm1I+jFJ5vOU/AVMgtkn2fTepPH4ApTODcy8UVdp 6S245WUrZYzpbbgRx5gEG9BWvLtF8ZKBA6FkyItIAtViV/o/BApIFv2fGin+tpN0MIpm NZxD55HLL9AodJLPidvBeWBCFIi5F+fF+46BTNa3vXUGnj/LJMW5aknh8qb0PEfPdGQs AhaQ== X-Gm-Message-State: AOJu0YyzENcdiptzLcQRSTvg18qL8p85ySLJfc1vWIIKgqHhdVNjs1Vh wIqpo8uEfjRn+pb2OFSWNh5V6hHkmLL30uQHgEeIgsAGxT+kRGxTa0FZVsFziOolwdCX54sdhbf + X-Gm-Gg: ASbGncvxuOIBEkymlHx47yTCEJEfWKoW6SnWUkeH1NHRgd8JeX8SSOG8rxseEaQUlTO O5jIXn5HCd2oJCA3ssz9FH7az6mNIs2Q1ZigG+divRmWDZNcWIPTtID7jSNB8HGrbcm1zOSWkre r1xTtVX9OJdg5ABbAxbbraFQ42BsGMvYt06iAyc6oo0jCc83AAHNBHtPM121LSEXxz4/q6ZLruV avKc0pYsRoILECLsidaAXYFOuQ9F0LM1GYqllZTzRgxQfcz40H/Mp7BS7KHStY= X-Google-Smtp-Source: AGHT+IGtIvdoSrCeS5AQoFq6igE84lRLxefPXvurQJRZfZPoQArYghQf+o6//zjZR5WWzd+YOSvsBA== X-Received: by 2002:a17:906:3145:b0:aa4:9ab1:196c with SMTP id a640c23a62f3a-aa580edf60bmr745364466b.9.1732886754275; Fri, 29 Nov 2024 05:25:54 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:53 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov Subject: [PATCH v3 bpf-next 1/7] bpf: add a __btf_get_by_fd helper Date: Fri, 29 Nov 2024 13:28:07 +0000 Message-Id: <20241129132813.1452294-2-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Add a new helper to get a pointer to a struct btf from a file descriptor. This helper doesn't increase a refcnt. Add a comment explaining this and pointing to a corresponding function which does take a reference. Signed-off-by: Anton Protopopov --- include/linux/bpf.h | 17 +++++++++++++++++ include/linux/btf.h | 2 ++ kernel/bpf/btf.c | 13 ++++--------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 3ace0d6227e3..fcb4ecd9d1fd 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -2294,6 +2294,14 @@ void __bpf_obj_drop_impl(void *p, const struct btf_record *rec, bool percpu); struct bpf_map *bpf_map_get(u32 ufd); struct bpf_map *bpf_map_get_with_uref(u32 ufd); +/* + * The __bpf_map_get() and __btf_get_by_fd() functions parse a file + * descriptor and return a corresponding map or btf object. + * Their names are double underscored to emphasize the fact that they + * do not increase refcnt. To also increase refcnt use corresponding + * bpf_map_get() and btf_get_by_fd() functions. + */ + static inline struct bpf_map *__bpf_map_get(struct fd f) { if (fd_empty(f)) @@ -2303,6 +2311,15 @@ static inline struct bpf_map *__bpf_map_get(struct fd f) return fd_file(f)->private_data; } +static inline struct btf *__btf_get_by_fd(struct fd f) +{ + if (fd_empty(f)) + return ERR_PTR(-EBADF); + if (unlikely(fd_file(f)->f_op != &btf_fops)) + return ERR_PTR(-EINVAL); + return fd_file(f)->private_data; +} + void bpf_map_inc(struct bpf_map *map); void bpf_map_inc_with_uref(struct bpf_map *map); struct bpf_map *__bpf_map_inc_not_zero(struct bpf_map *map, bool uref); diff --git a/include/linux/btf.h b/include/linux/btf.h index 4214e76c9168..69159e649675 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -4,6 +4,7 @@ #ifndef _LINUX_BTF_H #define _LINUX_BTF_H 1 +#include #include #include #include @@ -143,6 +144,7 @@ void btf_get(struct btf *btf); void btf_put(struct btf *btf); const struct btf_header *btf_header(const struct btf *btf); int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_sz); + struct btf *btf_get_by_fd(int fd); int btf_get_info_by_fd(const struct btf *btf, const union bpf_attr *attr, diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index e7a59e6462a9..ad5310fa1d3b 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -7743,17 +7743,12 @@ int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size) struct btf *btf_get_by_fd(int fd) { - struct btf *btf; CLASS(fd, f)(fd); + struct btf *btf; - if (fd_empty(f)) - return ERR_PTR(-EBADF); - - if (fd_file(f)->f_op != &btf_fops) - return ERR_PTR(-EINVAL); - - btf = fd_file(f)->private_data; - refcount_inc(&btf->refcnt); + btf = __btf_get_by_fd(f); + if (!IS_ERR(btf)) + refcount_inc(&btf->refcnt); return btf; } From patchwork Fri Nov 29 13:28:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888679 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-lj1-f181.google.com (mail-lj1-f181.google.com [209.85.208.181]) (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 DFEF719E806 for ; Fri, 29 Nov 2024 13:25:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886759; cv=none; b=eLyBtpmGg75J3ZMYVdwFPJ1guFFA2t67k7SaTW33aKXiO7zuVN+X4SneoLsxct3+MLxNwxnihsxPPaOpiTMpL1iQKIF3lrYUQH7ticjea9ei3axOgAkQX81p38dqN+tOM/m0VjdccaI2iByrdcALYSS7nVmahX+RTDioJZuQjks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886759; c=relaxed/simple; bh=RaCURLyhvuUv4IEXFUW5A6FO4E9KSRJiAy8ykc7vNQI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=aVhMZRoZzMsezUmv5ot8eIJoDJtCOB42QG0kUc+D0W/POv2ffxvox8m4IcXjxIwHcUotTIetg1BexoldE4BZQYmQInqO7W61Wsw1LmU8qQVUG5Mh7W3ZAuH72uVDwxNUZWXmyAxE3KfBGfzJK4LUsOGHFBfr8p7O1EWHiKSDaH4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=UTpOyDEA; arc=none smtp.client-ip=209.85.208.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="UTpOyDEA" Received: by mail-lj1-f181.google.com with SMTP id 38308e7fff4ca-2ffdbc0c103so30244831fa.3 for ; Fri, 29 Nov 2024 05:25:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886755; x=1733491555; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=96O2iIJ6kHVU2T0b9pQtLYj8nAEcwSxIqjPYwkm5vuA=; b=UTpOyDEAeS+/u0ok2jOjAZLZOFh4opjoclSeL6YG5Ej3WK6HVgKC+uY+Cf8mMn4z3P XEEXM1XbiYE+a0LE/4puRBCtMZR+AnN9U1/oq63V+Bh4BcO+Smh4+IJTtXVseAhMZENc +EaGwFGQDQjYQvbUOYZ1vMOZlaPCQ4sjnNUTprZf7ghe13Rm7vL3XbJaG078czJfVXZ0 jHb3P3RypcsfrOHf0Aen4c6pnLB3kqOGCyzT0ZTCrY022cN/9qdKZu6b4hq+lcK1v/ls xM+oOVY6QN78eiW6B+d9rhrVNYIUA4bG2U5kmoXzLKfDo702qrJVCY6jhaX36Gd5tJu/ L09A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886755; x=1733491555; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=96O2iIJ6kHVU2T0b9pQtLYj8nAEcwSxIqjPYwkm5vuA=; b=inxYqa3dqMP8GSxpC7EEoG68zOuRk/8RdC8LTsKPUPMqXgzkvxGoR13jFhxe4vCEkG FOFUYCzhgODmnr+OyIGU1S90V64dzmcUs8ABhjMHnKvxsjbMOGWwtgFoyRJKdYESGDru Kla9/sddE7C+QEzyozXsAfyrAN4ALVpIADvlNgcBLaVgxgSu3YRnHYM9QHKt6ZTfixJO hbDVN7X2mqL4XPYGXOC9LhgqDfdFAtP1ip06ksSDwXT4icKPFhvFpSv7zwoIOKxh+ok9 jTN7ly4QSioE/ZzjvK4FJ32iR7JZaRaB7IMdYCKAV5fN9qU/zLE+vqtdsZZC663BFfco Fy6w== X-Gm-Message-State: AOJu0YyjUlc903xLu+jqJODaDDc7SsWIYteGFrG3L6nCxi/4lgdnrxZh jrp6nX6ykJJH04cIuXD3rFsu18nkG/4ai8mdo+SGjTZmlCSL+4uLlm9XPD9rEL4eZQTZWyAxwyV D X-Gm-Gg: ASbGncvOPsdNRWvYQauTgqN159YaWtHHw3RQCCLUzrZ6eSGxN10/6LKH4uRHwidRi0m gudklibJ/HNt9//VNh8EGkqP7RJ/ph68IZEuWBv/lL5CZb+M+GkDzHt2ZnA0FFfhlDJPqcRzrlQ rkguh9g0R3tGQ/OpF54xt05rBO++84GK/Q3pZk7tNgfSIdN7icptnjOuzPaBPC+CXpEObs4Fwfc Ty4yvLO8y8cE034PzTvGzI86pIsU7iMnjuGz7yGalwMU4MUDP3AGq5wLvL57aQ= X-Google-Smtp-Source: AGHT+IHsc4sWzMYjsyeeP/NEOO/1Lm2q/czoCzOdPH/XUCNxNRfmjamwhNonmu+HooA0algDMHQ1/g== X-Received: by 2002:a2e:ab0a:0:b0:2fb:3df8:6a8c with SMTP id 38308e7fff4ca-2ffd604aa06mr94236891fa.23.1732886755355; Fri, 29 Nov 2024 05:25:55 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:54 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov , Andrii Nakryiko Subject: [PATCH v3 bpf-next 2/7] bpf: move map/prog compatibility checks Date: Fri, 29 Nov 2024 13:28:08 +0000 Message-Id: <20241129132813.1452294-3-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Move some inlined map/prog compatibility checks from the resolve_pseudo_ldimm64() function to the dedicated check_map_prog_compatibility() function. Call the latter function from the add_used_map_from_fd() function directly. This simplifies code and optimizes logic a bit, as before these changes the check_map_prog_compatibility() function was executed on every map usage, which doesn't make sense, as it doesn't include any per-instruction checks, only map type vs. prog type. (This patch also simplifies a consequent patch which will call the add_used_map_from_fd() function from another code path.) Signed-off-by: Anton Protopopov Acked-by: Andrii Nakryiko --- kernel/bpf/verifier.c | 101 +++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 55 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 1c4ebb326785..8e034a22aa2a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -19064,6 +19064,12 @@ static bool is_tracing_prog_type(enum bpf_prog_type type) } } +static bool bpf_map_is_cgroup_storage(struct bpf_map *map) +{ + return (map->map_type == BPF_MAP_TYPE_CGROUP_STORAGE || + map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE); +} + static int check_map_prog_compatibility(struct bpf_verifier_env *env, struct bpf_map *map, struct bpf_prog *prog) @@ -19142,25 +19148,48 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env, return -EINVAL; } - return 0; -} + if (bpf_map_is_cgroup_storage(map) && + bpf_cgroup_storage_assign(env->prog->aux, map)) { + verbose(env, "only one cgroup storage of each type is allowed\n"); + return -EBUSY; + } -static bool bpf_map_is_cgroup_storage(struct bpf_map *map) -{ - return (map->map_type == BPF_MAP_TYPE_CGROUP_STORAGE || - map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE); + if (map->map_type == BPF_MAP_TYPE_ARENA) { + if (env->prog->aux->arena) { + verbose(env, "Only one arena per program\n"); + return -EBUSY; + } + if (!env->allow_ptr_leaks || !env->bpf_capable) { + verbose(env, "CAP_BPF and CAP_PERFMON are required to use arena\n"); + return -EPERM; + } + if (!env->prog->jit_requested) { + verbose(env, "JIT is required to use arena\n"); + return -EOPNOTSUPP; + } + if (!bpf_jit_supports_arena()) { + verbose(env, "JIT doesn't support arena\n"); + return -EOPNOTSUPP; + } + env->prog->aux->arena = (void *)map; + if (!bpf_arena_get_user_vm_start(env->prog->aux->arena)) { + verbose(env, "arena's user address must be set via map_extra or mmap()\n"); + return -EINVAL; + } + } + + return 0; } /* Add map behind fd to used maps list, if it's not already there, and return - * its index. Also set *reused to true if this map was already in the list of - * used maps. + * its index. * Returns <0 on error, or >= 0 index, on success. */ -static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd, bool *reused) +static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd) { CLASS(fd, f)(fd); struct bpf_map *map; - int i; + int i, err; map = __bpf_map_get(f); if (IS_ERR(map)) { @@ -19169,12 +19198,9 @@ static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd, bool *reus } /* check whether we recorded this map already */ - for (i = 0; i < env->used_map_cnt; i++) { - if (env->used_maps[i] == map) { - *reused = true; + for (i = 0; i < env->used_map_cnt; i++) + if (env->used_maps[i] == map) return i; - } - } if (env->used_map_cnt >= MAX_USED_MAPS) { verbose(env, "The total number of maps per program has reached the limit of %u\n", @@ -19182,6 +19208,10 @@ static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd, bool *reus return -E2BIG; } + err = check_map_prog_compatibility(env, map, env->prog); + if (err) + return err; + if (env->prog->sleepable) atomic64_inc(&map->sleepable_refcnt); @@ -19192,7 +19222,6 @@ static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd, bool *reus */ bpf_map_inc(map); - *reused = false; env->used_maps[env->used_map_cnt++] = map; return env->used_map_cnt - 1; @@ -19229,7 +19258,6 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env) int map_idx; u64 addr; u32 fd; - bool reused; if (i == insn_cnt - 1 || insn[1].code != 0 || insn[1].dst_reg != 0 || insn[1].src_reg != 0 || @@ -19290,7 +19318,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env) break; } - map_idx = add_used_map_from_fd(env, fd, &reused); + map_idx = add_used_map_from_fd(env, fd); if (map_idx < 0) return map_idx; map = env->used_maps[map_idx]; @@ -19298,10 +19326,6 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env) aux = &env->insn_aux_data[i]; aux->map_index = map_idx; - err = check_map_prog_compatibility(env, map, env->prog); - if (err) - return err; - if (insn[0].src_reg == BPF_PSEUDO_MAP_FD || insn[0].src_reg == BPF_PSEUDO_MAP_IDX) { addr = (unsigned long)map; @@ -19332,39 +19356,6 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env) insn[0].imm = (u32)addr; insn[1].imm = addr >> 32; - /* proceed with extra checks only if its newly added used map */ - if (reused) - goto next_insn; - - if (bpf_map_is_cgroup_storage(map) && - bpf_cgroup_storage_assign(env->prog->aux, map)) { - verbose(env, "only one cgroup storage of each type is allowed\n"); - return -EBUSY; - } - if (map->map_type == BPF_MAP_TYPE_ARENA) { - if (env->prog->aux->arena) { - verbose(env, "Only one arena per program\n"); - return -EBUSY; - } - if (!env->allow_ptr_leaks || !env->bpf_capable) { - verbose(env, "CAP_BPF and CAP_PERFMON are required to use arena\n"); - return -EPERM; - } - if (!env->prog->jit_requested) { - verbose(env, "JIT is required to use arena\n"); - return -EOPNOTSUPP; - } - if (!bpf_jit_supports_arena()) { - verbose(env, "JIT doesn't support arena\n"); - return -EOPNOTSUPP; - } - env->prog->aux->arena = (void *)map; - if (!bpf_arena_get_user_vm_start(env->prog->aux->arena)) { - verbose(env, "arena's user address must be set via map_extra or mmap()\n"); - return -EINVAL; - } - } - next_insn: insn++; i++; From patchwork Fri Nov 29 13:28:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888680 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f46.google.com (mail-ej1-f46.google.com [209.85.218.46]) (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 5122919C566 for ; Fri, 29 Nov 2024 13:25:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886760; cv=none; b=s4f0f7g9sscbmVQABS+pbFjirfh0+IbYOWV5WAdY9ApS1LDIr/ie6H70eZiIH+Njh/CcqtpK6bBlhfP/JZNbK8xWfAJzA0bMjf25DZ0M9nfxtJfMJx2+hioOkpJxxltq+WEO+REz7da1MabH5rp/RDQFYPMhgI29ZrATL/iF180= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886760; c=relaxed/simple; bh=1SWL9EbzbarFkG0HIuke17Dv7jdx7Fix+DDWSFg7uxY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=OeOtffC6rFy765PBhDkFfJsyriXEIHiWAok1gZqI4HbIYh9f9Hg/xXU4tejhSvtBPbA0QoOLBsl3/dWr2K+//8qyrwDkyWW9zkFMl8SmChhoonOcfUKrI92JyxdBzg7fcBE9lLdzDbIkC3AaeyEX7CFQcgmqn24r8/YCk0OJ3Oc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=gI6Wqzwf; arc=none smtp.client-ip=209.85.218.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="gI6Wqzwf" Received: by mail-ej1-f46.google.com with SMTP id a640c23a62f3a-aa51b8c5f4dso247341366b.2 for ; Fri, 29 Nov 2024 05:25:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886756; x=1733491556; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7XpeRWJwzZZZHEPTFcKVXIIr71udHMEOsTLECK9dRZQ=; b=gI6WqzwfIFOXb/5Yk06aYp9d6C4ffca6ff+OuWfRIjlH3cq9vEh2D+/snGStEmMpPi eW0Mje59p3twH8bGXXmvWUju6PnQ4CVackJb6jDJj0aES9W4hp2z4AV1h3UlgMM9/fck F+RrngNEjJ06pkeAkRs4e25B38DsA93+FCFPPPfLThIZo8l9tw7LBeg4W0iOwMnO+ZJx hi3OviV73MjoYIIV5HNVrwxkgm3FIxXi/k1L6X+Wgrhe1uu61Ya/kIax3TZcXXSEVCsC 4IOl1qDBY33Bj5CESZxR0Ro9qgT+qnjEmJ3yi2HQhmpQlkl7/zl8sl/GQ+ocOPtsPHMz G/Qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886756; x=1733491556; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7XpeRWJwzZZZHEPTFcKVXIIr71udHMEOsTLECK9dRZQ=; b=rBNkemTxVC7Nq4sHDaknPhUdfNH/ZSNHCUbbKwXoROGYkQLm0ilPfwVgAbTixT+OWP b0NTgwjRymmAFJd+bmZ3wn4jvhaOtqWjGNlfizHzORlKToINHiChmHggWtCqTjr7AxTL PoXFrQ1yyH6MNBL08P47NPafXHCrHbLuyP6VoZ3JvfQsMLuWCV25YcpUq4+ZAQAJ9RIl y7k7PD5LoAryiOeFYwaAoccsikgqwz0u4vBfdnXcSfeTDcY7jaKJWQ2lUkOOo+oSP4RQ N84dUj5P/0JFbGlS0K2FrY2nGEMcccy74Diil81tCNkyUOTq1/wkrZUt5fVqu1Yr32Pt TeHA== X-Gm-Message-State: AOJu0YwePbQa1TY7gA5G+2B/aA3U321fpQUDleEiwljA4Q+KGpscsd13 sPGtUDrh58gkGMC7Brop95aBg5hxVeMDm13B2MrjXhMl/S+cVqRDp7woc8RAFDvi1pXfFeO7y1q K X-Gm-Gg: ASbGncv1houe9qjsy4iOfbSmiJWqIFG8H4EpCMwemOkv299gebqLkAMRVeu5jZLAjCk IP4vtuNJ9fxNsZAkTAJUyeF48JksJx8TejedIrQVolutPOnBXrq2fvYMzma/iKSQFFeEixSLNMR P6BaRc5QoSBp/AjvTGFs/HMqrmEk7SXCGf12amIhAp5vXudYzH/+bVm1xkZc3N2zRKJAuEJvvz4 EAnb/tllvLHKnVHvSE0dKuRg3wreoUxGb4lL+s0lqfk3JaXLigr8UJ6BQIq9fM= X-Google-Smtp-Source: AGHT+IFDsJKEETI7PkYNIu83wbSymXr/9GPnJnkYJXAL21+sgF4knyvEQKappJH22Y6OJqAZOnfFlQ== X-Received: by 2002:a17:906:cc9:b0:a99:8a5c:a357 with SMTP id a640c23a62f3a-aa58106387bmr812652166b.58.1732886756117; Fri, 29 Nov 2024 05:25:56 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:55 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov Subject: [PATCH v3 bpf-next 3/7] bpf: add fd_array_cnt attribute for prog_load Date: Fri, 29 Nov 2024 13:28:09 +0000 Message-Id: <20241129132813.1452294-4-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net The fd_array attribute of the BPF_PROG_LOAD syscall may contain a set of file descriptors: maps or btfs. This field was introduced as a sparse array. Introduce a new attribute, fd_array_cnt, which, if present, indicates that the fd_array is a continuous array of the corresponding length. If fd_array_cnt is non-zero, then every map in the fd_array will be bound to the program, as if it was used by the program. This functionality is similar to the BPF_PROG_BIND_MAP syscall, but such maps can be used by the verifier during the program load. Signed-off-by: Anton Protopopov --- include/uapi/linux/bpf.h | 10 ++++ kernel/bpf/syscall.c | 2 +- kernel/bpf/verifier.c | 94 ++++++++++++++++++++++++++++------ tools/include/uapi/linux/bpf.h | 10 ++++ 4 files changed, 100 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 4162afc6b5d0..2acf9b336371 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1573,6 +1573,16 @@ union bpf_attr { * If provided, prog_flags should have BPF_F_TOKEN_FD flag set. */ __s32 prog_token_fd; + /* The fd_array_cnt can be used to pass the length of the + * fd_array array. In this case all the [map] file descriptors + * passed in this array will be bound to the program, even if + * the maps are not referenced directly. The functionality is + * similar to the BPF_PROG_BIND_MAP syscall, but maps can be + * used by the verifier during the program load. If provided, + * then the fd_array[0,...,fd_array_cnt-1] is expected to be + * continuous. + */ + __u32 fd_array_cnt; }; struct { /* anonymous struct used by BPF_OBJ_* commands */ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 58190ca724a2..7e3fbc23c742 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2729,7 +2729,7 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type) } /* last field in 'union bpf_attr' used by this command */ -#define BPF_PROG_LOAD_LAST_FIELD prog_token_fd +#define BPF_PROG_LOAD_LAST_FIELD fd_array_cnt static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size) { diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8e034a22aa2a..d172f6974fd7 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -19181,22 +19181,10 @@ static int check_map_prog_compatibility(struct bpf_verifier_env *env, return 0; } -/* Add map behind fd to used maps list, if it's not already there, and return - * its index. - * Returns <0 on error, or >= 0 index, on success. - */ -static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd) +static int __add_used_map(struct bpf_verifier_env *env, struct bpf_map *map) { - CLASS(fd, f)(fd); - struct bpf_map *map; int i, err; - map = __bpf_map_get(f); - if (IS_ERR(map)) { - verbose(env, "fd %d is not pointing to valid bpf_map\n", fd); - return PTR_ERR(map); - } - /* check whether we recorded this map already */ for (i = 0; i < env->used_map_cnt; i++) if (env->used_maps[i] == map) @@ -19227,6 +19215,24 @@ static int add_used_map_from_fd(struct bpf_verifier_env *env, int fd) return env->used_map_cnt - 1; } +/* Add map behind fd to used maps list, if it's not already there, and return + * its index. + * Returns <0 on error, or >= 0 index, on success. + */ +static int add_used_map(struct bpf_verifier_env *env, int fd) +{ + struct bpf_map *map; + CLASS(fd, f)(fd); + + map = __bpf_map_get(f); + if (IS_ERR(map)) { + verbose(env, "fd %d is not pointing to valid bpf_map\n", fd); + return PTR_ERR(map); + } + + return __add_used_map(env, map); +} + /* find and rewrite pseudo imm in ld_imm64 instructions: * * 1. if it accesses map FD, replace it with actual map pointer. @@ -19318,7 +19324,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env) break; } - map_idx = add_used_map_from_fd(env, fd); + map_idx = add_used_map(env, fd); if (map_idx < 0) return map_idx; map = env->used_maps[map_idx]; @@ -22526,6 +22532,61 @@ struct btf *bpf_get_btf_vmlinux(void) return btf_vmlinux; } +/* + * The add_fd_from_fd_array() is executed only if fd_array_cnt is given. In + * this case expect that every file descriptor in the array is either a map or + * a BTF, or a hole (0). Everything else is considered to be trash. + */ +static int add_fd_from_fd_array(struct bpf_verifier_env *env, int fd) +{ + struct bpf_map *map; + CLASS(fd, f)(fd); + int ret; + + map = __bpf_map_get(f); + if (!IS_ERR(map)) { + ret = __add_used_map(env, map); + if (ret < 0) + return ret; + return 0; + } + + if (!IS_ERR(__btf_get_by_fd(f))) + return 0; + + verbose(env, "fd %d is not pointing to valid bpf_map or btf\n", fd); + return PTR_ERR(map); +} + +static int init_fd_array(struct bpf_verifier_env *env, union bpf_attr *attr, bpfptr_t uattr) +{ + size_t size = sizeof(int); + int ret; + int fd; + u32 i; + + env->fd_array = make_bpfptr(attr->fd_array, uattr.is_kernel); + + /* + * The only difference between old (no fd_array_cnt is given) and new + * APIs is that in the latter case the fd_array is expected to be + * continuous and is scanned for map fds right away + */ + if (!attr->fd_array_cnt) + return 0; + + for (i = 0; i < attr->fd_array_cnt; i++) { + if (copy_from_bpfptr_offset(&fd, env->fd_array, i * size, size)) + return -EFAULT; + + ret = add_fd_from_fd_array(env, fd); + if (ret) + return ret; + } + + return 0; +} + int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u32 uattr_size) { u64 start_time = ktime_get_ns(); @@ -22557,7 +22618,9 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 env->insn_aux_data[i].orig_idx = i; env->prog = *prog; env->ops = bpf_verifier_ops[env->prog->type]; - env->fd_array = make_bpfptr(attr->fd_array, uattr.is_kernel); + ret = init_fd_array(env, attr, uattr); + if (ret) + goto err_free_aux_data; env->allow_ptr_leaks = bpf_allow_ptr_leaks(env->prog->aux->token); env->allow_uninit_stack = bpf_allow_uninit_stack(env->prog->aux->token); @@ -22775,6 +22838,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 err_unlock: if (!is_priv) mutex_unlock(&bpf_verifier_lock); +err_free_aux_data: vfree(env->insn_aux_data); kvfree(env->insn_hist); err_free_env: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 4162afc6b5d0..2acf9b336371 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1573,6 +1573,16 @@ union bpf_attr { * If provided, prog_flags should have BPF_F_TOKEN_FD flag set. */ __s32 prog_token_fd; + /* The fd_array_cnt can be used to pass the length of the + * fd_array array. In this case all the [map] file descriptors + * passed in this array will be bound to the program, even if + * the maps are not referenced directly. The functionality is + * similar to the BPF_PROG_BIND_MAP syscall, but maps can be + * used by the verifier during the program load. If provided, + * then the fd_array[0,...,fd_array_cnt-1] is expected to be + * continuous. + */ + __u32 fd_array_cnt; }; struct { /* anonymous struct used by BPF_OBJ_* commands */ From patchwork Fri Nov 29 13:28:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888681 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (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 4790C19DF99 for ; Fri, 29 Nov 2024 13:25:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886761; cv=none; b=coK+kvjkV7Z2MEQ69INSx7j52TtRDr+uzvq1GGSVxx6w7Q/b/nrATiBpMyiP8szNUr3t1gELFSe/AID8YY1SKIlFK+B6C3W36ylCqfG0+mq176vBoP7FDZ9jNp7VIQQV+vg6T9P/lDwDrYk7lgw9f4DGWIF+/rV3BU+LK+pyc0g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886761; c=relaxed/simple; bh=SfiHhxW8L0Lmn3ihd8debUXb8wBmxj5Pu01khKVp4tw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ca9VOk03C6XUaoEsgKFijnpLVj0MIeMbHta4L4ifWoeV9o42pzgBgyuaTA3SuVl4LjhugVBHKLrkwaptrDEBk1m9Z0uf4ZX5CJgTPjxZYeyQHF2Rv6SL2MpR3APw6JslOzbvl2BaH6O3GugGnEzO2BiTP2O1sVkA44+XQVPxn4A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=W79bkyBp; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="W79bkyBp" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-aa545dc7105so252481766b.3 for ; Fri, 29 Nov 2024 05:25:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886757; x=1733491557; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JP3QAMrozbgzwuk6m5bfUUTya1nGlDpj7m4OrmHYW7M=; b=W79bkyBpaUV1rjtne64H3/eg5E3eKGAaniajZgL3x2/EDl30M1EipJQlspkJeJUHgY /SUVqqcneyeMLkWcB4LNHTnAHMveXwaLyfoOw+L5b7XrfqQI+nljtZlrwM4BzZ3oLa4j fXtdQShVIY3EnuqLtxVLTxr5EeO/Y2YUFawtntKJg0qbNS101mJ2pgsZAu/6p8X6a8ck Voq1VbEgIwnA96MFi0ZJ3fhtGA8P2WBoWMieZz4dG7CV0orP9bVmGOGEhHpurjRBgETV tIrdn6XfSvLixflRQKGlAsfQLVu+u1VwnwxcWedGnWo4I3eU0vLt8AA1Z00lb436NVdA rm7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886757; x=1733491557; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JP3QAMrozbgzwuk6m5bfUUTya1nGlDpj7m4OrmHYW7M=; b=oG6MpimON7Cj5PSDjGO2D9NLsXO5DdfD9YVkXcYd9xWZjUYdZ23Z6K0d6ttfByUcM4 Tzd5FlfR6rpF7dpq4a0t5DD+kbhtshBLCi4tdAQwMhWCwssu8RLL2TE4Wp0QX/pSMVMH ZXADbIeP1aJteTyGXi9pEhnxS+8VMfq3vduxJYuWoquTRV/dJFlnk53fFfa3onAjtWfk IdWfIex2YAnLffBpaoGJiAybYqeBkZ0mEW4Su9CKuENt0LVotpUGWQopVlgahr2haYk+ I4GGgaRVpQl+i4d2TJUoTGfYSoauktRsQxYfSM8OvWPokPGXAirMxmqzr+E1psyUC46w duUw== X-Gm-Message-State: AOJu0YzYXAPXNgZAtp/I/OHxXBHvgxFYGkCXBygdInDVNTMmpQZTA9Pg Vk0m+ZSP8d2mXfbBW2ibf9JhH9JZkgQ0KMnV6SXouSioACHaOZdq7LTMU8ZLYHT8JfBBTt0/09R e X-Gm-Gg: ASbGncsvl6HBzcN543GdvftGKe0RII8t/Xp3pHLdQVMx80ygKvh0kTEcfv2nmBPEjQZ Z9axK6Hqhg67rmUszQ2xeuVWTyi6K6l25fIUZq9FKYTlg73mRGTQIjTAaFEAxlA9/EZIyKuBsE4 r8qhseyXVc/BCTZqYsluA8iZiONjJpZnno+jF3icqTJRr5PF3yQszwEZoeDmqrItg5uWf0t1Uf7 CB71mdM4+YKhUKC2CwrENsBWLMKoqWOiWU5djzKdALuj+pSrZiwI5SFtsnJ25s= X-Google-Smtp-Source: AGHT+IGyGc7cxDLL4nZQOcckaBf+ME9jmw6o1RXnPptr9L/wHiKZdeOKQ8YNYLWpx0Kwyh9i5ZhNRg== X-Received: by 2002:a17:906:3d22:b0:a9a:597:8cca with SMTP id a640c23a62f3a-aa5810333b8mr691092766b.45.1732886756783; Fri, 29 Nov 2024 05:25:56 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:56 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov Subject: [PATCH v3 bpf-next 4/7] libbpf: prog load: allow to use fd_array_cnt Date: Fri, 29 Nov 2024 13:28:10 +0000 Message-Id: <20241129132813.1452294-5-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Add new fd_array_cnt field to bpf_prog_load_opts and pass it in bpf_attr, if set. Signed-off-by: Anton Protopopov --- tools/lib/bpf/bpf.c | 5 +++-- tools/lib/bpf/bpf.h | 5 ++++- tools/lib/bpf/features.c | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index becdfa701c75..0e7f59224936 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -105,7 +105,7 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts) */ int probe_memcg_account(int token_fd) { - const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); + const size_t attr_sz = offsetofend(union bpf_attr, fd_array_cnt); struct bpf_insn insns[] = { BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns), BPF_EXIT_INSN(), @@ -238,7 +238,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns, size_t insn_cnt, struct bpf_prog_load_opts *opts) { - const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); + const size_t attr_sz = offsetofend(union bpf_attr, fd_array_cnt); void *finfo = NULL, *linfo = NULL; const char *func_info, *line_info; __u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd; @@ -311,6 +311,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type, attr.line_info_cnt = OPTS_GET(opts, line_info_cnt, 0); attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL)); + attr.fd_array_cnt = OPTS_GET(opts, fd_array_cnt, 0); if (log_level) { attr.log_buf = ptr_to_u64(log_buf); diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index a4a7b1ad1b63..435da95d2058 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -107,9 +107,12 @@ struct bpf_prog_load_opts { */ __u32 log_true_size; __u32 token_fd; + + /* if set, provides the length of fd_array */ + __u32 fd_array_cnt; size_t :0; }; -#define bpf_prog_load_opts__last_field token_fd +#define bpf_prog_load_opts__last_field fd_array_cnt LIBBPF_API int bpf_prog_load(enum bpf_prog_type prog_type, const char *prog_name, const char *license, diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c index 760657f5224c..5afc9555d9ac 100644 --- a/tools/lib/bpf/features.c +++ b/tools/lib/bpf/features.c @@ -22,7 +22,7 @@ int probe_fd(int fd) static int probe_kern_prog_name(int token_fd) { - const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd); + const size_t attr_sz = offsetofend(union bpf_attr, fd_array_cnt); struct bpf_insn insns[] = { BPF_MOV64_IMM(BPF_REG_0, 0), BPF_EXIT_INSN(), From patchwork Fri Nov 29 13:28:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888683 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f52.google.com (mail-ej1-f52.google.com [209.85.218.52]) (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 A7EED19E806 for ; Fri, 29 Nov 2024 13:26:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886762; cv=none; b=mpHq6PsV57AATh4ID5WJBvLxp0ZpR59VXSNdKlgeZ3RXVhQjpAbL+OB3XOrZX3wuuhM+juh90hpec2bOosmrv8gRrTTlV+ov2cDMo7SwfIdvJ+Rvpqdu0F9OsyMBTUUfx579bQhLiIsxeiJpCJfO4RbIhMP56wML9qj5dkDTOZo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886762; c=relaxed/simple; bh=q8kIqdjFR8VhaEdljaQIv0ADCkAKL0LE5LW/UB27fy0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IB2EeleHv5czWl0qWgBB+lvFzjHoPo9OEBhyG9mgH8HfRz1eNq/IfaLaS0RjBbeF1UemLsJAxu86KKoJ+n5RAOME5ZcBPrPUUBRnJYbQ9ckf3kPH4PTl2Lk9yyGhKRc6BzouTnQRKtUwp+7Z/BC/oqOu/H0cbzJ6knnKke1YRvU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=OyIPVmqw; arc=none smtp.client-ip=209.85.218.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="OyIPVmqw" Received: by mail-ej1-f52.google.com with SMTP id a640c23a62f3a-aa503cced42so259419966b.3 for ; Fri, 29 Nov 2024 05:26:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886759; x=1733491559; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oZaeN35fXOQqFjsexfjmHkmqsK002i7Hw/kubNXFYbg=; b=OyIPVmqwd/tU1/bZzj9OG/87zrWBsg4UsK+hXJwBZQXED48I053DlhHbseH0lvwkv9 cXptBYqV7Sq9JMbVPwP7HKYQ1fub2mVlKki9iq6R6ziCNRxqZF/YL3Hu2IZc/z4UjEuk yhWCewSVwVClzEDicZseMB8GktAywzwIJynMHEaCdidbctnGgamGKGLPz1tLWUijpT7L 8m+YNT9KU9084M+20MkBrOJWxuTTSkR4VN5EzeOHJuHkgn4VlLmPIkuQ5KR2zF3pMrWf TEaZiTud9Tv8G2Bwo3oJH6Jlvj6EjqUgr1iIDYGDYLxCMTcMU9f6c/9pBzzHyLp463/o 2CxA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886759; x=1733491559; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oZaeN35fXOQqFjsexfjmHkmqsK002i7Hw/kubNXFYbg=; b=fWpKpB7nR3HvxureIBdHkctmalHvO1Z+s13qg1DjQTqIQFWKEtP8Cn5CT+zqhESFwt AycaL+60qbg//MDbkmEwrB/HZtKbxkYtiZeD35UEqx1n8WY3B7OJtGx06zbW1IZndGL3 YUYjlEol6+2uWT+4qo2JflvWqTy9IISu6Bi5h0cbNmkwmSAeZucK5k0CVHkT85hDghPG CzUDMf5xfws+Jk7yXz6ag9ueTRDGkIha2P/lnReKW5pgidDqbOFUPWEx6OYGrO0lKHPd uMY/ps3ZZgBVkDwA35rfIAu1n1tI4eFys48f0NiMN6leSNV9wGAkDbKDWhoh6S8CC6xk V8XA== X-Gm-Message-State: AOJu0YxH6Ezc7DsL0CxoiNG381hS1HQgklaUZC5RNRgjA8Dq8IEMsvUG tFnsc5HtT1IbDpxa4a6LQebPbQF+e4ulYJDKl7VFMZaL2a3Ukatvr27tMr+/gU3q+spg/ORBOwJ h X-Gm-Gg: ASbGncv2pJLPlSbxKf15RDFuJZG9ivNY4Ueum9GXQ+kjC22Y4KsMa0BWvmXBpTz4A0o /ipI6V76NnxBBGaTo7/rcb8jkzv4Smnt7fxuntidZ0Mr7J4dBbSwGuSHSzEqTKX5TgW2PNJXWxl s4clAOdMMxJwOl74pd2ATWya7klbvFMEWrDOXAAxsUMd7IbqpvFLWZ/RaNBD+HXq25d8BkwYT+P 6Hxw2VxTPIGtokDaixlv9IRV6OwDn0+V5zTArgDWldXs8p7Vpfd5AZdDnYAJbE= X-Google-Smtp-Source: AGHT+IF0/9EsYDvYxR3fHRo5Qxe8yrVRhF0RCHzuSwYOorP3eGHPDy65yoWEHUNYNRyQ27cOMt7nNg== X-Received: by 2002:a17:906:2932:b0:aa5:396a:c9e8 with SMTP id a640c23a62f3a-aa580f27899mr629685566b.23.1732886758386; Fri, 29 Nov 2024 05:25:58 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:57 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov Subject: [PATCH v3 bpf-next 5/7] selftests/bpf: Add tests for fd_array_cnt Date: Fri, 29 Nov 2024 13:28:11 +0000 Message-Id: <20241129132813.1452294-6-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Add a new set of tests to test the new field in PROG_LOAD-related part of bpf_attr: fd_array_cnt. Add the following test cases: * fd_array_cnt/no-fd-array: program is loaded in a normal way, without any fd_array present * fd_array_cnt/fd-array-ok: pass two extra non-used maps, check that they're bound to the program * fd_array_cnt/fd-array-dup-input: pass a few extra maps, only two of which are unique * fd_array_cnt/fd-array-ref-maps-in-array: pass a map in fd_array which is also referenced from within the program * fd_array_cnt/fd-array-trash-input: pass array with some trash * fd_array_cnt/fd-array-with-holes: pass an array with holes (fd=0) * fd_array_cnt/fd-array-2big: pass too large array All the tests above are using the bpf(2) syscall directly, no libbpf involved. Signed-off-by: Anton Protopopov --- kernel/bpf/verifier.c | 30 +- .../selftests/bpf/prog_tests/fd_array.c | 340 ++++++++++++++++++ 2 files changed, 355 insertions(+), 15 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/fd_array.c diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index d172f6974fd7..7102d85f580d 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -22620,7 +22620,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 env->ops = bpf_verifier_ops[env->prog->type]; ret = init_fd_array(env, attr, uattr); if (ret) - goto err_free_aux_data; + goto err_release_maps; env->allow_ptr_leaks = bpf_allow_ptr_leaks(env->prog->aux->token); env->allow_uninit_stack = bpf_allow_uninit_stack(env->prog->aux->token); @@ -22773,11 +22773,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 copy_to_bpfptr_offset(uattr, offsetof(union bpf_attr, log_true_size), &log_true_size, sizeof(log_true_size))) { ret = -EFAULT; - goto err_release_maps; + goto err_ext; } if (ret) - goto err_release_maps; + goto err_ext; if (env->used_map_cnt) { /* if program passed verifier, update used_maps in bpf_prog_info */ @@ -22787,7 +22787,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 if (!env->prog->aux->used_maps) { ret = -ENOMEM; - goto err_release_maps; + goto err_ext; } memcpy(env->prog->aux->used_maps, env->used_maps, @@ -22801,7 +22801,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 GFP_KERNEL); if (!env->prog->aux->used_btfs) { ret = -ENOMEM; - goto err_release_maps; + goto err_ext; } memcpy(env->prog->aux->used_btfs, env->used_btfs, @@ -22817,15 +22817,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 adjust_btf_func(env); -err_release_maps: - if (!env->prog->aux->used_maps) - /* if we didn't copy map pointers into bpf_prog_info, release - * them now. Otherwise free_used_maps() will release them. - */ - release_maps(env); - if (!env->prog->aux->used_btfs) - release_btfs(env); - +err_ext: /* extension progs temporarily inherit the attach_type of their targets for verification purposes, so set it back to zero before returning */ @@ -22838,7 +22830,15 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3 err_unlock: if (!is_priv) mutex_unlock(&bpf_verifier_lock); -err_free_aux_data: +err_release_maps: + if (!env->prog->aux->used_maps) + /* if we didn't copy map pointers into bpf_prog_info, release + * them now. Otherwise free_used_maps() will release them. + */ + release_maps(env); + if (!env->prog->aux->used_btfs) + release_btfs(env); + vfree(env->insn_aux_data); kvfree(env->insn_hist); err_free_env: diff --git a/tools/testing/selftests/bpf/prog_tests/fd_array.c b/tools/testing/selftests/bpf/prog_tests/fd_array.c new file mode 100644 index 000000000000..1d4bff4a1269 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/fd_array.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#include +#include + +#include "../test_btf.h" + +static inline int new_map(void) +{ + LIBBPF_OPTS(bpf_map_create_opts, opts); + const char *name = NULL; + __u32 max_entries = 1; + __u32 value_size = 8; + __u32 key_size = 4; + + return bpf_map_create(BPF_MAP_TYPE_ARRAY, name, + key_size, value_size, + max_entries, &opts); +} + +static int new_btf(void) +{ + LIBBPF_OPTS(bpf_btf_load_opts, opts); + struct btf_blob { + struct btf_header btf_hdr; + __u32 types[8]; + __u32 str; + } raw_btf = { + .btf_hdr = { + .magic = BTF_MAGIC, + .version = BTF_VERSION, + .hdr_len = sizeof(struct btf_header), + .type_len = sizeof(raw_btf.types), + .str_off = offsetof(struct btf_blob, str) - offsetof(struct btf_blob, types), + .str_len = sizeof(raw_btf.str), + }, + .types = { + /* long */ + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8), /* [1] */ + /* unsigned long */ + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ + }, + }; + + return bpf_btf_load(&raw_btf, sizeof(raw_btf), &opts); +} + +static bool map_exists(__u32 id) +{ + int fd; + + fd = bpf_map_get_fd_by_id(id); + if (fd >= 0) { + close(fd); + return true; + } + return false; +} + +static inline int bpf_prog_get_map_ids(int prog_fd, __u32 *nr_map_ids, __u32 *map_ids) +{ + __u32 len = sizeof(struct bpf_prog_info); + struct bpf_prog_info info = { + .nr_map_ids = *nr_map_ids, + .map_ids = ptr_to_u64(map_ids), + }; + int err; + + err = bpf_prog_get_info_by_fd(prog_fd, &info, &len); + if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd")) + return -1; + + *nr_map_ids = info.nr_map_ids; + + return 0; +} + +static int __load_test_prog(int map_fd, const int *fd_array, int fd_array_cnt) +{ + /* A trivial program which uses one map */ + struct bpf_insn insns[] = { + BPF_LD_MAP_FD(BPF_REG_1, map_fd), + BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + LIBBPF_OPTS(bpf_prog_load_opts, opts); + + opts.fd_array = fd_array; + opts.fd_array_cnt = fd_array_cnt; + + return bpf_prog_load(BPF_PROG_TYPE_XDP, NULL, "GPL", insns, ARRAY_SIZE(insns), &opts); +} + +static int load_test_prog(const int *fd_array, int fd_array_cnt) +{ + int map_fd; + int ret; + + map_fd = new_map(); + if (!ASSERT_GE(map_fd, 0, "new_map")) + return map_fd; + + ret = __load_test_prog(map_fd, fd_array, fd_array_cnt); + close(map_fd); + + /* switch back to returning the actual value */ + if (ret < 0) + return -errno; + return ret; +} + +static bool check_expected_map_ids(int prog_fd, int expected, __u32 *map_ids, __u32 *nr_map_ids) +{ + int err; + + err = bpf_prog_get_map_ids(prog_fd, nr_map_ids, map_ids); + if (!ASSERT_OK(err, "bpf_prog_get_map_ids")) + return false; + if (!ASSERT_EQ(*nr_map_ids, expected, "unexpected nr_map_ids")) + return false; + + return true; +} + +/* + * Load a program, which uses one map. No fd_array maps are present. + * On return only one map is expected to be bound to prog. + */ +static void check_fd_array_cnt__no_fd_array(void) +{ + __u32 map_ids[16]; + __u32 nr_map_ids; + int prog_fd = -1; + + prog_fd = load_test_prog(NULL, 0); + if (!ASSERT_GE(prog_fd, 0, "BPF_PROG_LOAD")) + return; + nr_map_ids = ARRAY_SIZE(map_ids); + check_expected_map_ids(prog_fd, 1, map_ids, &nr_map_ids); + close(prog_fd); +} + +/* + * Load a program, which uses one map, and pass two extra, non-equal, maps in + * fd_array with fd_array_cnt=2. On return three maps are expected to be bound + * to the program. + */ +static void check_fd_array_cnt__fd_array_ok(void) +{ + int extra_fds[2] = { -1, -1 }; + __u32 map_ids[16]; + __u32 nr_map_ids; + int prog_fd = -1; + + extra_fds[0] = new_map(); + if (!ASSERT_GE(extra_fds[0], 0, "new_map")) + goto cleanup; + extra_fds[1] = new_map(); + if (!ASSERT_GE(extra_fds[1], 0, "new_map")) + goto cleanup; + prog_fd = load_test_prog(extra_fds, 2); + if (!ASSERT_GE(prog_fd, 0, "BPF_PROG_LOAD")) + goto cleanup; + nr_map_ids = ARRAY_SIZE(map_ids); + if (!check_expected_map_ids(prog_fd, 3, map_ids, &nr_map_ids)) + goto cleanup; + + /* maps should still exist when original file descriptors are closed */ + close(extra_fds[0]); + close(extra_fds[1]); + if (!ASSERT_EQ(map_exists(map_ids[0]), true, "map_ids[0] should exist")) + goto cleanup; + if (!ASSERT_EQ(map_exists(map_ids[1]), true, "map_ids[1] should exist")) + goto cleanup; + + /* some fds might be invalid, so ignore return codes */ +cleanup: + close(extra_fds[1]); + close(extra_fds[0]); + close(prog_fd); +} + +/* + * Load a program with a few extra maps duplicated in the fd_array. + * After the load maps should only be referenced once. + */ +static void check_fd_array_cnt__duplicated_maps(void) +{ + int extra_fds[4] = { -1, -1, -1, -1 }; + __u32 map_ids[16]; + __u32 nr_map_ids; + int prog_fd = -1; + + extra_fds[0] = extra_fds[2] = new_map(); + if (!ASSERT_GE(extra_fds[0], 0, "new_map")) + goto cleanup; + extra_fds[1] = extra_fds[3] = new_map(); + if (!ASSERT_GE(extra_fds[1], 0, "new_map")) + goto cleanup; + prog_fd = load_test_prog(extra_fds, 4); + if (!ASSERT_GE(prog_fd, 0, "BPF_PROG_LOAD")) + goto cleanup; + nr_map_ids = ARRAY_SIZE(map_ids); + if (!check_expected_map_ids(prog_fd, 3, map_ids, &nr_map_ids)) + goto cleanup; + + /* maps should still exist when original file descriptors are closed */ + close(extra_fds[0]); + close(extra_fds[1]); + if (!ASSERT_EQ(map_exists(map_ids[0]), true, "map should exist")) + goto cleanup; + if (!ASSERT_EQ(map_exists(map_ids[1]), true, "map should exist")) + goto cleanup; + + /* some fds might be invalid, so ignore return codes */ +cleanup: + close(extra_fds[1]); + close(extra_fds[0]); + close(prog_fd); +} + +/* + * Check that if maps which are referenced by a program are + * passed in fd_array, then they will be referenced only once + */ +static void check_fd_array_cnt__referenced_maps_in_fd_array(void) +{ + int extra_fds[1] = { -1 }; + __u32 map_ids[16]; + __u32 nr_map_ids; + int prog_fd = -1; + + extra_fds[0] = new_map(); + if (!ASSERT_GE(extra_fds[0], 0, "new_map")) + goto cleanup; + prog_fd = __load_test_prog(extra_fds[0], extra_fds, 1); + if (!ASSERT_GE(prog_fd, 0, "BPF_PROG_LOAD")) + goto cleanup; + nr_map_ids = ARRAY_SIZE(map_ids); + if (!check_expected_map_ids(prog_fd, 1, map_ids, &nr_map_ids)) + goto cleanup; + + /* map should still exist when original file descriptor is closed */ + close(extra_fds[0]); + if (!ASSERT_EQ(map_exists(map_ids[0]), true, "map should exist")) + goto cleanup; + + /* some fds might be invalid, so ignore return codes */ +cleanup: + close(extra_fds[0]); + close(prog_fd); +} + +/* + * Test that a program with trash in fd_array can't be loaded: + * only map and BTF file descriptors should be accepted. + */ +static void check_fd_array_cnt__fd_array_with_trash(void) +{ + int extra_fds[3] = { -1, -1, -1 }; + int prog_fd = -1; + + extra_fds[0] = new_map(); + if (!ASSERT_GE(extra_fds[0], 0, "new_map")) + goto cleanup; + extra_fds[1] = new_btf(); + if (!ASSERT_GE(extra_fds[1], 0, "new_btf")) + goto cleanup; + + /* trash 1: not a file descriptor */ + extra_fds[2] = 0xbeef; + prog_fd = load_test_prog(extra_fds, 3); + if (!ASSERT_EQ(prog_fd, -EBADF, "prog should have been rejected with -EBADF")) + goto cleanup; + + /* trash 2: not a map or btf */ + extra_fds[2] = socket(AF_INET, SOCK_STREAM, 0); + if (!ASSERT_GE(extra_fds[2], 0, "socket")) + goto cleanup; + + prog_fd = load_test_prog(extra_fds, 3); + if (!ASSERT_EQ(prog_fd, -EINVAL, "prog should have been rejected with -EINVAL")) + goto cleanup; + + /* some fds might be invalid, so ignore return codes */ +cleanup: + close(extra_fds[2]); + close(extra_fds[1]); + close(extra_fds[0]); +} + +/* + * Test that a program with too big fd_array can't be loaded. + */ +static void check_fd_array_cnt__fd_array_too_big(void) +{ + int extra_fds[65]; + int prog_fd = -1; + int i; + + for (i = 0; i < 65; i++) { + extra_fds[i] = new_map(); + if (!ASSERT_GE(extra_fds[i], 0, "new_map")) + goto cleanup_fds; + } + + prog_fd = load_test_prog(extra_fds, 65); + ASSERT_EQ(prog_fd, -E2BIG, "prog should have been rejected with -E2BIG"); + +cleanup_fds: + while (i > 0) + close(extra_fds[--i]); +} + +void test_fd_array_cnt(void) +{ + if (test__start_subtest("no-fd-array")) + check_fd_array_cnt__no_fd_array(); + + if (test__start_subtest("fd-array-ok")) + check_fd_array_cnt__fd_array_ok(); + + if (test__start_subtest("fd-array-dup-input")) + check_fd_array_cnt__duplicated_maps(); + + if (test__start_subtest("fd-array-ref-maps-in-array")) + check_fd_array_cnt__referenced_maps_in_fd_array(); + + if (test__start_subtest("fd-array-trash-input")) + check_fd_array_cnt__fd_array_with_trash(); + + if (test__start_subtest("fd-array-2big")) + check_fd_array_cnt__fd_array_too_big(); +} From patchwork Fri Nov 29 13:28:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888682 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ed1-f42.google.com (mail-ed1-f42.google.com [209.85.208.42]) (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 1632619C566 for ; Fri, 29 Nov 2024 13:26:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886762; cv=none; b=pgj9/3C+hkcw1MZhFY5gicR9EveetRvjcgvMCy8b/V0Ut/PJy4Tj8F6njt2vQUFf3mxPzn8DRcs2/1xFJTe/43kYS0G5wHhnRNEfGzI/KU/d975ysgCz5OS2+NH5x65BGMXSKJrLd7Rya40dhxjgfXPy9NHw03hLqW/6dxVjndo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886762; c=relaxed/simple; bh=N4fVQPXJXo2Th6B1WGHku4ZK0MSeXujnBW5iXtm9jAw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QB2lhiNrIftXxcsv5+2WFtT1DFlcRqsHcZ6dWsv9JVvb0gJPO+KwSMuIW1kJKCWgtZmWStER83r+YjeL4cI4UuGqOYpVRfuDZmRvlHJn4BCpSo04ExYbMyQ/Qe5ImCug7Pa82NXUjhcMBp8DjKGxj/d3FW0shUsZkvBs5Ky923c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=YwVW02Uz; arc=none smtp.client-ip=209.85.208.42 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="YwVW02Uz" Received: by mail-ed1-f42.google.com with SMTP id 4fb4d7f45d1cf-5d0062e9c80so2294704a12.2 for ; Fri, 29 Nov 2024 05:26:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886759; x=1733491559; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=u/uCtoS5e1shwI4lkh3m+//bTjTAkVIgPynZLquHrvs=; b=YwVW02Uz/MkrSA5ohuiYsFo0wwwPsGl3Fvi+ZEtB/qon2P1UMaXWYXDjXwYKYcoYmU NHraJTKJ7AVnEzXi7/7x0YPaz/g1VefkQb29MKX/oFd1Vbpnla/6t1RS2zTWUS1pZNnn 1UzUy3Szq3Q5Mc0HwzuaFfS2jwUjX9sL5WzWz1z0gol9S7VCdOJvYLXNnUJD+V+wpcgE BeG/7bj4jz2q3YREpDw/yOmoKBGvNeEvVt5RZH+JUYFZtbEXbckVRd8cBlTWF05FzDyw 0N5WrtQBD9cj8gBFRsGpYw1QBuT49oRy++Ev5YiYaft8wgAwsr1LDYpriFSIqIWhax+H Ix8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886759; x=1733491559; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=u/uCtoS5e1shwI4lkh3m+//bTjTAkVIgPynZLquHrvs=; b=g6GQ/TKeaP7Sr4eBm/zwA4a6Wlz8MxOl5rAw4EuCySwyZwBapnrilP7nLG0MBT8QI8 Kg8qzCyfKO2zM9wOwt/04o7IAD6cbtlh/UUc421p6mjSFhkdh7SKGjDHWf+OhI5WU86E f+8ge8dU16S7+s9QO7alWfaazhjyz1zrVq1Z196S2z1FeO2gsDDQPwp4j0sUuoq759hW qY0TmGbQ7TlmTk+yO51qv0jHBbl4qwq/E5/GJDYnssqj2b5faztriD7KJvYpqwztWm9E SY0cu0axwuuvOLqVs5trTb63GzZIytjhgXsUXpFiXG4sz4JA1yfh2PAE0f9v+68mASRW EJwg== X-Gm-Message-State: AOJu0YyPG/8OL7kUNjEEGFM0MjcZdwf1VyE0QYXGmb0f9oSN9/izc78A 0+a1IeVzqdvvu5dJbqQZkNytJVhPplErgLDEv61tn5jG6x2dZDvm+vjAtSQ/28t80DkxAqIt6wI 5 X-Gm-Gg: ASbGnctgWxVdLbl8uO/ndN4ty8IwF50zVGvkz6lINr5ahuM+ysvdYA1etCjPHTVkRHi akSWaUHO5xQ/QR1D1RpoPS0N0VP3YrHMGO7UpLvGRk3TNLzGcex3/gdXeLApNxL3zh7j28aRkVP dDMzZHAy+uaBI4u5U3c5qg44Dg6tt+iF0NwJm2tgZK1Ig5hbpmx9Aot4t0PgH0xEZTu78C+fH4Q JGCbLJVo2IP4UY80zPuUvDxfMvRSc4uWpFFiVDoauhSG67mRFskUWMlfGH7uyA= X-Google-Smtp-Source: AGHT+IFsJu8f4czyvQxnVGXKoGjlPhxC1a5uCdNKPpAQ7SOIAxTb9P03gtVrYjbU4IAzKr5XRl21ZA== X-Received: by 2002:a17:906:4c9:b0:aa5:33f0:c50e with SMTP id a640c23a62f3a-aa5810634b5mr867375666b.57.1732886759195; Fri, 29 Nov 2024 05:25:59 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:58 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov , Jiri Olsa Subject: [PATCH v3 bpf-next 6/7] bpf: fix potential error return Date: Fri, 29 Nov 2024 13:28:12 +0000 Message-Id: <20241129132813.1452294-7-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net The bpf_remove_insns() function returns WARN_ON_ONCE(error), where error is a result of bpf_adj_branches(), and thus should be always 0 However, if for any reason it is not 0, then it will be converted to boolean by WARN_ON_ONCE and returned to user space as 1, not an actual error value. Fix this by returning the original err after the WARN check. Signed-off-by: Anton Protopopov Acked-by: Jiri Olsa --- kernel/bpf/core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 14d9288441f2..35a306ce9d94 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -539,6 +539,8 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off, int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt) { + int err; + /* Branch offsets can't overflow when program is shrinking, no need * to call bpf_adj_branches(..., true) here */ @@ -546,7 +548,9 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt) sizeof(struct bpf_insn) * (prog->len - off - cnt)); prog->len -= cnt; - return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false)); + err = bpf_adj_branches(prog, off, off + cnt, off, false); + WARN_ON_ONCE(err); + return err; } static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp) From patchwork Fri Nov 29 13:28:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Protopopov X-Patchwork-Id: 13888684 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-ej1-f43.google.com (mail-ej1-f43.google.com [209.85.218.43]) (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 94A8719E826 for ; Fri, 29 Nov 2024 13:26:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886768; cv=none; b=C2IXEP6KJOVaL6ue2z3uEaRk4inXmjMjiRfp0FLE1kO0QKkrbBKHalpc5ZAvmXR9QLTFQkIm6fveom6I73qoAqjegkMls/veDe+I2lmNnfFPFjjjSadhV5i7L4KBy+CJDNxLMH0/ow878ZqjRXSwVs+VKRqfDMnAjj54PoKP1OY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732886768; c=relaxed/simple; bh=5M+9sZ2uOISCSb6KW/FXzpjBYHwIs149KFBIoWPdbV4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=kdB2sBAMkdKiXYaeZiJLZj/D92DXMbd6VhD5rmnPs1EYw/ShjOoatsVTCk/hdPcs9lbpQp9bYeoM85X7zmr0cDXFF69OWpiA4C/viJl31RQeIKNQZ7OkoBymizM24dl/U/1KDcghG0lS5rBPcFMN+QKpWB3/qnu5LWbzlap8lrc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com; spf=pass smtp.mailfrom=isovalent.com; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b=D2yAPRvC; arc=none smtp.client-ip=209.85.218.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=isovalent.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=isovalent.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=isovalent.com header.i=@isovalent.com header.b="D2yAPRvC" Received: by mail-ej1-f43.google.com with SMTP id a640c23a62f3a-aa5325af6a0so244147266b.2 for ; Fri, 29 Nov 2024 05:26:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=isovalent.com; s=google; t=1732886762; x=1733491562; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=95uLp76JDqCGAntKfWwQIWRGb8VQc95vaaCgVutyp08=; b=D2yAPRvCkt2QQuKEXD+sbXp9pDr51lpMALL5co40Uz4srVdJhUjdgUMECgVB0tjPYu 0qnUAWJAdejUv0zXNvvn4owC2qFMrQURsKR89YcR9bipKVSxyit+4hHHI4oPiQIuNl8u F6qxHYWPfDF4N1lfZgnNQXPbcEgccSqecqUNS1BlwT7uazWzZsZ91reQ+5P2OjBmnw2p BwJm9EwVlc8YcOyxNuOCZ805beYtnqzsnzqk5YSDkdAkHfaA5EYZdes2uH+8xEuD4TgC mQHAL08mTZJgAqQKUrdHnbqoXEr+f/w8prQk+B8qPkb6oHW8/Ims5S4hns87yzjjRKaO KLnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732886762; x=1733491562; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=95uLp76JDqCGAntKfWwQIWRGb8VQc95vaaCgVutyp08=; b=DrnJrwV9E0jmiZlvuV1y7pfpTnpfdksRDFUNCW8sQk6wDTzC+2HL0nmAEXVBVnrhZz +45HYy+w1YkOaiGu+qn/IOgMsG62rIMCSw/0DzQ/SOATuZNKbLBgaLQtxpDQYQ6Z9aRn 9XOMwEfGbV31GXcqcf5qIKSli++9aAB63Run0EiN9KuDUk+1HIzNnK5lo7am5YosVODo 89uFaYFRQbyf0WqCcBOj8ye61Okti4A8TDW+P+TPstUqYRkmkcWIImCuGxUZW48qOd1I ToXAbCtnRT3VopBeG+4VP/IyOnD8Km/FEMqqArlRSkwfJ+jAt2OlRYga1jSMPAbhDl9G IxTw== X-Gm-Message-State: AOJu0YzkXuy1PelXyCxdeFsj/JBGhHdfz79ygArzgjmdSuNVN9cWy6fO OMq/KDHJlfHm4kgfnfuYcuZ7D/IfqbC6dUeDjfnw3F1CiXSPWdas82Pn1jxmUohcs7ObCSHkQYi u X-Gm-Gg: ASbGncsucpOqG9ohg39C8CC3yriLNtUlde5s1HlenU6GAGL9LfbgQm2R1Bnd2uJYBbP MtUBURu/gY71mGBzAVODYe/XaqHq3IaInkvU1E6tQeKMH5hQcBephw0TqLXu1qZp1VD7WoaNNUk 28T9r4f8u40ygnErloSebq0Ym2RygN2KpK0odTlMsqYOI+nXogoCWlEmL2JLsC+0z0oYa4giCWi zRJxo4OVnriKeky4mO69y0JeEN+/bnnRGW4f8GnmaCJ80oV3KSE9EtLCP2GMu4= X-Google-Smtp-Source: AGHT+IHHyk6HIjbwNkEK6rJ0FdHykw43HV1JWlx9lFXBP+TsV3R5Jj1b02ZX/w2auWD4b9NkL9k2DA== X-Received: by 2002:a17:907:7809:b0:aa5:2b4b:616a with SMTP id a640c23a62f3a-aa580f1b29cmr867150666b.17.1732886760255; Fri, 29 Nov 2024 05:26:00 -0800 (PST) Received: from localhost.localdomain ([2a04:ee41:4:b2de:1ac0:4dff:fe0f:3782]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-aa599904f33sm173295066b.135.2024.11.29.05.25.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 29 Nov 2024 05:25:59 -0800 (PST) From: Anton Protopopov To: bpf@vger.kernel.org Cc: Anton Protopopov , Eduard Zingerman Subject: [PATCH v3 bpf-next 7/7] selftest/bpf: replace magic constants by macros Date: Fri, 29 Nov 2024 13:28:13 +0000 Message-Id: <20241129132813.1452294-8-aspsk@isovalent.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241129132813.1452294-1-aspsk@isovalent.com> References: <20241129132813.1452294-1-aspsk@isovalent.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: bpf@iogearbox.net Replace magic constants in a BTF structure initialization code by proper macros, as is done in other similar selftests. Signed-off-by: Anton Protopopov Suggested-by: Eduard Zingerman --- tools/testing/selftests/bpf/progs/syscall.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/syscall.c b/tools/testing/selftests/bpf/progs/syscall.c index 0f4dfb770c32..b698cc62a371 100644 --- a/tools/testing/selftests/bpf/progs/syscall.c +++ b/tools/testing/selftests/bpf/progs/syscall.c @@ -76,9 +76,9 @@ static int btf_load(void) .magic = BTF_MAGIC, .version = BTF_VERSION, .hdr_len = sizeof(struct btf_header), - .type_len = sizeof(__u32) * 8, - .str_off = sizeof(__u32) * 8, - .str_len = sizeof(__u32), + .type_len = sizeof(raw_btf.types), + .str_off = offsetof(struct btf_blob, str) - offsetof(struct btf_blob, types), + .str_len = sizeof(raw_btf.str), }, .types = { /* long */