1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * binfmt_misc_ops handler for the transparent-mode case: match a synthetic 4 * riscv ELF header and run the asserting interpreter transparently - the 5 * argument vector untouched, the binary in AT_EXECFD and mm->exe_file 6 * labeled with the binary. 7 */ 8 #include "vmlinux.h" 9 #include <bpf/bpf_helpers.h> 10 #include <bpf/bpf_tracing.h> 11 12 char _license[] SEC("license") = "GPL"; 13 14 #define EI_CLASS 4 15 #define ELFCLASS64 2 16 #define EM_RISCV 243 17 18 extern int bpf_binprm_set_interp(struct linux_binprm *bprm, const char *path, 19 size_t path__sz) __ksym; 20 extern int bpf_binprm_set_flags(struct linux_binprm *bprm, 21 enum bpf_binprm_flags flags) __ksym; 22 23 SEC("struct_ops.s/match") 24 bool BPF_PROG(transparent_match, struct linux_binprm *bprm) 25 { 26 __u16 machine; 27 28 if (bprm->buf[0] != 0x7f || bprm->buf[1] != 'E' || 29 bprm->buf[2] != 'L' || bprm->buf[3] != 'F' || 30 bprm->buf[EI_CLASS] != ELFCLASS64) 31 return false; 32 33 /* e_machine is a 16-bit little-endian field at offset 18. */ 34 machine = (__u8)bprm->buf[18] | ((__u16)(__u8)bprm->buf[19] << 8); 35 return machine == EM_RISCV; 36 } 37 38 SEC("struct_ops.s/load") 39 int BPF_PROG(transparent_load, struct linux_binprm *bprm) 40 { 41 char interp[] = "/tmp/binfmt_transparent_interp"; 42 int err; 43 44 err = bpf_binprm_set_flags(bprm, BPF_BINPRM_TRANSPARENT); 45 if (err) 46 return err; 47 48 /* @path__sz includes the terminating NUL; 0 commits the selection. */ 49 return bpf_binprm_set_interp(bprm, interp, sizeof(interp)); 50 } 51 52 SEC(".struct_ops.link") 53 struct binfmt_misc_ops transparent = { 54 .match = (void *)transparent_match, 55 .load = (void *)transparent_load, 56 .name = "transparent", 57 }; 58