From patchwork Fri Feb 9 02:00:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13550798 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-yw1-f174.google.com (mail-yw1-f174.google.com [209.85.128.174]) (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 B7DBC4C8E for ; Fri, 9 Feb 2024 02:00:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444060; cv=none; b=irrY5TY9dBHL3IntM4AJ1vxsuM3wtAbAwaJnUiq6HRcCVqK4lOwjiAReEJOqk0PzleHuLpGNntviA69URwv5plORJJAsIZgxGLACfvLnBkEtEYtEXBl+Eyq31sR3xNrhhmko04K5TqVdcTh+qsZno4h9Btlh9vTRQJUBMOTjeO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444060; c=relaxed/simple; bh=4UNGAiBlbIhXPVNFPusepQXSZLNoKdzsnPsjmEDsRNk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=k7nOWo02eUt3lH6lM2QaA4tXVFV4uB2Em5SouMYUrAfXROH5dqiO/VyTh2Co6DNd2chU0ImzOFHeg3muSyuLOno0ZJVc0cXscM+mdyVwNv9jD9KdzxUiiTyv53ZWV2b8UujiSP6vps2IfMg0ETsDrLezC4boG/uHkC2p78R/aoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YtLVjpvy; arc=none smtp.client-ip=209.85.128.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YtLVjpvy" Received: by mail-yw1-f174.google.com with SMTP id 00721157ae682-604a184703bso5518497b3.3 for ; Thu, 08 Feb 2024 18:00:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707444057; x=1708048857; 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=RVXAYn+kBBkRE2GKj9qbQ7OXYLy6VKv4rz5z5iQMMZ8=; b=YtLVjpvyi4ApaNx8MaF4YJNa4yh6zY89C80QAAK8FeOOFDQFLTmNyVaE4eaCaexLqJ LX2HjGP2tn4NKBUENv0/wJnWa9Mzd39rXp/NaTFs4AhgmdO28yJ5hOs6g7XU2MHaSr7I FrrqZkXgMKJhJEXtcfyIqTOm8xoeZXhzaQ8hYFcuDGzPJ7sHyvdjNhZrZp/KP1JU6zPv pOWXrELL9dUTbi4GiPtiJpzXWRZo2YZYRjXAvuwgmpseqdmJ+DS8A1ShvJRfCS/JXK5i uxy1QJyyXvO5/1oFlw3jyifldnTT3ccePzQMQoRGw2kRsoVks6m7u6Z5CQk0/gfTHEgA dS1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707444057; x=1708048857; 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=RVXAYn+kBBkRE2GKj9qbQ7OXYLy6VKv4rz5z5iQMMZ8=; b=b+sYhgR8D7c1wkQ1Lgg4vlbDFRFd14lNNelF5uhV/1UMbYnd7m+9m9dNeO/57HxbAM qkThi79jJlrH/FApeMeFhVqalTgVouvkb6uqzL4f3AXaxJ8m4FPznfBo3cnEhtObBnTh 86dho2T1gc4lCiDPWRaNgBt5aZc1q18o6cSPZeiX9niONDn5J0YfR5SRsouNaCNYA/U7 gB6ZjKz9kFEpt28BJjrSZVmIc24ijrDezc41VkAku+npyBesZB5sMZPfafwgs4Fci8jh E6rGq1uKvt0DtQQ6lLM8FjOndOC/KjkVq7WhUQbH1esiOl66W4u3HIoCgrIh2eMzViOk VzEw== X-Gm-Message-State: AOJu0YwdwAv0efmlHrvkn5HYzlqsTJgbLWU8/vF8BKZ6YLojlvbpTKdj RkguEKwfg+XcWLZ0n7YcyQvvZ/NtpoyO54XuE9RWwB3S3gn2rcpjRVBF8h8fhIU= X-Google-Smtp-Source: AGHT+IEhn37uTGKTQ80jI6TyeGX0PWA+kWcYCcEl4YuRu6chlXRY89/oMEV7U519kOn8BwPl/G1ztA== X-Received: by 2002:a0d:d583:0:b0:604:57dd:4e9d with SMTP id x125-20020a0dd583000000b0060457dd4e9dmr262038ywd.21.1707444057121; Thu, 08 Feb 2024 18:00:57 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCVcsHJdDHowj76b7zNZAKFeNbpbXbWt/ElgCJXhQ7JLVJsjhQEN9lqnQiB2THu0+OGmqJhheBZz+5Yul0LA3BcAJx3Wu8TJVI1L/S/n8oRKJDLwrzurrifqnPhv9bkHSSilH8jRCmLoWkAtnqmWoloEt/52KrwnWS44Ze310MpiEEvYc89WqvPZyTIlVht4g7V73AFWc+u6JQD7PcvBvFDJJOro0Xt8UMC6udmxiVjryGtVx4ozktqUdOhYgX7wGnh3JBOGra0WyhMLHeqgCFZrQlyt95CWtDeDxKQtWAlMA1U= Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:1c58:82ab:ea0c:f407]) by smtp.gmail.com with ESMTPSA id h123-20020a0dc581000000b006041f5a308esm134982ywd.133.2024.02.08.18.00.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Feb 2024 18:00:56 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, davemarchevsky@meta.com, dvernet@meta.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v7 1/4] bpf: add btf pointer to struct bpf_ctx_arg_aux. Date: Thu, 8 Feb 2024 18:00:50 -0800 Message-Id: <20240209020053.1132710-2-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240209020053.1132710-1-thinker.li@gmail.com> References: <20240209020053.1132710-1-thinker.li@gmail.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 From: Kui-Feng Lee Enable the providers to use types defined in a module instead of in the kernel (btf_vmlinux). Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 1 + kernel/bpf/btf.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 1ebbee1d648e..9a2ee9456989 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1416,6 +1416,7 @@ struct bpf_ctx_arg_aux { u32 offset; enum bpf_reg_type reg_type; u32 btf_id; + struct btf *btf; }; struct btf_mod_pair { diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 8e06d29961f1..7c6c9fefdbd6 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -6266,7 +6266,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type, } info->reg_type = ctx_arg_info->reg_type; - info->btf = btf_vmlinux; + info->btf = ctx_arg_info->btf ? ctx_arg_info->btf : btf_vmlinux; info->btf_id = ctx_arg_info->btf_id; return true; } From patchwork Fri Feb 9 02:00:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13550799 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-yw1-f180.google.com (mail-yw1-f180.google.com [209.85.128.180]) (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 B5B6D4C97 for ; Fri, 9 Feb 2024 02:00:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444061; cv=none; b=hWKNuXKRhzubOsDQmmVFmtjIv+6HTyRd1SX6obzF7Fe/tHbkBf4QqB5nFf61mX/yEtVaNDalpo3cB9EyoffyDuvAUJn/hW58Pq6COGlsOKj2SWTyG4XBNC9D6FflhufnvJmw4QnmB9YwsdnkjUBq79sAlVcrzKglhgNuHwNfA4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444061; c=relaxed/simple; bh=OEM1teVXmRXxwhKKimMVilsgKi4wDhaucDE3mY4mQR0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IF3fsnfe+np7gUiHyVtL0wwmnRjfrJnbnfs0nbElIObEKWthcPF2dgiUuWW4oFqGtNY8fwWEH5Mzk8cxi4HLJnhTDfez/1RdR4q0YKvOInH8Aiy/EetX9M5teaji4+jyi6zWdxEQ2MDX18XOzEw2Xmxup+lokz8QiQzH6Mp7fhU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YG24dqux; arc=none smtp.client-ip=209.85.128.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YG24dqux" Received: by mail-yw1-f180.google.com with SMTP id 00721157ae682-604819d544cso5602797b3.1 for ; Thu, 08 Feb 2024 18:00:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707444058; x=1708048858; 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=HY2+/0CN+qJ6mOOyTUyPyVR80Te7x3h2sgw+aRJbrBg=; b=YG24dquxc5V/o/3av5Ip22wIeNrybWsCHMVFWHyxfeVskeyNYP4637Hq5kqnVNSyzv JkRmy8a32cnSDpnbioM1tHTzxlpHR1r1gHDop8xxYEQoZWupyoA6kS9QhG51Fhnv/x2z 0hlBhfzLVcLi0gXZFl1AwpbfdMVv5i6FqRd5rkbGizxcwKvG4HDP51AS6Az4gcGZYqCn CulWW411Z4qxyRhDMoRhxl+tr3zyJxJy9ImtWOgJGOGHI0W+P5QlsuXhB2ylGOLEyhUf urne3d7Z+riiDogTtbdp4FoGsU1DcKtoAlVK3+6T1z+UEAyc6V8hVA7RmZRwhYzSBrfx 3QUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707444058; x=1708048858; 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=HY2+/0CN+qJ6mOOyTUyPyVR80Te7x3h2sgw+aRJbrBg=; b=HkLazTC2b7uChw0HNufsJFQSX7KmP8/zpb5+l3BT7GRwD+B0dmcIBRoGZaGlES0UiP soycgAWSKEDXgLWlBtIvRABVLX/szTnFAK1VPYUcu7JLeH0j0j3V5orR/30MOT03Bxmb 4rzp1kuJK3DDv7K+eQLdMJrhyso5Ch689hKKqgnSS8O1iGpRD+zCLK6HzwGgJ4eZdOGO tqAUxEsM6ksvph1gtrJkokhpl4iHoz40HSQON0s5ZEExFMcXEgu2djS4N4MPOmQ3R+u6 jKnO0MaRy6+d66tpx7nEuBMflQa7L9t2NsNiW/RvubCVWjRIykZLw+IJv6v4z/T0oQNB qcaA== X-Gm-Message-State: AOJu0Yz0dTKJSqXCI335MNEEsbV0n2+/ta5zGldEctX2vst1JP3mFFsy MSIdpJv9rIjuWx/yTbjYvzDcfxv9LkNTyegnsG0I8LbSYCB3l9BYUBUfebTls+8= X-Google-Smtp-Source: AGHT+IEu9OnTwWPsEwS23ix1xjm82Opf00CvsI0Huyz8SNwPQpBopcQZDRjz0l5AXP9osB8i8iDXiw== X-Received: by 2002:a0d:e503:0:b0:604:44f2:6959 with SMTP id o3-20020a0de503000000b0060444f26959mr166646ywe.37.1707444058376; Thu, 08 Feb 2024 18:00:58 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCUzLEpsjpe1SjjGko9Utt1WGpz1bA2vFXg46Nactg/4+mWtzTPqtIpdLRs8V/lCl4NoV+PT3WUHCEIkf3ELno2aVAtArO2S9jCIkhHxBqNJh1d7Saz21pkYz1A+4O7OTsPjEomtThLfs037CtK6/TfQcb2V/UBeqRD66WrDDJfLYsUGXtugY1eRUVn2akEbTud9WJlRxOBWp2Z5Ow4Id21XRPSRYMNjx1Fo21jiotYkDZxAM7SLJ/F86ZqePa3h7HO109QWfLJ9D7TNy+jCR5QF/is9N8HXpBAZLxemCBND3mk= Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:1c58:82ab:ea0c:f407]) by smtp.gmail.com with ESMTPSA id h123-20020a0dc581000000b006041f5a308esm134982ywd.133.2024.02.08.18.00.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Feb 2024 18:00:58 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, davemarchevsky@meta.com, dvernet@meta.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v7 2/4] bpf: Move __kfunc_param_match_suffix() to btf.c. Date: Thu, 8 Feb 2024 18:00:51 -0800 Message-Id: <20240209020053.1132710-3-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240209020053.1132710-1-thinker.li@gmail.com> References: <20240209020053.1132710-1-thinker.li@gmail.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 From: Kui-Feng Lee Move __kfunc_param_match_suffix() to btf.c and rename it as btf_param_match_suffix(). It can be reused by bpf_struct_ops later. Signed-off-by: Kui-Feng Lee --- include/linux/btf.h | 4 ++++ kernel/bpf/btf.c | 18 ++++++++++++++++++ kernel/bpf/verifier.c | 38 ++++++++++---------------------------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/include/linux/btf.h b/include/linux/btf.h index 1ee8977b8c95..df76a14c64f6 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -495,6 +495,10 @@ static inline void *btf_id_set8_contains(const struct btf_id_set8 *set, u32 id) return bsearch(&id, set->pairs, set->cnt, sizeof(set->pairs[0]), btf_id_cmp_func); } +bool btf_param_match_suffix(const struct btf *btf, + const struct btf_param *arg, + const char *suffix); + struct bpf_verifier_log; #if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 7c6c9fefdbd6..db53bb76387e 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -8904,3 +8904,21 @@ int __register_bpf_struct_ops(struct bpf_struct_ops *st_ops) } EXPORT_SYMBOL_GPL(__register_bpf_struct_ops); #endif + +bool btf_param_match_suffix(const struct btf *btf, + const struct btf_param *arg, + const char *suffix) +{ + int suffix_len = strlen(suffix), len; + const char *param_name; + + /* In the future, this can be ported to use BTF tagging */ + param_name = btf_name_by_offset(btf, arg->name_off); + if (str_is_empty(param_name)) + return false; + len = strlen(param_name); + if (len <= suffix_len) + return false; + param_name += len - suffix_len; + return !strncmp(param_name, suffix, suffix_len); +} diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ddaf09db1175..c92d6af7d975 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10682,24 +10682,6 @@ static bool is_kfunc_rcu_protected(struct bpf_kfunc_call_arg_meta *meta) return meta->kfunc_flags & KF_RCU_PROTECTED; } -static bool __kfunc_param_match_suffix(const struct btf *btf, - const struct btf_param *arg, - const char *suffix) -{ - int suffix_len = strlen(suffix), len; - const char *param_name; - - /* In the future, this can be ported to use BTF tagging */ - param_name = btf_name_by_offset(btf, arg->name_off); - if (str_is_empty(param_name)) - return false; - len = strlen(param_name); - if (len < suffix_len) - return false; - param_name += len - suffix_len; - return !strncmp(param_name, suffix, suffix_len); -} - static bool is_kfunc_arg_mem_size(const struct btf *btf, const struct btf_param *arg, const struct bpf_reg_state *reg) @@ -10710,7 +10692,7 @@ static bool is_kfunc_arg_mem_size(const struct btf *btf, if (!btf_type_is_scalar(t) || reg->type != SCALAR_VALUE) return false; - return __kfunc_param_match_suffix(btf, arg, "__sz"); + return btf_param_match_suffix(btf, arg, "__sz"); } static bool is_kfunc_arg_const_mem_size(const struct btf *btf, @@ -10723,47 +10705,47 @@ static bool is_kfunc_arg_const_mem_size(const struct btf *btf, if (!btf_type_is_scalar(t) || reg->type != SCALAR_VALUE) return false; - return __kfunc_param_match_suffix(btf, arg, "__szk"); + return btf_param_match_suffix(btf, arg, "__szk"); } static bool is_kfunc_arg_optional(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__opt"); + return btf_param_match_suffix(btf, arg, "__opt"); } static bool is_kfunc_arg_constant(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__k"); + return btf_param_match_suffix(btf, arg, "__k"); } static bool is_kfunc_arg_ignore(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__ign"); + return btf_param_match_suffix(btf, arg, "__ign"); } static bool is_kfunc_arg_alloc_obj(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__alloc"); + return btf_param_match_suffix(btf, arg, "__alloc"); } static bool is_kfunc_arg_uninit(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__uninit"); + return btf_param_match_suffix(btf, arg, "__uninit"); } static bool is_kfunc_arg_refcounted_kptr(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__refcounted_kptr"); + return btf_param_match_suffix(btf, arg, "__refcounted_kptr"); } static bool is_kfunc_arg_nullable(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__nullable"); + return btf_param_match_suffix(btf, arg, "__nullable"); } static bool is_kfunc_arg_const_str(const struct btf *btf, const struct btf_param *arg) { - return __kfunc_param_match_suffix(btf, arg, "__str"); + return btf_param_match_suffix(btf, arg, "__str"); } static bool is_kfunc_arg_scalar_with_name(const struct btf *btf, From patchwork Fri Feb 9 02:00:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13550800 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-yw1-f182.google.com (mail-yw1-f182.google.com [209.85.128.182]) (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 1DFA3538A for ; Fri, 9 Feb 2024 02:01:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444063; cv=none; b=Bh9MlaWTuQmjmQsABygpTV95HQYKuIGhiNmbGZwTMsFLqYORtmGTXqTjKLvrrvsS+XQUnXZdxfZQphQxnF5U6fro640pKxNrQPJX4p1FrcDHgNTgicgnl9taeyDi4nxfMNWNjy7+G9AbDqFI2H7iuyfLQ1oIKJbc8fz2J1sbpag= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444063; c=relaxed/simple; bh=efhGLILJ57/+vF/Ieq4VvkQt3oeiyRVeg5CoWmgvxCs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YmcllMxsxNCUe7xKE22Ys83X9jvIXydN1xGU3NrL2dOqyE2FOGcLuVA/lJedjWE+z81XGsV4xMsk78CCS+t8DKJHQ/G7z1+nhOZVzf7wWC8LGklJe/uDUMhN7qkN36aXf1m9DCV5txdUxnvvH3FMBP045BT2NKq4ED4UBQuATac= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G3mhdUo3; arc=none smtp.client-ip=209.85.128.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G3mhdUo3" Received: by mail-yw1-f182.google.com with SMTP id 00721157ae682-604b4eed8fbso6604887b3.3 for ; Thu, 08 Feb 2024 18:01:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707444060; x=1708048860; 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=UF0P5JrrO9sYXVn5vAyjxmAQ/pBHydjFb/O4TgrSsmw=; b=G3mhdUo35gNCVSUHPISWSgX8N+L8ubLe0QA9V1Scw/xFoJ+92IWPQsJRNdq1Cxe9S6 ldNi4ku23kzG6puTgycc4GOfqq740W/xWvrmahEUD7RbBKSPo9rPTub/9Dul/YjUvPVp rUhnpyKzP42yADCFuKWgOAiv1Y+ufoOVrAo4XoSnlvNSeMjDt83OFn2ZD68DcrecIqSD dVIQXWIwvySuzkFT/PPK7LFQH/d/vspQSiI2nmkAhvYd23SxX/xyHip63rmkiwN9DB3h vwNDqTd9XiL045FuDqvJtEymtDmpN5dLvrI0J4S7CMP+6Mzh4LB2E2SIdaYSi4LdBv0N o7Qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707444060; x=1708048860; 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=UF0P5JrrO9sYXVn5vAyjxmAQ/pBHydjFb/O4TgrSsmw=; b=GDpGwCYz/EnoEdI9IqUE2KrPQYPS4oRkMqzEx2XFK5/Xhx8w6sFyqlfu2iFJukBVvC kH6TH2K5j0e02CJ3bi9HOGpOWJX+q0OQuRWxuv5dow51o4sn/W/BUWnbNkXBRfa+hrbO l3TDDP0tiWM03hFdI7HnajlBlUCi/mwHjfOS4WoaMsfMnLowJ7Bsdu+fZU7flbYuWx/M cq3gjr15YKaMRV3FdMwI9SC42pjrF/g3aFYi/iAFdGtdHQ8Td+XdxSx46qJvazI9sPBt V3txVOFFs6yNss02XENYZ71Ay77w4rEVMEy5RC8LyuDqtbp305go+/1C4emWDup8KCYp XSDg== X-Gm-Message-State: AOJu0Yyby9fQIaEq4KD67rEOSUwrX8TWXKc4tCoXHrua8gB/+bX4c6sN gLUsr917kBQDl3OrUvIPhsTBsd7byDlaXEObcN+QEK9gaHu9683YaBo+Hnw+nHU= X-Google-Smtp-Source: AGHT+IHl63h/g7sdLjHWxC+OIaQI+Yz84plR3UK9TbPUtHwFStY5GRLH2Aw7Nc+iB5xY0XGEzy9mcA== X-Received: by 2002:a81:8946:0:b0:602:c1e2:c6ee with SMTP id z67-20020a818946000000b00602c1e2c6eemr133915ywf.44.1707444059579; Thu, 08 Feb 2024 18:00:59 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCXNWFguJlfk1Dj1bqsUxNz4k46THEomjxge1W6K6rV0mReAU0UJacRJjDNEZqvWA1H01Wls2NzWgSzHy/adAALTEn4OHMf+vJ90XxgZNyp7NsSTZ71PhYlhIK+oepcl1HnMqDWykOXkEmZKCaobrCGb9ssmVUfUEBrWvICxdyrJWAt7ZP6sxfxPPNb17mlHIYfGqjG3spsTzK/5nDiU/86Kix6mqrFYJ/cs/0GQePWD2qRyzaafnX7IHnOXpqGR+Y2rQasSzuO+6KPDOIcDd9P/G6z4KV1bUlI/yjagNKZybfw= Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:1c58:82ab:ea0c:f407]) by smtp.gmail.com with ESMTPSA id h123-20020a0dc581000000b006041f5a308esm134982ywd.133.2024.02.08.18.00.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Feb 2024 18:00:59 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, davemarchevsky@meta.com, dvernet@meta.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v7 3/4] bpf: Create argument information for nullable arguments. Date: Thu, 8 Feb 2024 18:00:52 -0800 Message-Id: <20240209020053.1132710-4-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240209020053.1132710-1-thinker.li@gmail.com> References: <20240209020053.1132710-1-thinker.li@gmail.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 From: Kui-Feng Lee Collect argument information from the type information of stub functions to mark arguments of BPF struct_ops programs with PTR_MAYBE_NULL if they are nullable. A nullable argument is annotated by suffixing "__nullable" at the argument name of stub function. For nullable arguments, this patch sets a struct bpf_ctx_arg_aux to label their reg_type with PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL. This makes the verifier to check programs and ensure that they properly check the pointer. The programs should check if the pointer is null before accessing the pointed memory. The implementer of a struct_ops type should annotate the arguments that can be null. The implementer should define a stub function (empty) as a placeholder for each defined operator. The name of a stub function should be in the pattern "__". For example, for test_maybe_null of struct bpf_testmod_ops, it's stub function name should be "bpf_testmod_ops__test_maybe_null". You mark an argument nullable by suffixing the argument name with "__nullable" at the stub function. Since we already has stub functions for kCFI, we just reuse these stub functions with the naming convention mentioned earlier. These stub functions with the naming convention is only required if there are nullable arguments to annotate. For functions having not nullable arguments, stub functions are not necessary for the purpose of this patch. This patch will prepare a list of struct bpf_ctx_arg_aux, aka arg_info, for each member field of a struct_ops type. "arg_info" will be assigned to "prog->aux->ctx_arg_info" of BPF struct_ops programs in check_struct_ops_btf_id() so that it can be used by btf_ctx_access() later to set reg_type properly for the verifier. Signed-off-by: Kui-Feng Lee --- include/linux/bpf.h | 21 ++++ include/linux/btf.h | 2 + kernel/bpf/bpf_struct_ops.c | 210 +++++++++++++++++++++++++++++++++--- kernel/bpf/btf.c | 27 +++++ kernel/bpf/verifier.c | 6 ++ 5 files changed, 254 insertions(+), 12 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 9a2ee9456989..b4efec1ace48 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1709,6 +1709,19 @@ struct bpf_struct_ops { struct btf_func_model func_models[BPF_STRUCT_OPS_MAX_NR_MEMBERS]; }; +/* Every member of a struct_ops type has an instance even a member is not + * an operator (function pointer). The "info" field will be assigned to + * prog->aux->ctx_arg_info of BPF struct_ops programs to provide the + * argument information required by the verifier to verify the program. + * + * btf_ctx_access() will lookup prog->aux->ctx_arg_info to find the + * corresponding entry for an given argument. + */ +struct bpf_struct_ops_arg_info { + struct bpf_ctx_arg_aux *info; + u32 cnt; +}; + struct bpf_struct_ops_desc { struct bpf_struct_ops *st_ops; @@ -1716,6 +1729,9 @@ struct bpf_struct_ops_desc { const struct btf_type *value_type; u32 type_id; u32 value_id; + + /* Collection of argument information for each member */ + struct bpf_struct_ops_arg_info *arg_info; }; enum bpf_struct_ops_state { @@ -1790,6 +1806,7 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, struct btf *btf, struct bpf_verifier_log *log); void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struct bpf_map *map); +void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_ops_desc); #else #define register_bpf_struct_ops(st_ops, type) ({ (void *)(st_ops); 0; }) static inline bool bpf_try_module_get(const void *data, struct module *owner) @@ -1814,6 +1831,10 @@ static inline void bpf_map_struct_ops_info_fill(struct bpf_map_info *info, struc { } +static inline void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_ops_desc, int len) +{ +} + #endif #if defined(CONFIG_CGROUP_BPF) && defined(CONFIG_BPF_LSM) diff --git a/include/linux/btf.h b/include/linux/btf.h index df76a14c64f6..15ee845e6b38 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -498,6 +498,8 @@ static inline void *btf_id_set8_contains(const struct btf_id_set8 *set, u32 id) bool btf_param_match_suffix(const struct btf *btf, const struct btf_param *arg, const char *suffix); +int btf_ctx_arg_offset(struct btf *btf, const struct btf_type *func_proto, + u32 arg_no); struct bpf_verifier_log; diff --git a/kernel/bpf/bpf_struct_ops.c b/kernel/bpf/bpf_struct_ops.c index f98f580de77a..98448eecbde3 100644 --- a/kernel/bpf/bpf_struct_ops.c +++ b/kernel/bpf/bpf_struct_ops.c @@ -116,17 +116,180 @@ static bool is_valid_value_type(struct btf *btf, s32 value_id, return true; } +#define MAYBE_NULL_SUFFIX "__nullable" +#define MAX_STUB_NAME 128 + +/* Return the type info of a stub function, if it exists. + * + * The name of a stub function is made up of the name of the struct_ops and + * the name of the function pointer member, separated by "__". For example, + * if the struct_ops type is named "foo_ops" and the function pointer + * member is named "bar", the stub function name would be "foo_ops__bar". + */ +static const struct btf_type * +find_stub_func_proto(struct btf *btf, const char *st_op_name, + const char *member_name) +{ + char stub_func_name[MAX_STUB_NAME]; + const struct btf_type *func_type; + s32 btf_id; + int cp; + + cp = snprintf(stub_func_name, MAX_STUB_NAME, "%s__%s", + st_op_name, member_name); + if (cp >= MAX_STUB_NAME) { + pr_warn("Stub function name too long\n"); + return NULL; + } + btf_id = btf_find_by_name_kind(btf, stub_func_name, BTF_KIND_FUNC); + if (btf_id < 0) + return NULL; + func_type = btf_type_by_id(btf, btf_id); + if (!func_type) + return NULL; + + return btf_type_by_id(btf, func_type->type); /* FUNC_PROTO */ +} + +/* Prepare argument info for every nullable argument of a member of a + * struct_ops type. + * + * Initialize a struct bpf_struct_ops_arg_info according to type info of + * the arguments of a stub function. (Check kCFI for more information about + * stub functions.) + * + * Each member in the struct_ops type has a struct bpf_struct_ops_arg_info + * to provide an array of struct bpf_ctx_arg_aux, which in turn provides + * the information that used by the verifier to check the arguments of the + * BPF struct_ops program assigned to the member. Here, we only care about + * the arguments that are marked as __nullable. + * + * The array of struct bpf_ctx_arg_aux is eventually assigned to + * prog->aux->ctx_arg_info of BPF struct_ops programs and passed to the + * verifier. (See check_struct_ops_btf_id()) + * + * arg_info->info will be the list of struct bpf_ctx_arg_aux if success. If + * fails, it will be kept untouched. + */ +static int prepare_arg_info(struct btf *btf, + const char *st_ops_name, + const char *member_name, + const struct btf_type *func_proto, + struct bpf_struct_ops_arg_info *arg_info) +{ + const struct btf_type *stub_func_proto, *pointed_type; + const struct btf_param *stub_args, *args; + struct bpf_ctx_arg_aux *info, *info_buf; + u32 nargs, arg_no, info_cnt = 0; + s32 arg_btf_id; + int offset; + + stub_func_proto = find_stub_func_proto(btf, st_ops_name, member_name); + if (!stub_func_proto) + return 0; + + /* Check if the number of arguments of the stub function is the same + * as the number of arguments of the function pointer. + */ + nargs = btf_type_vlen(func_proto); + if (nargs != btf_type_vlen(stub_func_proto)) { + pr_warn("the number of arguments of the stub function %s__%s does not match the number of arguments of the member %s of struct %s\n", + st_ops_name, member_name, member_name, st_ops_name); + return -EINVAL; + } + + args = btf_params(func_proto); + stub_args = btf_params(stub_func_proto); + + info_buf = kcalloc(nargs, sizeof(*info_buf), GFP_KERNEL); + if (!info_buf) + return -ENOMEM; + + /* Prepare info for every nullable argument */ + info = info_buf; + for (arg_no = 0; arg_no < nargs; arg_no++) { + /* Skip arguments that is not suffixed with + * "__nullable". + */ + if (!btf_param_match_suffix(btf, &stub_args[arg_no], + MAYBE_NULL_SUFFIX)) + continue; + + /* Should be a pointer to struct */ + pointed_type = btf_type_resolve_ptr(btf, + args[arg_no].type, + &arg_btf_id); + if (!pointed_type || + !btf_type_is_struct(pointed_type)) { + pr_warn("stub function %s__%s has %s tagging to an unsupported type\n", + st_ops_name, member_name, MAYBE_NULL_SUFFIX); + goto err_out; + } + + offset = btf_ctx_arg_offset(btf, func_proto, arg_no); + if (offset < 0) { + pr_warn("stub function %s__%s has an invalid trampoline ctx offset for arg#%u\n", + st_ops_name, member_name, arg_no); + goto err_out; + } + + /* Fill the information of the new argument */ + info->reg_type = + PTR_TRUSTED | PTR_TO_BTF_ID | PTR_MAYBE_NULL; + info->btf_id = arg_btf_id; + info->btf = btf; + info->offset = offset; + + info++; + info_cnt++; + } + + if (info_cnt) { + arg_info->info = info_buf; + arg_info->cnt = info_cnt; + } else { + kfree(info_buf); + } + + return 0; + +err_out: + kfree(info_buf); + + return -EINVAL; +} + +/* Clean up the arg_info in a struct bpf_struct_ops_desc. + * + * The callers should pass the length of st_ops_desc->arg_info. + */ +void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_ops_desc) +{ + struct bpf_struct_ops_arg_info *arg_info; + int i; + + arg_info = st_ops_desc->arg_info; + if (!arg_info) + return; + + for (i = 0; i < btf_type_vlen(st_ops_desc->type); i++) + kfree(arg_info[i].info); + + kfree(arg_info); +} + int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, struct btf *btf, struct bpf_verifier_log *log) { struct bpf_struct_ops *st_ops = st_ops_desc->st_ops; + struct bpf_struct_ops_arg_info *arg_info; const struct btf_member *member; const struct btf_type *t; s32 type_id, value_id; char value_name[128]; const char *mname; - int i; + int i, err; if (strlen(st_ops->name) + VALUE_PREFIX_LEN >= sizeof(value_name)) { @@ -160,6 +323,17 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, if (!is_valid_value_type(btf, value_id, t, value_name)) return -EINVAL; + arg_info = kcalloc(btf_type_vlen(t), sizeof(*arg_info), + GFP_KERNEL); + if (!arg_info) + return -ENOMEM; + + st_ops_desc->arg_info = arg_info; + st_ops_desc->type = t; + st_ops_desc->type_id = type_id; + st_ops_desc->value_id = value_id; + st_ops_desc->value_type = btf_type_by_id(btf, value_id); + for_each_member(i, t, member) { const struct btf_type *func_proto; @@ -167,40 +341,52 @@ int bpf_struct_ops_desc_init(struct bpf_struct_ops_desc *st_ops_desc, if (!*mname) { pr_warn("anon member in struct %s is not supported\n", st_ops->name); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto errout; } if (__btf_member_bitfield_size(t, member)) { pr_warn("bit field member %s in struct %s is not supported\n", mname, st_ops->name); - return -EOPNOTSUPP; + err = -EOPNOTSUPP; + goto errout; } func_proto = btf_type_resolve_func_ptr(btf, member->type, NULL); - if (func_proto && - btf_distill_func_proto(log, btf, + if (!func_proto) + continue; + + if (btf_distill_func_proto(log, btf, func_proto, mname, &st_ops->func_models[i])) { pr_warn("Error in parsing func ptr %s in struct %s\n", mname, st_ops->name); - return -EINVAL; + err = -EINVAL; + goto errout; } + + err = prepare_arg_info(btf, st_ops->name, mname, + func_proto, + arg_info + i); + if (err) + goto errout; } if (st_ops->init(btf)) { pr_warn("Error in init bpf_struct_ops %s\n", st_ops->name); - return -EINVAL; + err = -EINVAL; + goto errout; } - st_ops_desc->type_id = type_id; - st_ops_desc->type = t; - st_ops_desc->value_id = value_id; - st_ops_desc->value_type = btf_type_by_id(btf, value_id); - return 0; + +errout: + bpf_struct_ops_desc_release(st_ops_desc); + + return err; } static int bpf_struct_ops_map_get_next_key(struct bpf_map *map, void *key, diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index db53bb76387e..533f02b92c94 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -1699,6 +1699,13 @@ static void btf_free_struct_meta_tab(struct btf *btf) static void btf_free_struct_ops_tab(struct btf *btf) { struct btf_struct_ops_tab *tab = btf->struct_ops_tab; + int i; + + if (!tab) + return; + + for (i = 0; i < tab->cnt; i++) + bpf_struct_ops_desc_release(&tab->ops[i]); kfree(tab); btf->struct_ops_tab = NULL; @@ -6130,6 +6137,26 @@ static bool prog_args_trusted(const struct bpf_prog *prog) } } +int btf_ctx_arg_offset(struct btf *btf, const struct btf_type *func_proto, + u32 arg_no) +{ + const struct btf_param *args; + const struct btf_type *t; + int off = 0, i; + u32 sz; + + args = btf_params(func_proto); + for (i = 0; i < arg_no; i++) { + t = btf_type_by_id(btf, args[i].type); + t = btf_resolve_size(btf, t, &sz); + if (IS_ERR(t)) + return PTR_ERR(t); + off += roundup(sz, 8); + } + + return off; +} + bool btf_ctx_access(int off, int size, enum bpf_access_type type, const struct bpf_prog *prog, struct bpf_insn_access_aux *info) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index c92d6af7d975..72ca27f49616 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -20419,6 +20419,12 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) } } + /* btf_ctx_access() used this to provide argument type info */ + prog->aux->ctx_arg_info = + st_ops_desc->arg_info[member_idx].info; + prog->aux->ctx_arg_info_size = + st_ops_desc->arg_info[member_idx].cnt; + prog->aux->attach_func_proto = func_proto; prog->aux->attach_func_name = mname; env->ops = st_ops->verifier_ops; From patchwork Fri Feb 9 02:00:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kui-Feng Lee X-Patchwork-Id: 13550801 X-Patchwork-Delegate: bpf@iogearbox.net Received: from mail-yw1-f179.google.com (mail-yw1-f179.google.com [209.85.128.179]) (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 51AA9139E for ; Fri, 9 Feb 2024 02:01:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444064; cv=none; b=s4obII/4wbzKCWJdqUDXiIPwd5kDAJpTOD838gFn3gn6UZ0PvBuPdicAy3wjx2+Q4nyHAag77i1Gr1o5YU4EpPMxE7QQoxoxnK0LLtZfFvtYY7iByi1s08DUCB6ucZTrYeZfmpxYOu2AC2HsCwQ5bihLo0gFX8gZe/hIPVInl5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707444064; c=relaxed/simple; bh=tJaEvUHBGfLHhQQ6Z8IUE3m7lUAI+XObVCJa24vf10U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=nO+eG4UkbRFOuDw/peTXlghqmG8TXkcjvaP+TJQqQy1KLFSY6ERs1FbkxWzUBnCzAso4QJp5tU8M78B+kdkAJum4YiOoRoqsAsEPNtkg2ZHC4jbeF5duAxuK8IFi0UmPykGLT6SZ+zZTo4zVKRw5dz57545q3faHOnYwUgUsJEY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Xai/Gfum; arc=none smtp.client-ip=209.85.128.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Xai/Gfum" Received: by mail-yw1-f179.google.com with SMTP id 00721157ae682-604a1581cffso5561937b3.3 for ; Thu, 08 Feb 2024 18:01:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707444061; x=1708048861; 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=KL46QOptrTSppgIc8VdwygxoqnHkFvIWCBIzuCoN1ys=; b=Xai/Gfum+8fK/bctOLtWXPh+UBF2M93WTaBEwMwZHR3KRHHJAozN2U+FufMzFL7Z0f InWbOmp/icTVAjgvocXvQUkN2TyqHFzSD7BLKj9bdySDeRsoKIlYBVab4r8Gqxq/A2FC sOYi1P9+WkcstOB7tmeQRibhmkYnLO2I9/04+xRBfaOh9axzOa3wEuXdKUJCpc6HR7te aLXE+GY+ewTNWBrzD+fxNbvNaNP5pO52LJPo+f0q8biT3BAdscwrvM63mZvkJHPzFrtQ PjdOu/LeC+P73cc5LXYrqWnEuKK6UoP/5hhKRQEZrV/XgjxkFMrWLsC+VWeEhJVyuon2 qmgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707444061; x=1708048861; 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=KL46QOptrTSppgIc8VdwygxoqnHkFvIWCBIzuCoN1ys=; b=enjaeAqQir5Az7zRqhDKbCz63kUAKkNPfyG1jeimplR9sEWGMHB9NaBPUwkUiwOf9s 3WkMPR6GmOsovrzTElbkT/D5JfhkigzA+8B/1bKsEo5tl69ls1G19l3ej48DRLvA1Cod DWz47pNPjI+jyccWfdCuvYkhQ3Avl5f0wwFClGFaQlzgpcNqK/0WQK/UkHmx5IaYStOI LdQS/NuYBoEZjxjQ43BuKR2emXMP/UGQcIsV4a7WovTlWgCkviPkJeXh4oYA9GjgzL/S IcpVYODErt1NJaciugZx1v5DqtTMSglbHJizZetETcTZA7vs7WpDucgl1ibUd6cNRlK5 1Lzw== X-Gm-Message-State: AOJu0Ywf7Cn4kqMg2BUaiq3ChDqmhprMNMGqL22XkdyejdqXMbt6a1tt qOOZq9DIXWB8f+GR+FR5HYujoYvTX0hAqpSmE0mkc0L9+gH65axop5xXd7/B870= X-Google-Smtp-Source: AGHT+IGWwKXbXVtmO8AxiKoZrF0cS9OTHxJtv6MlH2CCeMsUFJTK1B6cGXd60s7Ff94/oDhhAfBEsw== X-Received: by 2002:a0d:dac2:0:b0:603:c656:5e31 with SMTP id c185-20020a0ddac2000000b00603c6565e31mr238177ywe.28.1707444060788; Thu, 08 Feb 2024 18:01:00 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCXUUnD0ORsXrw3yP0UapBdcfw2nhn8tCXvkhgt45qudWmYzsCUNO9UIkDLB1n1JHjcg5qcFsufGj5RP4mk5vylHIPcZsikA19m+akgrQK+vPXOvXWyG3MZVdFavLabo23cx9l2qTJEUKWaT9fGaR3nyWRSv8Q8FQOnVATIoADOCtIPkMtwGPD8rDWDi4G7M/OUWmmKzRkssd/iDQhe1Xbeuj0fR4xTK43RGoLEblblFT7dGmTdcA+6ZE9PBKN6SM0aV2fwADQLTrMzdP6QDYxji89hN8sZSIOS+TbafdBZMdi4= Received: from kickker.attlocal.net ([2600:1700:6cf8:1240:1c58:82ab:ea0c:f407]) by smtp.gmail.com with ESMTPSA id h123-20020a0dc581000000b006041f5a308esm134982ywd.133.2024.02.08.18.00.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Feb 2024 18:01:00 -0800 (PST) From: thinker.li@gmail.com To: bpf@vger.kernel.org, ast@kernel.org, martin.lau@linux.dev, song@kernel.org, kernel-team@meta.com, andrii@kernel.org, davemarchevsky@meta.com, dvernet@meta.com Cc: sinquersw@gmail.com, kuifeng@meta.com, Kui-Feng Lee Subject: [PATCH bpf-next v7 4/4] selftests/bpf: Test PTR_MAYBE_NULL arguments of struct_ops operators. Date: Thu, 8 Feb 2024 18:00:53 -0800 Message-Id: <20240209020053.1132710-5-thinker.li@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240209020053.1132710-1-thinker.li@gmail.com> References: <20240209020053.1132710-1-thinker.li@gmail.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 From: Kui-Feng Lee Test if the verifier verifies nullable pointer arguments correctly for BPF struct_ops programs. "test_maybe_null" in struct bpf_testmod_ops is the operator defined for the test cases here. A BPF program should check a pointer for NULL beforehand to access the value pointed by the nullable pointer arguments, or the verifier should reject the programs. The test here includes two parts; the programs checking pointers properly and the programs not checking pointers beforehand. The test checks if the verifier accepts the programs checking properly and rejects the programs not checking at all. Signed-off-by: Kui-Feng Lee --- .../selftests/bpf/bpf_testmod/bpf_testmod.c | 13 +++++- .../selftests/bpf/bpf_testmod/bpf_testmod.h | 4 ++ .../prog_tests/test_struct_ops_maybe_null.c | 46 +++++++++++++++++++ .../bpf/progs/struct_ops_maybe_null.c | 29 ++++++++++++ .../bpf/progs/struct_ops_maybe_null_fail.c | 24 ++++++++++ 5 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/test_struct_ops_maybe_null.c create mode 100644 tools/testing/selftests/bpf/progs/struct_ops_maybe_null.c create mode 100644 tools/testing/selftests/bpf/progs/struct_ops_maybe_null_fail.c diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c index a06daebc75c9..66787e99ba1b 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c @@ -555,7 +555,11 @@ static int bpf_dummy_reg(void *kdata) { struct bpf_testmod_ops *ops = kdata; - ops->test_2(4, 3); + /* Some test cases (ex. struct_ops_maybe_null) may not have test_2 + * initialized, so we need to check for NULL. + */ + if (ops->test_2) + ops->test_2(4, 3); return 0; } @@ -573,9 +577,16 @@ static void bpf_testmod_test_2(int a, int b) { } +static int bpf_testmod_ops__test_maybe_null(int dummy, + struct task_struct *task__nullable) +{ + return 0; +} + static struct bpf_testmod_ops __bpf_testmod_ops = { .test_1 = bpf_testmod_test_1, .test_2 = bpf_testmod_test_2, + .test_maybe_null = bpf_testmod_ops__test_maybe_null, }; struct bpf_struct_ops bpf_bpf_testmod_ops = { diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h index 537beca42896..c3b0cf788f9f 100644 --- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h +++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.h @@ -5,6 +5,8 @@ #include +struct task_struct; + struct bpf_testmod_test_read_ctx { char *buf; loff_t off; @@ -31,6 +33,8 @@ struct bpf_iter_testmod_seq { struct bpf_testmod_ops { int (*test_1)(void); void (*test_2)(int a, int b); + /* Used to test nullable arguments. */ + int (*test_maybe_null)(int dummy, struct task_struct *task); }; #endif /* _BPF_TESTMOD_H */ diff --git a/tools/testing/selftests/bpf/prog_tests/test_struct_ops_maybe_null.c b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_maybe_null.c new file mode 100644 index 000000000000..01dc2613c8a5 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_maybe_null.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ +#include + +#include "struct_ops_maybe_null.skel.h" +#include "struct_ops_maybe_null_fail.skel.h" + +/* Test that the verifier accepts a program that access a nullable pointer + * with a proper check. + */ +static void maybe_null(void) +{ + struct struct_ops_maybe_null *skel; + + skel = struct_ops_maybe_null__open_and_load(); + if (!ASSERT_OK_PTR(skel, "struct_ops_module_open_and_load")) + return; + + struct_ops_maybe_null__destroy(skel); +} + +/* Test that the verifier rejects a program that access a nullable pointer + * without a check beforehand. + */ +static void maybe_null_fail(void) +{ + struct struct_ops_maybe_null_fail *skel; + + skel = struct_ops_maybe_null_fail__open_and_load(); + if (ASSERT_ERR_PTR(skel, "struct_ops_module_fail__open_and_load")) + return; + + struct_ops_maybe_null_fail__destroy(skel); +} + +void test_struct_ops_maybe_null(void) +{ + /* The verifier verifies the programs at load time, so testing both + * programs in the same compile-unit is complicated. We run them in + * separate objects to simplify the testing. + */ + if (test__start_subtest("maybe_null")) + maybe_null(); + if (test__start_subtest("maybe_null_fail")) + maybe_null_fail(); +} diff --git a/tools/testing/selftests/bpf/progs/struct_ops_maybe_null.c b/tools/testing/selftests/bpf/progs/struct_ops_maybe_null.c new file mode 100644 index 000000000000..b450f72e744a --- /dev/null +++ b/tools/testing/selftests/bpf/progs/struct_ops_maybe_null.c @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ +#include +#include +#include "../bpf_testmod/bpf_testmod.h" + +char _license[] SEC("license") = "GPL"; + +pid_t tgid = 0; + +/* This is a test BPF program that uses struct_ops to access an argument + * that may be NULL. This is a test for the verifier to ensure that it can + * rip PTR_MAYBE_NULL correctly. + */ +SEC("struct_ops/test_maybe_null") +int BPF_PROG(test_maybe_null, int dummy, + struct task_struct *task) +{ + if (task) + tgid = task->tgid; + + return 0; +} + +SEC(".struct_ops.link") +struct bpf_testmod_ops testmod_1 = { + .test_maybe_null = (void *)test_maybe_null, +}; + diff --git a/tools/testing/selftests/bpf/progs/struct_ops_maybe_null_fail.c b/tools/testing/selftests/bpf/progs/struct_ops_maybe_null_fail.c new file mode 100644 index 000000000000..6283099ec383 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/struct_ops_maybe_null_fail.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ +#include +#include +#include "../bpf_testmod/bpf_testmod.h" + +char _license[] SEC("license") = "GPL"; + +pid_t tgid = 0; + +SEC("struct_ops/test_maybe_null_struct_ptr") +int BPF_PROG(test_maybe_null_struct_ptr, int dummy, + struct task_struct *task) +{ + tgid = task->tgid; + + return 0; +} + +SEC(".struct_ops.link") +struct bpf_testmod_ops testmod_struct_ptr = { + .test_maybe_null = (void *)test_maybe_null_struct_ptr, +}; +