On Thu, Mar 18, 2021 at 12:31 PM Rafael David Tinoco <rafaeldtinoco@xxxxxxxxxx> wrote: > > Unfortunately some distros don't have their accurate kernel version > defined correctly in version.h due to long term support decisions. This > makes LINUX_VERSION_CODE to be defined as the original upstream version > in header, while the running in-kernel version is different. > > Older kernels might still check kern_version during bpf_prog_load(), > making it impossible to load a program that could still be portable. > This patch allows one to override bpf objects kern_version attributes, > so program can bypass this in-kernel check during load. > > Example: > > A kernel 4.15.0-129.132, for example, might have 4.15.18 version defined > in its headers, which is the kernel it is based on, but have a 4.15.0 > version defined within the kernel due to other factors. > > $ export LIBBPF_KERN_VERSION=4.15.18 > $ sudo -E ./portablebpf -v > ... > libbpf: bpf object: kernel_version enforced by env variable: 266002 > ... > > This will also help portable binaries within similar older kernels, as > long as they have their BTF data converted from DWARVES (for example). > > Signed-off-by: Rafael David Tinoco <rafaeldtinoco@xxxxxxxxxx> > --- Libbpf currently provides a way to specify custom kernel version using a special "version" ELF section: int _version SEC("version") = 123; But it seems like you would want to set it at runtime, so this compile-time approach might be problematic. But instead of hijacking get_kernel_version(), it's better to add a simple setter counterpart to bpf_object__kversion() that would just override obj->kern_version. > src/libbpf.c | 12 +++++++++--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/src/libbpf.c b/src/libbpf.c > index 4dc09d3..cbc6e61 100644 > --- a/src/libbpf.c > +++ b/src/libbpf.c > @@ -708,13 +708,19 @@ bpf_object__add_programs(struct bpf_object *obj, Elf_Data *sec_data, > > static __u32 get_kernel_version(void) > { > - __u32 major, minor, patch; > struct utsname info; > + __u32 major, minor, patch, ver; > + char *ptr, *e = getenv("LIBBPF_KERN_VERSION"); > > uname(&info); > - if (sscanf(info.release, "%u.%u.%u", &major, &minor, &patch) != 3) > + ptr = (e != NULL) ? e : (char *) &info.release; > + if (sscanf(ptr, "%u.%u.%u", &major, &minor, &patch) != 3) > return 0; > - return KERNEL_VERSION(major, minor, patch); > + ver = KERNEL_VERSION(major, minor, patch); > + if (e) > + pr_debug("bpf object: kernel_version enforced by env variable: %u\n", ver); > + > + return ver; > } > > static const struct btf_member * > -- > 2.17.1 >