1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * e_bpf.c BPF exec proxy
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can distribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Daniel Borkmann <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker */
11*de1e4e89SAndroid Build Coastguard Worker
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
14*de1e4e89SAndroid Build Coastguard Worker
15*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
16*de1e4e89SAndroid Build Coastguard Worker
17*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
18*de1e4e89SAndroid Build Coastguard Worker
19*de1e4e89SAndroid Build Coastguard Worker #include "bpf_util.h"
20*de1e4e89SAndroid Build Coastguard Worker #include "bpf_elf.h"
21*de1e4e89SAndroid Build Coastguard Worker #include "bpf_scm.h"
22*de1e4e89SAndroid Build Coastguard Worker
23*de1e4e89SAndroid Build Coastguard Worker #define BPF_DEFAULT_CMD "/bin/sh"
24*de1e4e89SAndroid Build Coastguard Worker
25*de1e4e89SAndroid Build Coastguard Worker static char *argv_default[] = { BPF_DEFAULT_CMD, NULL };
26*de1e4e89SAndroid Build Coastguard Worker
explain(void)27*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
28*de1e4e89SAndroid Build Coastguard Worker {
29*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ... bpf [ import UDS_FILE ] [ run CMD ]\n");
30*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ... bpf [ debug ]\n");
31*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " ... bpf [ graft MAP_FILE ] [ key KEY ]\n");
32*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " `... [ object-file OBJ_FILE ] [ type TYPE ] [ section NAME ] [ verbose ]\n");
33*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, " `... [ object-pinned PROG_FILE ]\n");
34*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\n");
35*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Where UDS_FILE provides the name of a unix domain socket file\n");
36*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "to import eBPF maps and the optional CMD denotes the command\n");
37*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "to be executed (default: \'%s\').\n", BPF_DEFAULT_CMD);
38*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Where MAP_FILE points to a pinned map, OBJ_FILE to an object file\n");
39*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "and PROG_FILE to a pinned program. TYPE can be {cls, act}, where\n");
40*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "\'cls\' is default. KEY is optional and can be inferred from the\n");
41*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "section name, otherwise it needs to be provided.\n");
42*de1e4e89SAndroid Build Coastguard Worker }
43*de1e4e89SAndroid Build Coastguard Worker
bpf_num_env_entries(void)44*de1e4e89SAndroid Build Coastguard Worker static int bpf_num_env_entries(void)
45*de1e4e89SAndroid Build Coastguard Worker {
46*de1e4e89SAndroid Build Coastguard Worker char **envp;
47*de1e4e89SAndroid Build Coastguard Worker int num;
48*de1e4e89SAndroid Build Coastguard Worker
49*de1e4e89SAndroid Build Coastguard Worker for (num = 0, envp = environ; *envp != NULL; envp++)
50*de1e4e89SAndroid Build Coastguard Worker num++;
51*de1e4e89SAndroid Build Coastguard Worker return num;
52*de1e4e89SAndroid Build Coastguard Worker }
53*de1e4e89SAndroid Build Coastguard Worker
parse_bpf(struct exec_util * eu,int argc,char ** argv)54*de1e4e89SAndroid Build Coastguard Worker static int parse_bpf(struct exec_util *eu, int argc, char **argv)
55*de1e4e89SAndroid Build Coastguard Worker {
56*de1e4e89SAndroid Build Coastguard Worker char **argv_run = argv_default, **envp_run, *tmp;
57*de1e4e89SAndroid Build Coastguard Worker int ret, i, env_old, env_num, env_map;
58*de1e4e89SAndroid Build Coastguard Worker const char *bpf_uds_name = NULL;
59*de1e4e89SAndroid Build Coastguard Worker int fds[BPF_SCM_MAX_FDS] = {};
60*de1e4e89SAndroid Build Coastguard Worker struct bpf_map_aux aux = {};
61*de1e4e89SAndroid Build Coastguard Worker
62*de1e4e89SAndroid Build Coastguard Worker if (argc == 0)
63*de1e4e89SAndroid Build Coastguard Worker return 0;
64*de1e4e89SAndroid Build Coastguard Worker
65*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
66*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "run") == 0) {
67*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
68*de1e4e89SAndroid Build Coastguard Worker argv_run = argv;
69*de1e4e89SAndroid Build Coastguard Worker break;
70*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "import") == 0) {
71*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
72*de1e4e89SAndroid Build Coastguard Worker bpf_uds_name = *argv;
73*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "debug") == 0 ||
74*de1e4e89SAndroid Build Coastguard Worker matches(*argv, "dbg") == 0) {
75*de1e4e89SAndroid Build Coastguard Worker if (bpf_trace_pipe())
76*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr,
77*de1e4e89SAndroid Build Coastguard Worker "No trace pipe, tracefs not mounted?\n");
78*de1e4e89SAndroid Build Coastguard Worker return -1;
79*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "graft") == 0) {
80*de1e4e89SAndroid Build Coastguard Worker const char *bpf_map_path;
81*de1e4e89SAndroid Build Coastguard Worker bool has_key = false;
82*de1e4e89SAndroid Build Coastguard Worker uint32_t key;
83*de1e4e89SAndroid Build Coastguard Worker
84*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
85*de1e4e89SAndroid Build Coastguard Worker bpf_map_path = *argv;
86*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
87*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "key") == 0) {
88*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
89*de1e4e89SAndroid Build Coastguard Worker if (get_unsigned(&key, *argv, 0)) {
90*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"key\"\n");
91*de1e4e89SAndroid Build Coastguard Worker return -1;
92*de1e4e89SAndroid Build Coastguard Worker }
93*de1e4e89SAndroid Build Coastguard Worker has_key = true;
94*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
95*de1e4e89SAndroid Build Coastguard Worker }
96*de1e4e89SAndroid Build Coastguard Worker return bpf_graft_map(bpf_map_path, has_key ?
97*de1e4e89SAndroid Build Coastguard Worker &key : NULL, argc, argv);
98*de1e4e89SAndroid Build Coastguard Worker } else {
99*de1e4e89SAndroid Build Coastguard Worker explain();
100*de1e4e89SAndroid Build Coastguard Worker return -1;
101*de1e4e89SAndroid Build Coastguard Worker }
102*de1e4e89SAndroid Build Coastguard Worker
103*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG_FWD();
104*de1e4e89SAndroid Build Coastguard Worker }
105*de1e4e89SAndroid Build Coastguard Worker
106*de1e4e89SAndroid Build Coastguard Worker if (!bpf_uds_name) {
107*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "bpf: No import parameter provided!\n");
108*de1e4e89SAndroid Build Coastguard Worker explain();
109*de1e4e89SAndroid Build Coastguard Worker return -1;
110*de1e4e89SAndroid Build Coastguard Worker }
111*de1e4e89SAndroid Build Coastguard Worker
112*de1e4e89SAndroid Build Coastguard Worker if (argv_run != argv_default && argc == 0) {
113*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "bpf: No run command provided!\n");
114*de1e4e89SAndroid Build Coastguard Worker explain();
115*de1e4e89SAndroid Build Coastguard Worker return -1;
116*de1e4e89SAndroid Build Coastguard Worker }
117*de1e4e89SAndroid Build Coastguard Worker
118*de1e4e89SAndroid Build Coastguard Worker ret = bpf_recv_map_fds(bpf_uds_name, fds, &aux, ARRAY_SIZE(fds));
119*de1e4e89SAndroid Build Coastguard Worker if (ret < 0) {
120*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "bpf: Could not receive fds!\n");
121*de1e4e89SAndroid Build Coastguard Worker return -1;
122*de1e4e89SAndroid Build Coastguard Worker }
123*de1e4e89SAndroid Build Coastguard Worker
124*de1e4e89SAndroid Build Coastguard Worker if (aux.num_ent == 0) {
125*de1e4e89SAndroid Build Coastguard Worker envp_run = environ;
126*de1e4e89SAndroid Build Coastguard Worker goto out;
127*de1e4e89SAndroid Build Coastguard Worker }
128*de1e4e89SAndroid Build Coastguard Worker
129*de1e4e89SAndroid Build Coastguard Worker env_old = bpf_num_env_entries();
130*de1e4e89SAndroid Build Coastguard Worker env_num = env_old + aux.num_ent + 2;
131*de1e4e89SAndroid Build Coastguard Worker env_map = env_old + 1;
132*de1e4e89SAndroid Build Coastguard Worker
133*de1e4e89SAndroid Build Coastguard Worker envp_run = malloc(sizeof(*envp_run) * env_num);
134*de1e4e89SAndroid Build Coastguard Worker if (!envp_run) {
135*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "bpf: No memory left to allocate env!\n");
136*de1e4e89SAndroid Build Coastguard Worker goto err;
137*de1e4e89SAndroid Build Coastguard Worker }
138*de1e4e89SAndroid Build Coastguard Worker
139*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < env_old; i++)
140*de1e4e89SAndroid Build Coastguard Worker envp_run[i] = environ[i];
141*de1e4e89SAndroid Build Coastguard Worker
142*de1e4e89SAndroid Build Coastguard Worker ret = asprintf(&tmp, "BPF_NUM_MAPS=%u", aux.num_ent);
143*de1e4e89SAndroid Build Coastguard Worker if (ret < 0)
144*de1e4e89SAndroid Build Coastguard Worker goto err_free;
145*de1e4e89SAndroid Build Coastguard Worker
146*de1e4e89SAndroid Build Coastguard Worker envp_run[env_old] = tmp;
147*de1e4e89SAndroid Build Coastguard Worker
148*de1e4e89SAndroid Build Coastguard Worker for (i = env_map; i < env_num - 1; i++) {
149*de1e4e89SAndroid Build Coastguard Worker ret = asprintf(&tmp, "BPF_MAP%u=%u",
150*de1e4e89SAndroid Build Coastguard Worker aux.ent[i - env_map].id,
151*de1e4e89SAndroid Build Coastguard Worker fds[i - env_map]);
152*de1e4e89SAndroid Build Coastguard Worker if (ret < 0)
153*de1e4e89SAndroid Build Coastguard Worker goto err_free_env;
154*de1e4e89SAndroid Build Coastguard Worker
155*de1e4e89SAndroid Build Coastguard Worker envp_run[i] = tmp;
156*de1e4e89SAndroid Build Coastguard Worker }
157*de1e4e89SAndroid Build Coastguard Worker
158*de1e4e89SAndroid Build Coastguard Worker envp_run[env_num - 1] = NULL;
159*de1e4e89SAndroid Build Coastguard Worker out:
160*de1e4e89SAndroid Build Coastguard Worker return execvpe(argv_run[0], argv_run, envp_run);
161*de1e4e89SAndroid Build Coastguard Worker
162*de1e4e89SAndroid Build Coastguard Worker err_free_env:
163*de1e4e89SAndroid Build Coastguard Worker for (--i; i >= env_old; i--)
164*de1e4e89SAndroid Build Coastguard Worker free(envp_run[i]);
165*de1e4e89SAndroid Build Coastguard Worker err_free:
166*de1e4e89SAndroid Build Coastguard Worker free(envp_run);
167*de1e4e89SAndroid Build Coastguard Worker err:
168*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < aux.num_ent; i++)
169*de1e4e89SAndroid Build Coastguard Worker close(fds[i]);
170*de1e4e89SAndroid Build Coastguard Worker return -1;
171*de1e4e89SAndroid Build Coastguard Worker }
172*de1e4e89SAndroid Build Coastguard Worker
173*de1e4e89SAndroid Build Coastguard Worker struct exec_util bpf_exec_util = {
174*de1e4e89SAndroid Build Coastguard Worker .id = "bpf",
175*de1e4e89SAndroid Build Coastguard Worker .parse_eopt = parse_bpf,
176*de1e4e89SAndroid Build Coastguard Worker };
177