Received: by 2002:a05:6500:1b45:b0:1f5:f2ab:c469 with SMTP id cz5csp994037lqb; Wed, 17 Apr 2024 18:07:56 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCVO9EggBsyubiXD2wM+jVwnClucMik9a36LOOeo+JdDC5BXU4Reuo3r30FuX/ypWfRYHvM7hKj/czgmJE8mCLvT/Ef6IM7HjMCjOfzRZA== X-Google-Smtp-Source: AGHT+IGe1+WWqvZ6y2izepmLUNo6knsl38NsFZFYXeB2bKa0S59Th8svOy/TONfm68uGohuH8bSP X-Received: by 2002:a05:6359:4183:b0:183:66a7:b247 with SMTP id ki3-20020a056359418300b0018366a7b247mr1112827rwc.32.1713402476555; Wed, 17 Apr 2024 18:07:56 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1713402475; cv=pass; d=google.com; s=arc-20160816; b=iUVAAzf2T1P9LJXRSW9MST0yXvqcu14aLX47u9rChZ6M7N9qxkZQM3NzVk1rz81kND yK5/Ps8zuv1QCnGtmlx+8BHDZQBbf3aWv9PcxWQSYj6vTy00yVV0RRzioZ9B4lQAXRFK uLsF3vCTB3S45TiuC9YiIwbLUvd4arM2d7SAkEaF9EVAZf1a8E56Rn9rQrly6z5yoSLv GzlnOGkQO71SRUHBnqlGPhp2aCY/3ktfdMKPBMudHE73r4cUxhjWUojXgufIH1TMtyCh Z+UfW/CAHBkOExLRQANCUUJGVAcicx+z61HyynRSqD6P8akBynOMTtzHJSy/1XvlrGuI 2NYg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:from:subject:message-id:references:mime-version :list-unsubscribe:list-subscribe:list-id:precedence:in-reply-to:date :dkim-signature; bh=3Rwr3eeaVXhAcle1iJOgXmRS8H6PJaYqRipuqiAZK/g=; fh=YVKBRm8iqnQ6kzXScEvUl8umONRKgcR3IxaIPYYKoPk=; b=DT2VUkCx6G4S1qoWZIaevfY27gGle2DaiBow2qcPCHSyND6b0qxTJniheKQUQayIee 9lKykXzZP3VMN5j6VjT5yOmpb8HXucbpOz8q4+msuPrymbPzwSa65zqX+f/1Akvi0Xir gT/Gp6pDO5JeJXktOma7q6ZLsqxpzW5a9j5HF5GrpDyDtLYpMegIZJ0U5KLHFYFxxhPj OkNzHrfWM6bAFVByEm022n32kZOJdi+Zal/gQme6ApPYLZ9QyjU7jh2qir0/TLmT+YfF MGj0SzrRSbs6l5m0Ooonhu+rxmTeSr5SpEp92pyX2BMeV17JesSwcR9gEiDyiTm4uAh9 BTNg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=ePNiZwSd; arc=pass (i=1 spf=pass spfdomain=flex--edliaw.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-149376-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-149376-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id m13-20020a634c4d000000b005f401ca2a72si364573pgl.242.2024.04.17.18.07.55 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 17 Apr 2024 18:07:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-149376-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=ePNiZwSd; arc=pass (i=1 spf=pass spfdomain=flex--edliaw.bounces.google.com dkim=pass dkdomain=google.com dmarc=pass fromdomain=google.com); spf=pass (google.com: domain of linux-kernel+bounces-149376-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-149376-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id 5F121281F01 for ; Thu, 18 Apr 2024 01:07:53 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A71506AD6; Thu, 18 Apr 2024 01:07:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ePNiZwSd" Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (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 0BC7A1E521 for ; Thu, 18 Apr 2024 01:07:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713402452; cv=none; b=GZsUUD9VhONFcErR6Tkh2+dls/ExsK0ao/dV6pzGsWnDOtSPTtWfDvGezavWZYSoWHz/s+31pT/bSJ0qiQ2NsDtl/ZYyQzpdk4P4k2PUhWnMLcIbtudJCEhI7liPENF8M2wDpVNRDs3DIsiJYynnEfClRVnUP7C+WNCTTcoQbmE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713402452; c=relaxed/simple; bh=d167ZLj6rlIcq7zB/ehHfuDbNcPrOcrdXiROJHMaMDk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=DWGT91op20iwnthqJzos6ojAUw+fsU7ii7+3rndqG5UC3AESGxpPeXr376gBIN7+gOEOcO1m6QU4Ys57M+NSFCPnbbe/bKz74Mc98w2RUbatPq8n/0beWF6VmjN0L72XTC/SD8U0BtVfVanwtVBqptvnjXETwi7St/ZuVQrWh34= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--edliaw.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ePNiZwSd; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--edliaw.bounces.google.com Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-60a2386e932so6016647b3.1 for ; Wed, 17 Apr 2024 18:07:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1713402450; x=1714007250; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=3Rwr3eeaVXhAcle1iJOgXmRS8H6PJaYqRipuqiAZK/g=; b=ePNiZwSdJHiBAAiDjdprVRScVDMZjWEwdgOCCm85HNP66RDaOdnDMUnz9qwLmLynLm r0+SqpEJeyC05XYn3UHRXNlnkR98GUsox7vwbUBNiRHUuDNrvEOTZSBRIPrmpUjVQp+E JG5baIwdAW7Qz5RrspSzJEMNAGU4uXdJvs5kdmhM7rHmlollmE2DOqmYlnJOY2m5jMix v/8kPoh1WALoXSHmgq5H0yIQcM07NChZOPDLH23jlXCE5RXZU37tk+Cb6khLDCBDiV2k /4AJaQi6af7m+ee4QKDmP/0XLsvZ0a76I5tETuGM1n+VNzTLe+ZzltZEB2ghx70Sze7T mehQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713402450; x=1714007250; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=3Rwr3eeaVXhAcle1iJOgXmRS8H6PJaYqRipuqiAZK/g=; b=f0KxHzYDMHGelq3VqWOa8zZYxjsJxtzJE/7aFQiP4qOBUv6kJYoHqQcNaTAe/DsS8P KxhUNPNpsgFXVMix9qvdDHhVdhOXrrjw+cHsAKBHNJTY9K5Ss2UOVb4N8cFTdJRRQBJu H8m54TxJMwsC7dkQ8VAievVbNpWMtydDpo/KhLnm2JJPcmsYzHdk4pnjuLtVieE/qgN3 Xk6gVIZj02K1TV+fNGonpBREN2xFIwyX2E88ewZC0Tm0U7cXU1GGULw9/bzBFCc6FUO2 n7NkbXWgXyJOJ9qTLebICxhYOT/HjFmEFpkFDjKvzc4laRYRuVcvWeE4mHIhZ+pS0aiu B3sA== X-Forwarded-Encrypted: i=1; AJvYcCVVhz4dx0AKfXlc2Mw/qY19hpMoTxZQfWHyrysFMYWKw4KBKwnMIpxqimZaIWejoev/LJmGmx+E6YswHmEFxXwkpWYVCfi07D5Ol7TZ X-Gm-Message-State: AOJu0YwnMJ1+oacw33j1BzmD9qmTioxXKeeb31i6vGOyfBDv6oG0SuAd 5eiCji39U+bQ9RPdGwTcmXzCdzWJzlI2174ARo+jgK5kSYzCcrHpeGalQ/co0xCE4a4JH1evJri Y2Q== X-Received: from edliaw.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:305d]) (user=edliaw job=sendgmr) by 2002:a0d:f801:0:b0:61b:a3:d445 with SMTP id i1-20020a0df801000000b0061b00a3d445mr201303ywf.7.1713402449959; Wed, 17 Apr 2024 18:07:29 -0700 (PDT) Date: Thu, 18 Apr 2024 01:07:10 +0000 In-Reply-To: <20240418010723.3069001-1-edliaw@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <16430256912363@kroah.com> <20240418010723.3069001-1-edliaw@google.com> X-Mailer: git-send-email 2.44.0.769.g3c40516874-goog Message-ID: <20240418010723.3069001-2-edliaw@google.com> Subject: [PATCH 5.15.y v2 1/5] bpf: Extend kfunc with PTR_TO_CTX, PTR_TO_MEM argument support From: Edward Liaw To: stable@vger.kernel.org, Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Hao Luo Cc: bpf@vger.kernel.org, kernel-team@android.com, Edward Liaw , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Kumar Kartikeya Dwivedi Content-Type: text/plain; charset="UTF-8" From: Kumar Kartikeya Dwivedi Allow passing PTR_TO_CTX, if the kfunc expects a matching struct type, and punt to PTR_TO_MEM block if reg->type does not fall in one of PTR_TO_BTF_ID or PTR_TO_SOCK* types. This will be used by future commits to get access to XDP and TC PTR_TO_CTX, and pass various data (flags, l4proto, netns_id, etc.) encoded in opts struct passed as pointer to kfunc. For PTR_TO_MEM support, arguments are currently limited to pointer to scalar, or pointer to struct composed of scalars. This is done so that unsafe scenarios (like passing PTR_TO_MEM where PTR_TO_BTF_ID of in-kernel valid structure is expected, which may have pointers) are avoided. Since the argument checking happens basd on argument register type, it is not easy to ascertain what the expected type is. In the future, support for PTR_TO_MEM for kfunc can be extended to serve other usecases. The struct type whose pointer is passed in may have maximum nesting depth of 4, all recursively composed of scalars or struct with scalars. Future commits will add negative tests that check whether these restrictions imposed for kfunc arguments are duly rejected by BPF verifier or not. Signed-off-by: Kumar Kartikeya Dwivedi Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20211217015031.1278167-4-memxor@gmail.com (cherry picked from commit 3363bd0cfbb80dfcd25003cd3815b0ad8b68d0ff) [edliaw: fixed up with changes from 45ce4b4f90091 ("bpf: Fix crash due to out of bounds access into reg2btf_ids.")] Signed-off-by: Edward Liaw --- kernel/bpf/btf.c | 93 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 0c2fa93bd8d2..9a0db26a3bfa 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -5441,6 +5441,46 @@ static u32 *reg2btf_ids[__BPF_REG_TYPE_MAX] = { #endif }; +/* Returns true if struct is composed of scalars, 4 levels of nesting allowed */ +static bool __btf_type_is_scalar_struct(struct bpf_verifier_log *log, + const struct btf *btf, + const struct btf_type *t, int rec) +{ + const struct btf_type *member_type; + const struct btf_member *member; + u32 i; + + if (!btf_type_is_struct(t)) + return false; + + for_each_member(i, t, member) { + const struct btf_array *array; + + member_type = btf_type_skip_modifiers(btf, member->type, NULL); + if (btf_type_is_struct(member_type)) { + if (rec >= 3) { + bpf_log(log, "max struct nesting depth exceeded\n"); + return false; + } + if (!__btf_type_is_scalar_struct(log, btf, member_type, rec + 1)) + return false; + continue; + } + if (btf_type_is_array(member_type)) { + array = btf_type_array(member_type); + if (!array->nelems) + return false; + member_type = btf_type_skip_modifiers(btf, array->type, NULL); + if (!btf_type_is_scalar(member_type)) + return false; + continue; + } + if (!btf_type_is_scalar(member_type)) + return false; + } + return true; +} + static int btf_check_func_arg_match(struct bpf_verifier_env *env, const struct btf *btf, u32 func_id, struct bpf_reg_state *regs, @@ -5449,6 +5489,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, enum bpf_prog_type prog_type = env->prog->type == BPF_PROG_TYPE_EXT ? env->prog->aux->dst_prog->type : env->prog->type; struct bpf_verifier_log *log = &env->log; + bool is_kfunc = btf_is_kernel(btf); const char *func_name, *ref_tname; const struct btf_type *t, *ref_t; const struct btf_param *args; @@ -5501,7 +5542,20 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, ref_t = btf_type_skip_modifiers(btf, t->type, &ref_id); ref_tname = btf_name_by_offset(btf, ref_t->name_off); - if (btf_is_kernel(btf)) { + if (btf_get_prog_ctx_type(log, btf, t, + env->prog->type, i)) { + /* If function expects ctx type in BTF check that caller + * is passing PTR_TO_CTX. + */ + if (reg->type != PTR_TO_CTX) { + bpf_log(log, + "arg#%d expected pointer to ctx, but got %s\n", + i, btf_type_str(t)); + return -EINVAL; + } + if (check_ctx_reg(env, reg, regno)) + return -EINVAL; + } else if (is_kfunc && (reg->type == PTR_TO_BTF_ID || reg2btf_ids[base_type(reg->type)])) { const struct btf_type *reg_ref_t; const struct btf *reg_btf; const char *reg_ref_tname; @@ -5517,14 +5571,9 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, if (reg->type == PTR_TO_BTF_ID) { reg_btf = reg->btf; reg_ref_id = reg->btf_id; - } else if (reg2btf_ids[base_type(reg->type)]) { + } else { reg_btf = btf_vmlinux; reg_ref_id = *reg2btf_ids[base_type(reg->type)]; - } else { - bpf_log(log, "kernel function %s args#%d expected pointer to %s %s but R%d is not a pointer to btf_id\n", - func_name, i, - btf_type_str(ref_t), ref_tname, regno); - return -EINVAL; } reg_ref_t = btf_type_skip_modifiers(reg_btf, reg_ref_id, @@ -5540,22 +5589,24 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, reg_ref_tname); return -EINVAL; } - } else if (btf_get_prog_ctx_type(log, btf, t, prog_type, i)) { - /* If function expects ctx type in BTF check that caller - * is passing PTR_TO_CTX. - */ - if (reg->type != PTR_TO_CTX) { - bpf_log(log, - "arg#%d expected pointer to ctx, but got %s\n", - i, btf_type_str(t)); - return -EINVAL; - } - if (check_ctx_reg(env, reg, regno)) - return -EINVAL; } else if (ptr_to_mem_ok) { const struct btf_type *resolve_ret; u32 type_size; + if (is_kfunc) { + /* Permit pointer to mem, but only when argument + * type is pointer to scalar, or struct composed + * (recursively) of scalars. + */ + if (!btf_type_is_scalar(ref_t) && + !__btf_type_is_scalar_struct(log, btf, ref_t, 0)) { + bpf_log(log, + "arg#%d pointer type %s %s must point to scalar or struct with scalar\n", + i, btf_type_str(ref_t), ref_tname); + return -EINVAL; + } + } + resolve_ret = btf_resolve_size(btf, ref_t, &type_size); if (IS_ERR(resolve_ret)) { bpf_log(log, @@ -5568,6 +5619,8 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, if (check_mem_reg(env, reg, regno, type_size)) return -EINVAL; } else { + bpf_log(log, "reg type unsupported for arg#%d %sfunction %s#%d\n", i, + is_kfunc ? "kernel " : "", func_name, func_id); return -EINVAL; } } @@ -5617,7 +5670,7 @@ int btf_check_kfunc_arg_match(struct bpf_verifier_env *env, const struct btf *btf, u32 func_id, struct bpf_reg_state *regs) { - return btf_check_func_arg_match(env, btf, func_id, regs, false); + return btf_check_func_arg_match(env, btf, func_id, regs, true); } /* Convert BTF of a function into bpf_reg_state if possible -- 2.44.0.769.g3c40516874-goog