From 8a1b7cc617b685e14bdcec8f6f5e80c18e2ef416 Mon Sep 17 00:00:00 2001 From: Donald Buczek Date: Tue, 25 Jan 2022 18:55:57 +0100 Subject: [PATCH] Import existing files into repository --- .gitignore | 2 + build.sh | 24 +++++++++ fix-lpp/.gitignore | 6 +++ fix-lpp/Makefile | 7 +++ fix-lpp/fix-lpp.c | 130 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 169 insertions(+) create mode 100644 .gitignore create mode 100755 build.sh create mode 100644 fix-lpp/.gitignore create mode 100644 fix-lpp/Makefile create mode 100644 fix-lpp/fix-lpp.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..409e53a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +out +*.o diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..9660f18 --- /dev/null +++ b/build.sh @@ -0,0 +1,24 @@ +#! /bin/bash + +set -xe + +releases=( + 5.10.92-421 5.10.82-414 5.10.70-403 5.10.47-390 5.10.24-375 + 5.4.97-368 5.4.72-349 5.4.57-340 5.4.39-334 +) + +for release in "${releases[@]}"; do + test -d /scratch/local/linux-$release.x86_64 || (cd /scratch/local && tar xf /src/mariux/beeroot/build-archives/linux-$release.x86_64.beebuild.tar.bz2) + ( + cd fix-lpp + KERNEL=/scratch/local/linux-$release.x86_64/build make clean + KERNEL=/scratch/local/linux-$release.x86_64/build make + ) + ver=${release%-*} # 5.10.92 + build=${release#*-} # 421 + echo "release $release ver $ver build $build" + mkdir -p out/$ver.mx64.$build + cp fix-lpp/fix-lpp.ko out/$ver.mx64.$build/fix-lpp.ko +done + + diff --git a/fix-lpp/.gitignore b/fix-lpp/.gitignore new file mode 100644 index 0000000..8e1e220 --- /dev/null +++ b/fix-lpp/.gitignore @@ -0,0 +1,6 @@ +*.cmd +Module.symvers +*.ko +*.mod +*.mod.c +modules.order diff --git a/fix-lpp/Makefile b/fix-lpp/Makefile new file mode 100644 index 0000000..1094eb3 --- /dev/null +++ b/fix-lpp/Makefile @@ -0,0 +1,7 @@ +obj-m += fix-lpp.o + +all: + make -C $(KERNEL) M=$(PWD) modules + +clean: + make -C $(KERNEL) M=$(PWD) clean diff --git a/fix-lpp/fix-lpp.c b/fix-lpp/fix-lpp.c new file mode 100644 index 0000000..90260c3 --- /dev/null +++ b/fix-lpp/fix-lpp.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Donald Buczek "); +MODULE_DESCRIPTION("fix-lpp"); +MODULE_VERSION("0.01"); + +/* + * General concept to hook a kernel function with ftrace: + * + * https://www.codeproject.com/Articles/1275114/Hooking-Linux-Kernel-Functions-Part-2-How-to-Hook + * + * Idea to hack around the no longer exported kallsyms_lookup_name with register_kprobe + * originally from AMD developers in the comments of this thread: + * + * https://lwn.net/Articles/813350/ + */ + +/* function signature as defined in kernel source */ + +typedef int legacy_parse_param_fn_type(struct fs_context *fc, struct fs_parameter *param); + +static legacy_parse_param_fn_type *legacy_parse_param; +static legacy_parse_param_fn_type legacy_parse_param_wrapper; + +enum legacy_fs_param { + LEGACY_FS_UNSET_PARAMS, + LEGACY_FS_MONOLITHIC_PARAMS, + LEGACY_FS_INDIVIDUAL_PARAMS, +}; + +struct legacy_fs_context { + char *legacy_data; /* Data page for legacy filesystems */ + size_t data_size; + enum legacy_fs_param param_type; +}; + +static __attribute__((optimize("no-optimize-sibling-calls"))) +int legacy_parse_param_wrapper(struct fs_context *fc, struct fs_parameter *param) +{ + struct legacy_fs_context *ctx = fc->fs_private; + unsigned int size = ctx->data_size; + size_t len = 0; + + switch (param->type) { + case fs_value_is_string: + len = 1 + param->size; + fallthrough; + case fs_value_is_flag: + len += strlen(param->key); + break; + default: + break; + } + if (size + len + 2 > PAGE_SIZE) + return invalf(fc, "VFS: Legacy: Cumulative options too large"); + + return legacy_parse_param(fc, param); +} + +static void ftrace_callback(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *ops, struct pt_regs *regs) +{ + if (!within_module(parent_ip, THIS_MODULE)) + regs->ip = (unsigned long)legacy_parse_param_wrapper; +} + +static int get_symbol_via_kprobe(char *name, void **addr) +{ + struct kprobe kp; + int err; + memset(&kp, 0, sizeof(kp)); + kp.symbol_name = name; + err = register_kprobe(&kp); + if (err) { + return err; + } + *addr = kp.addr; + unregister_kprobe(&kp); + return 0; +} + +static struct ftrace_ops ops = { + .func = ftrace_callback, + .flags = FTRACE_OPS_FL_SAVE_REGS|FTRACE_OPS_FL_IPMODIFY +}; + +static int __init fix_lpp_init(void) +{ + int err; + + err = get_symbol_via_kprobe("legacy_parse_param", (void **)&legacy_parse_param); + if (err) { + pr_err("fix_lpp: can't find legacy_parse_param: %d\n", err); + return(err); + } + + err = ftrace_set_filter_ip(&ops, (unsigned long)legacy_parse_param, 0, 0); + if (err) { + pr_err("fix_lpp: ftrace_set_filter_ip failed: %d\n", err); + return(err); + + } + err = register_ftrace_function(&ops); + if (err) { + pr_err("fix_lpp: register_ftrace_function failed: %d\n", err); + return(err); + + } + pr_info("fix-lpp: installed\n"); + return 0; +} + +static void __exit fix_lpp_exit(void) +{ + int err; + err = unregister_ftrace_function(&ops); + if (err) { + pr_err("fix_lpp: unregister_ftrace_function failed: %d\n", err); + } + pr_info("fix-lpp: removed\n"); +} + +module_init(fix_lpp_init); +module_exit(fix_lpp_exit);