xref: /aosp_15_r20/external/minijail/bpf.h (revision 4b9c6d91573e8b3a96609339b46361b5476dd0f9)
1*4b9c6d91SCole Faust /* bpf.h
2*4b9c6d91SCole Faust  * Copyright 2012 The ChromiumOS Authors
3*4b9c6d91SCole Faust  * Use of this source code is governed by a BSD-style license that can be
4*4b9c6d91SCole Faust  * found in the LICENSE file.
5*4b9c6d91SCole Faust  *
6*4b9c6d91SCole Faust  * Berkeley Packet Filter functions.
7*4b9c6d91SCole Faust  */
8*4b9c6d91SCole Faust 
9*4b9c6d91SCole Faust #ifndef BPF_H
10*4b9c6d91SCole Faust #define BPF_H
11*4b9c6d91SCole Faust 
12*4b9c6d91SCole Faust #include <asm/bitsperlong.h>   /* for __BITS_PER_LONG */
13*4b9c6d91SCole Faust #include <endian.h>
14*4b9c6d91SCole Faust #include <linux/audit.h>
15*4b9c6d91SCole Faust #include <linux/filter.h>
16*4b9c6d91SCole Faust #include <stddef.h>
17*4b9c6d91SCole Faust #include <sys/user.h>
18*4b9c6d91SCole Faust 
19*4b9c6d91SCole Faust #ifdef __cplusplus
20*4b9c6d91SCole Faust extern "C" {
21*4b9c6d91SCole Faust #endif
22*4b9c6d91SCole Faust 
23*4b9c6d91SCole Faust #include "arch.h"
24*4b9c6d91SCole Faust 
25*4b9c6d91SCole Faust #if __BITS_PER_LONG == 32 || defined(__ILP32__)
26*4b9c6d91SCole Faust #define BITS32
27*4b9c6d91SCole Faust #elif __BITS_PER_LONG == 64
28*4b9c6d91SCole Faust #define BITS64
29*4b9c6d91SCole Faust #endif
30*4b9c6d91SCole Faust 
31*4b9c6d91SCole Faust /* Constants for comparison operators. */
32*4b9c6d91SCole Faust #define MIN_OPERATOR 128
33*4b9c6d91SCole Faust enum {
34*4b9c6d91SCole Faust 	EQ = MIN_OPERATOR,
35*4b9c6d91SCole Faust 	NE,
36*4b9c6d91SCole Faust 	LT,
37*4b9c6d91SCole Faust 	LE,
38*4b9c6d91SCole Faust 	GT,
39*4b9c6d91SCole Faust 	GE,
40*4b9c6d91SCole Faust 	SET,
41*4b9c6d91SCole Faust 	IN
42*4b9c6d91SCole Faust };
43*4b9c6d91SCole Faust 
44*4b9c6d91SCole Faust /*
45*4b9c6d91SCole Faust  * BPF return values and data structures,
46*4b9c6d91SCole Faust  * since they're not yet in the kernel.
47*4b9c6d91SCole Faust  * TODO(crbug.com/1147037): Replace this with an #include.
48*4b9c6d91SCole Faust  */
49*4b9c6d91SCole Faust 
50*4b9c6d91SCole Faust #define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the entire process */
51*4b9c6d91SCole Faust #define SECCOMP_RET_KILL_THREAD	 0x00000000U /* kill the thread */
52*4b9c6d91SCole Faust #define SECCOMP_RET_KILL	 SECCOMP_RET_KILL_THREAD
53*4b9c6d91SCole Faust #define SECCOMP_RET_TRAP	 0x00030000U /* return SIGSYS */
54*4b9c6d91SCole Faust #define SECCOMP_RET_ERRNO	 0x00050000U /* return -1 and set errno */
55*4b9c6d91SCole Faust #define SECCOMP_RET_LOG		 0x7ffc0000U /* allow after logging */
56*4b9c6d91SCole Faust #define SECCOMP_RET_ALLOW	 0x7fff0000U /* allow */
57*4b9c6d91SCole Faust 
58*4b9c6d91SCole Faust #define SECCOMP_RET_DATA	 0x0000ffffU /* mask for return value */
59*4b9c6d91SCole Faust 
60*4b9c6d91SCole Faust struct seccomp_data {
61*4b9c6d91SCole Faust 	int nr;
62*4b9c6d91SCole Faust 	__u32 arch;
63*4b9c6d91SCole Faust 	__u64 instruction_pointer;
64*4b9c6d91SCole Faust 	__u64 args[6];
65*4b9c6d91SCole Faust };
66*4b9c6d91SCole Faust 
67*4b9c6d91SCole Faust #define syscall_nr (offsetof(struct seccomp_data, nr))
68*4b9c6d91SCole Faust #define arch_nr (offsetof(struct seccomp_data, arch))
69*4b9c6d91SCole Faust 
70*4b9c6d91SCole Faust /* Size-dependent defines. */
71*4b9c6d91SCole Faust #if defined(BITS32)
72*4b9c6d91SCole Faust /*
73*4b9c6d91SCole Faust  * On 32 bits, comparisons take 2 instructions: 1 for loading the argument,
74*4b9c6d91SCole Faust  * 1 for the actual comparison.
75*4b9c6d91SCole Faust  */
76*4b9c6d91SCole Faust #define BPF_LOAD_ARG_LEN		1U
77*4b9c6d91SCole Faust #define BPF_COMP_LEN			1U
78*4b9c6d91SCole Faust #define BPF_SHORT_GT_GE_COMP_LEN	1U
79*4b9c6d91SCole Faust #define BPF_GT_GE_COMP_LEN		1U
80*4b9c6d91SCole Faust #define BPF_ARG_COMP_LEN (BPF_LOAD_ARG_LEN + BPF_COMP_LEN)
81*4b9c6d91SCole Faust #define BPF_ARG_SHORT_GT_GE_COMP_LEN (BPF_LOAD_ARG_LEN + BPF_SHORT_GT_GE_COMP_LEN)
82*4b9c6d91SCole Faust #define BPF_ARG_GT_GE_COMP_LEN (BPF_LOAD_ARG_LEN + BPF_GT_GE_COMP_LEN)
83*4b9c6d91SCole Faust 
84*4b9c6d91SCole Faust #define bpf_comp_jeq bpf_comp_jeq32
85*4b9c6d91SCole Faust #define bpf_comp_jgt bpf_comp_jgt32
86*4b9c6d91SCole Faust #define bpf_comp_jge bpf_comp_jge32
87*4b9c6d91SCole Faust #define bpf_comp_jset bpf_comp_jset32
88*4b9c6d91SCole Faust 
89*4b9c6d91SCole Faust #define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
90*4b9c6d91SCole Faust 
91*4b9c6d91SCole Faust #elif defined(BITS64)
92*4b9c6d91SCole Faust /*
93*4b9c6d91SCole Faust  * On 64 bits, comparisons take 7-8 instructions: 4 for loading the argument,
94*4b9c6d91SCole Faust  * and 3-4 for the actual comparison.
95*4b9c6d91SCole Faust  */
96*4b9c6d91SCole Faust #define BPF_LOAD_ARG_LEN		4U
97*4b9c6d91SCole Faust #define BPF_COMP_LEN			3U
98*4b9c6d91SCole Faust #define BPF_SHORT_GT_GE_COMP_LEN	3U
99*4b9c6d91SCole Faust #define BPF_GT_GE_COMP_LEN		4U
100*4b9c6d91SCole Faust #define BPF_ARG_COMP_LEN (BPF_LOAD_ARG_LEN + BPF_COMP_LEN)
101*4b9c6d91SCole Faust #define BPF_ARG_SHORT_GT_GE_COMP_LEN (BPF_LOAD_ARG_LEN + BPF_SHORT_GT_GE_COMP_LEN)
102*4b9c6d91SCole Faust #define BPF_ARG_GT_GE_COMP_LEN (BPF_LOAD_ARG_LEN + BPF_GT_GE_COMP_LEN)
103*4b9c6d91SCole Faust 
104*4b9c6d91SCole Faust #define bpf_comp_jeq bpf_comp_jeq64
105*4b9c6d91SCole Faust #define bpf_comp_jgt bpf_comp_jgt64
106*4b9c6d91SCole Faust #define bpf_comp_jge bpf_comp_jge64
107*4b9c6d91SCole Faust #define bpf_comp_jset bpf_comp_jset64
108*4b9c6d91SCole Faust 
109*4b9c6d91SCole Faust /* Ensure that we load the logically correct offset. */
110*4b9c6d91SCole Faust #if defined(__LITTLE_ENDIAN__) || __BYTE_ORDER == __LITTLE_ENDIAN
111*4b9c6d91SCole Faust #define LO_ARG(idx) offsetof(struct seccomp_data, args[(idx)])
112*4b9c6d91SCole Faust #define HI_ARG(idx) offsetof(struct seccomp_data, args[(idx)]) + sizeof(__u32)
113*4b9c6d91SCole Faust #else
114*4b9c6d91SCole Faust #error "Unsupported endianness"
115*4b9c6d91SCole Faust #endif
116*4b9c6d91SCole Faust 
117*4b9c6d91SCole Faust #else
118*4b9c6d91SCole Faust #error "Unknown bit width"
119*4b9c6d91SCole Faust 
120*4b9c6d91SCole Faust #endif
121*4b9c6d91SCole Faust 
122*4b9c6d91SCole Faust /* Common jump targets. */
123*4b9c6d91SCole Faust #define NEXT 0
124*4b9c6d91SCole Faust #define SKIP 1
125*4b9c6d91SCole Faust #define SKIPN(_n) (_n)
126*4b9c6d91SCole Faust 
127*4b9c6d91SCole Faust /* Support for labels in BPF programs. */
128*4b9c6d91SCole Faust #define JUMP_JT 0xff
129*4b9c6d91SCole Faust #define JUMP_JF 0xff
130*4b9c6d91SCole Faust #define LABEL_JT 0xfe
131*4b9c6d91SCole Faust #define LABEL_JF 0xfe
132*4b9c6d91SCole Faust 
133*4b9c6d91SCole Faust #define MAX_BPF_LABEL_LEN 32
134*4b9c6d91SCole Faust 
135*4b9c6d91SCole Faust #define BPF_LABELS_MAX 512U	/* Each syscall could have an argument block. */
136*4b9c6d91SCole Faust struct bpf_labels {
137*4b9c6d91SCole Faust 	size_t count;
138*4b9c6d91SCole Faust 	struct __bpf_label {
139*4b9c6d91SCole Faust 		const char *label;
140*4b9c6d91SCole Faust 		unsigned int location;
141*4b9c6d91SCole Faust 	} labels[BPF_LABELS_MAX];
142*4b9c6d91SCole Faust };
143*4b9c6d91SCole Faust 
144*4b9c6d91SCole Faust /* BPF instruction manipulation functions and macros. */
set_bpf_instr(struct sock_filter * instr,unsigned short code,unsigned int k,unsigned char jt,unsigned char jf)145*4b9c6d91SCole Faust static inline size_t set_bpf_instr(struct sock_filter *instr,
146*4b9c6d91SCole Faust 				   unsigned short code, unsigned int k,
147*4b9c6d91SCole Faust 				   unsigned char jt, unsigned char jf)
148*4b9c6d91SCole Faust {
149*4b9c6d91SCole Faust 	instr->code = code;
150*4b9c6d91SCole Faust 	instr->k = k;
151*4b9c6d91SCole Faust 	instr->jt = jt;
152*4b9c6d91SCole Faust 	instr->jf = jf;
153*4b9c6d91SCole Faust 	return 1U;
154*4b9c6d91SCole Faust }
155*4b9c6d91SCole Faust 
156*4b9c6d91SCole Faust #define set_bpf_stmt(_block, _code, _k) \
157*4b9c6d91SCole Faust 	set_bpf_instr((_block), (_code), (_k), 0, 0)
158*4b9c6d91SCole Faust 
159*4b9c6d91SCole Faust #define set_bpf_jump(_block, _code, _k, _jt, _jf) \
160*4b9c6d91SCole Faust 	set_bpf_instr((_block), (_code), (_k), (_jt), (_jf))
161*4b9c6d91SCole Faust 
162*4b9c6d91SCole Faust #define set_bpf_lbl(_block, _lbl_id) \
163*4b9c6d91SCole Faust 	set_bpf_jump((_block), BPF_JMP+BPF_JA, (_lbl_id), \
164*4b9c6d91SCole Faust 			LABEL_JT, LABEL_JF)
165*4b9c6d91SCole Faust 
166*4b9c6d91SCole Faust #define set_bpf_jump_lbl(_block, _lbl_id) \
167*4b9c6d91SCole Faust 	set_bpf_jump((_block), BPF_JMP+BPF_JA, (_lbl_id), \
168*4b9c6d91SCole Faust 			JUMP_JT, JUMP_JF)
169*4b9c6d91SCole Faust 
170*4b9c6d91SCole Faust #define set_bpf_ret_kill(_block) \
171*4b9c6d91SCole Faust 	set_bpf_stmt((_block), BPF_RET+BPF_K, SECCOMP_RET_KILL)
172*4b9c6d91SCole Faust 
173*4b9c6d91SCole Faust #define set_bpf_ret_kill_process(_block) \
174*4b9c6d91SCole Faust 	set_bpf_stmt((_block), BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS)
175*4b9c6d91SCole Faust 
176*4b9c6d91SCole Faust #define set_bpf_ret_trap(_block) \
177*4b9c6d91SCole Faust 	set_bpf_stmt((_block), BPF_RET+BPF_K, SECCOMP_RET_TRAP)
178*4b9c6d91SCole Faust 
179*4b9c6d91SCole Faust #define set_bpf_ret_errno(_block, _errno) \
180*4b9c6d91SCole Faust 	set_bpf_stmt((_block), BPF_RET+BPF_K, \
181*4b9c6d91SCole Faust 		SECCOMP_RET_ERRNO | ((_errno) & SECCOMP_RET_DATA))
182*4b9c6d91SCole Faust 
183*4b9c6d91SCole Faust #define set_bpf_ret_log(_block) \
184*4b9c6d91SCole Faust 	set_bpf_stmt((_block), BPF_RET+BPF_K, SECCOMP_RET_LOG)
185*4b9c6d91SCole Faust 
186*4b9c6d91SCole Faust #define set_bpf_ret_allow(_block) \
187*4b9c6d91SCole Faust 	set_bpf_stmt((_block), BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
188*4b9c6d91SCole Faust 
189*4b9c6d91SCole Faust #define bpf_load_syscall_nr(_filter) \
190*4b9c6d91SCole Faust 	set_bpf_stmt((_filter), BPF_LD+BPF_W+BPF_ABS, syscall_nr)
191*4b9c6d91SCole Faust 
192*4b9c6d91SCole Faust /* BPF label functions. */
193*4b9c6d91SCole Faust int bpf_resolve_jumps(struct bpf_labels *labels,
194*4b9c6d91SCole Faust 		struct sock_filter *filter, size_t count);
195*4b9c6d91SCole Faust int bpf_label_id(struct bpf_labels *labels, const char *label);
196*4b9c6d91SCole Faust void free_label_strings(struct bpf_labels *labels);
197*4b9c6d91SCole Faust 
198*4b9c6d91SCole Faust /* BPF helper functions. */
199*4b9c6d91SCole Faust size_t bpf_load_arg(struct sock_filter *filter, int argidx);
200*4b9c6d91SCole Faust size_t bpf_comp_jeq(struct sock_filter *filter, unsigned long c,
201*4b9c6d91SCole Faust 		    unsigned char jt, unsigned char jf);
202*4b9c6d91SCole Faust size_t bpf_comp_jgt(struct sock_filter *filter, unsigned long c,
203*4b9c6d91SCole Faust 		    unsigned char jt, unsigned char jf);
204*4b9c6d91SCole Faust size_t bpf_comp_jge(struct sock_filter *filter, unsigned long c,
205*4b9c6d91SCole Faust 		    unsigned char jt, unsigned char jf);
206*4b9c6d91SCole Faust size_t bpf_comp_jset(struct sock_filter *filter, unsigned long mask,
207*4b9c6d91SCole Faust 		     unsigned char jt, unsigned char jf);
208*4b9c6d91SCole Faust size_t bpf_comp_jin(struct sock_filter *filter, unsigned long mask,
209*4b9c6d91SCole Faust 		    unsigned char jt, unsigned char jf);
210*4b9c6d91SCole Faust 
211*4b9c6d91SCole Faust /* Functions called by syscall_filter.c */
212*4b9c6d91SCole Faust #define ARCH_VALIDATION_LEN 3U
213*4b9c6d91SCole Faust #define ALLOW_SYSCALL_LEN 2U
214*4b9c6d91SCole Faust 
215*4b9c6d91SCole Faust size_t bpf_arg_comp(struct sock_filter **pfilter,
216*4b9c6d91SCole Faust 		int op, int argidx, unsigned long c, unsigned int label_id);
217*4b9c6d91SCole Faust size_t bpf_validate_arch(struct sock_filter *filter);
218*4b9c6d91SCole Faust size_t bpf_allow_syscall(struct sock_filter *filter, int nr);
219*4b9c6d91SCole Faust size_t bpf_allow_syscall_args(struct sock_filter *filter,
220*4b9c6d91SCole Faust 		int nr, unsigned int id);
221*4b9c6d91SCole Faust 
222*4b9c6d91SCole Faust #ifdef __cplusplus
223*4b9c6d91SCole Faust }; /* extern "C" */
224*4b9c6d91SCole Faust #endif
225*4b9c6d91SCole Faust 
226*4b9c6d91SCole Faust #endif /* BPF_H */
227