projects/linux·blob master · refs

57 lines · 1.6 KiB

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
12char _license[] SEC("license") = "GPL";
13
14#define EI_CLASS 4
15#define ELFCLASS64 2
16#define EM_RISCV 243
17
18extern int bpf_binprm_set_interp(struct linux_binprm *bprm, const char *path,
19 size_t path__sz) __ksym;
20extern int bpf_binprm_set_flags(struct linux_binprm *bprm,
21 enum bpf_binprm_flags flags) __ksym;
22
23SEC("struct_ops.s/match")
24bool 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
38SEC("struct_ops.s/load")
39int 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
52SEC(".struct_ops.link")
53struct binfmt_misc_ops transparent = {
54 .match = (void *)transparent_match,
55 .load = (void *)transparent_load,
56 .name = "transparent",
57};