Re: [PATCH bpf-next v2 1/1] libbpf: Correctly set the kernel code version in Debian kernel.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 1, 2023 at 10:33 PM Hao Xiang . <hao.xiang@xxxxxxxxxxxxx> wrote:
>
> In a previous commit, Ubuntu kernel code version is correctly set
> by retrieving the information from /proc/version_signature.
>
> commit<5b3d72987701d51bf31823b39db49d10970f5c2d>
> (libbpf: Improve LINUX_VERSION_CODE detection)
>
> The /proc/version_signature file doesn't present in at least the
> older versions of Debian distributions (eg, Debian 9, 10). The Debian
> kernel has a similar issue where the release information from uname()
> syscall doesn't give the kernel code version that matches what the
> kernel actually expects. Below is an example content from Debian 10.
>
> release: 4.19.0-23-amd64
> version: #1 SMP Debian 4.19.269-1 (2022-12-20) x86_64
>
> Debian reports incorrect kernel version in utsname::release returned
> by uname() syscall, which in older kernels (Debian 9, 10) leads to
> kprobe BPF programs failing to load due to the version check mismatch.
>
> Fortunately, the correct kernel code version presents in the
> utsname::version returned by uname() syscall in Debian kernels. This
> change adds another get kernel version function to handle Debian in
> addition to the previously added get kernel version function to handle
> Ubuntu. Some minor refactoring work is also done to make the code more
> readable.
>
> Signed-off-by: Hao Xiang <hao.xiang@xxxxxxxxxxxxx>
> ---

Are you basing your patches on top of bpf-next/master? BPF CI claims
that your patch has merge conflicts ([0])

  [0] https://patchwork.kernel.org/project/netdevbpf/patch/CAAYibXgCncBUj8m03iGvOgq8dt2evNHFh0BO1-EnAjtkf+c5yg@xxxxxxxxxxxxxx/


> tools/lib/bpf/libbpf.c        | 37 --------------
> tools/lib/bpf/libbpf_probes.c | 93 +++++++++++++++++++++++++++++++++++
> 2 files changed, 93 insertions(+), 37 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index eed5cec6f510..4191a78b2815 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -34,7 +34,6 @@
> #include <linux/limits.h>
> #include <linux/perf_event.h>
> #include <linux/ring_buffer.h>
> -#include <linux/version.h>
> #include <sys/epoll.h>
> #include <sys/ioctl.h>
> #include <sys/mman.h>
> @@ -870,42 +869,6 @@ bpf_object__add_programs(struct bpf_object *obj,
> Elf_Data *sec_data,
>         return 0;
> }
>
> -__u32 get_kernel_version(void)
> -{
> -        /* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
> -         * but Ubuntu provides /proc/version_signature file, as described at
> -         * https://ubuntu.com/kernel, with an example contents below, which we
> -         * can use to get a proper LINUX_VERSION_CODE.
> -         *
> -         *   Ubuntu 5.4.0-12.15-generic 5.4.8
> -         *
> -         * In the above, 5.4.8 is what kernel is actually expecting, while
> -         * uname() call will return 5.4.0 in info.release.
> -         */
> -        const char *ubuntu_kver_file = "/proc/version_signature";
> -        __u32 major, minor, patch;
> -        struct utsname info;
> -
> -        if (faccessat(AT_FDCWD, ubuntu_kver_file, R_OK, AT_EACCESS) == 0) {
> -                FILE *f;
> -
> -                f = fopen(ubuntu_kver_file, "r");
> -                if (f) {
> -                        if (fscanf(f, "%*s %*s %d.%d.%d\n", &major,
> &minor, &patch) == 3) {
> -                                fclose(f);
> -                                return KERNEL_VERSION(major, minor, patch);
> -                        }
> -                        fclose(f);
> -                }
> -                /* something went wrong, fall back to uname() approach */
> -        }
> -
> -        uname(&info);
> -        if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3)
> -                return 0;
> -        return KERNEL_VERSION(major, minor, patch);
> -}
> -
> static const struct btf_member *
> find_member_by_offset(const struct btf_type *t, __u32 bit_offset)
> {
> diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
> index b44fcbb4b42e..8d2a2bc5eec9 100644
> --- a/tools/lib/bpf/libbpf_probes.c
> +++ b/tools/lib/bpf/libbpf_probes.c
> @@ -12,11 +12,104 @@
> #include <linux/btf.h>
> #include <linux/filter.h>
> #include <linux/kernel.h>
> +#include <linux/version.h>
>
> #include "bpf.h"
> #include "libbpf.h"
> #include "libbpf_internal.h"
>
> +/* On Ubuntu LINUX_VERSION_CODE doesn't correspond to info.release,
> + * but Ubuntu provides /proc/version_signature file, as described at
> + * https://ubuntu.com/kernel, with an example contents below, which we
> + * can use to get a proper LINUX_VERSION_CODE.
> + *
> + *   Ubuntu 5.4.0-12.15-generic 5.4.8
> + *
> + * In the above, 5.4.8 is what kernel is actually expecting, while
> + * uname() call will return 5.4.0 in info.release.
> + */
> +static __u32 get_ubuntu_kernel_version(void)
> +{
> +        const char *ubuntu_kver_file = "/proc/version_signature";
> +        __u32 major, minor, patch;
> +
> +        if (faccessat(AT_FDCWD, ubuntu_kver_file, R_OK, AT_EACCESS) == 0) {

nit: invert condition and exit early

> +                FILE *f;
> +
> +                f = fopen(ubuntu_kver_file, "r");
> +                if (f) {

same, invert and return


> +                        if (fscanf(f, "%*s %*s %d.%d.%d\n", &major,
> &minor, &patch) == 3) {

let's also use %u just like you do in the new code

> +                                fclose(f);
> +                                return KERNEL_VERSION(major, minor, patch);
> +                        }
> +                        fclose(f);
> +                }
> +                /* something went wrong, fall back to uname() approach */
> +        }
> +
> +        return 0;
> +}
> +
> +/* On Debian LINUX_VERSION_CODE doesn't correspond to info.release.
> + * Instead, it is provided in info.version. An example content of
> + * Debian 10 looks like the below.
> + *
> + *   utsname::release   4.19.0-22-amd64
> + *   utsname::version   #1 SMP Debian 4.19.260-1 (2022-09-29)
> + *
> + * In the above, 4.19.260 is what kernel is actually expecting, while
> + * uname() call will return 4.19.0 in info.release.
> + */
> +static __u32 get_debian_kernel_version(struct utsname *info)
> +{
> +        __u32 major, minor, patch;
> +        char *version;
> +        char *p;
> +
> +        version = info->version;
> +
> +        p = strstr(version, "Debian ");
> +        if (!p) {
> +                /* This is not a Debian kernel. */
> +                return 0;
> +        }
> +
> +        if (sscanf(p, "Debian %u.%u.%u", &major, &minor, &patch) != 3)
> +                return 0;
> +
> +        return KERNEL_VERSION(major, minor, patch);
> +}
> +
> +static __u32 get_general_kernel_version(struct utsname *info)
> +{
> +        __u32 major, minor, patch;
> +
> +        if (sscanf(info->release, "%u.%u.%u", &major, &minor, &patch) != 3)
> +                return 0;
> +
> +        return KERNEL_VERSION(major, minor, patch);
> +}

just put this at the bottom of get_kernel_version, not worth having a
separate function for generic case, IMO

> +
> +__u32 get_kernel_version(void)
> +{
> +        __u32 version;
> +        struct utsname info;
> +
> +        /* Check if this is an Ubuntu kernel. */
> +        version = get_ubuntu_kernel_version();
> +        if (version != 0)
> +                return version;
> +
> +        uname(&info);
> +
> +        /* Check if this is a Debian kernel. */
> +        version = get_debian_kernel_version(&info);
> +        if (version != 0)
> +                return version;
> +
> +        return get_general_kernel_version(&info);
> +}
> +
> static int probe_prog_load(enum bpf_prog_type prog_type,
>                            const struct bpf_insn *insns, size_t insns_cnt,
>                            char *log_buf, size_t log_buf_sz)
> --
> 2.30.2



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux