From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59D2DC43603 for ; Mon, 16 Dec 2019 11:17:40 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 36BB8206CB for ; Mon, 16 Dec 2019 11:17:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727102AbfLPLRk (ORCPT ); Mon, 16 Dec 2019 06:17:40 -0500 Received: from www62.your-server.de ([213.133.104.62]:43368 "EHLO www62.your-server.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727059AbfLPLRj (ORCPT ); Mon, 16 Dec 2019 06:17:39 -0500 Received: from [2001:1620:665:0:5795:5b0a:e5d5:5944] (helo=localhost) by www62.your-server.de with esmtpsa (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89_1) (envelope-from ) id 1igoNc-0007qp-Ox; Mon, 16 Dec 2019 12:17:36 +0100 Date: Mon, 16 Dec 2019 12:17:36 +0100 From: Daniel Borkmann To: Andrii Nakryiko Cc: bpf@vger.kernel.org, netdev@vger.kernel.org, ast@fb.com, andrii.nakryiko@gmail.com, kernel-team@fb.com Subject: Re: [PATCH v4 bpf-next 2/4] libbpf: support libbpf-provided extern variables Message-ID: <20191216111736.GA14887@linux.fritz.box> References: <20191214014710.3449601-1-andriin@fb.com> <20191214014710.3449601-3-andriin@fb.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20191214014710.3449601-3-andriin@fb.com> User-Agent: Mutt/1.12.1 (2019-06-15) X-Authenticated-Sender: daniel@iogearbox.net X-Virus-Scanned: Clear (ClamAV 0.101.4/25665/Mon Dec 16 10:52:23 2019) Sender: bpf-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: bpf@vger.kernel.org On Fri, Dec 13, 2019 at 05:47:08PM -0800, Andrii Nakryiko wrote: > Add support for extern variables, provided to BPF program by libbpf. Currently > the following extern variables are supported: > - LINUX_KERNEL_VERSION; version of a kernel in which BPF program is > executing, follows KERNEL_VERSION() macro convention, can be 4- and 8-byte > long; > - CONFIG_xxx values; a set of values of actual kernel config. Tristate, > boolean, strings, and integer values are supported. > [...] > > All detected extern variables, are put into a separate .extern internal map. > It, similarly to .rodata map, is marked as read-only from BPF program side, as > well as is frozen on load. This allows BPF verifier to track extern values as > constants and perform enhanced branch prediction and dead code elimination. > This can be relied upon for doing kernel version/feature detection and using > potentially unsupported field relocations or BPF helpers in a CO-RE-based BPF > program, while still having a single version of BPF program running on old and > new kernels. Selftests are validating this explicitly for unexisting BPF > helper. > > Signed-off-by: Andrii Nakryiko [...] > +static int bpf_object__resolve_externs(struct bpf_object *obj, > + const char *config_path) > +{ > + bool need_config = false; > + struct extern_desc *ext; > + int err, i; > + void *data; > + > + if (obj->nr_extern == 0) > + return 0; > + > + data = obj->maps[obj->extern_map_idx].mmaped; > + > + for (i = 0; i < obj->nr_extern; i++) { > + ext = &obj->externs[i]; > + > + if (strcmp(ext->name, "LINUX_KERNEL_VERSION") == 0) { > + void *ext_val = data + ext->data_off; > + __u32 kver = get_kernel_version(); > + > + if (!kver) { > + pr_warn("failed to get kernel version\n"); > + return -EINVAL; > + } > + err = set_ext_value_num(ext, ext_val, kver); > + if (err) > + return err; > + pr_debug("extern %s=0x%x\n", ext->name, kver); > + } else if (strncmp(ext->name, "CONFIG_", 7) == 0) { > + need_config = true; > + } else { > + pr_warn("unrecognized extern '%s'\n", ext->name); > + return -EINVAL; > + } I don't quite like that this is (mainly) tracing-only specific, and that for everything else we just bail out - there is much more potential than just completing above vars. But also, there is also no way to opt-out for application developers of /this specific/ semi-magic auto-completion of externs. bpf_object__resolve_externs() should be changed instead to invoke a callback obj->resolve_externs(). Former can be passed by the application developer to allow them to take care of extern resolution all by themself, and if no callback has been passed, then we default to the one above being set as obj->resolve_externs. > + } > + if (need_config) { > + err = bpf_object__read_kernel_config(obj, config_path, data); > + if (err) > + return -EINVAL; > + } > + for (i = 0; i < obj->nr_extern; i++) { > + ext = &obj->externs[i]; > + > + if (!ext->is_set && !ext->is_weak) { > + pr_warn("extern %s (strong) not resolved\n", ext->name); > + return -ESRCH; > + } else if (!ext->is_set) { > + pr_debug("extern %s (weak) not resolved, defaulting to zero\n", > + ext->name); > + } > + } > + > + return 0; > +} > + > int bpf_object__load_xattr(struct bpf_object_load_attr *attr) > { > struct bpf_object *obj; > @@ -4126,6 +4753,7 @@ int bpf_object__load_xattr(struct bpf_object_load_attr *attr) > obj->loaded = true; > > err = bpf_object__probe_caps(obj); > + err = err ? : bpf_object__resolve_externs(obj, obj->kconfig_path); > err = err ? : bpf_object__sanitize_and_load_btf(obj); > err = err ? : bpf_object__sanitize_maps(obj); > err = err ? : bpf_object__create_maps(obj); [...]