summaryrefslogtreecommitdiff
path: root/src/db.h
blob: 906a857c1f29753ce4994d2eae5e927ec74a2c71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/**
 * Enhanced Seccomp Filter DB
 *
 * Copyright (c) 2012,2016 Red Hat <pmoore@redhat.com>
 * Copyright (c) 2022 Microsoft Corporation <paulmoore@microsoft.com>
 * Author: Paul Moore <paul@paul-moore.com>
 */

/*
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of version 2.1 of the GNU Lesser General Public License as
 * published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, see <http://www.gnu.org/licenses>.
 */

#ifndef _FILTER_DB_H
#define _FILTER_DB_H

#include <inttypes.h>
#include <stdbool.h>

#include <seccomp.h>

#include "arch.h"
#include "gen_bpf.h"

/* XXX - need to provide doxygen comments for the types here */

struct db_api_arg {
	unsigned int arg;
	enum scmp_compare op;
	scmp_datum_t mask;
	scmp_datum_t datum;

	bool valid;
};

struct db_api_rule_list {
	uint32_t action;
	int syscall;
	bool strict;
	struct db_api_arg args[ARG_COUNT_MAX];

	struct db_api_rule_list *prev, *next;
};

struct db_arg_chain_tree {
	/* argument number (a0 = 0, a1 = 1, etc.) */
	unsigned int arg;
	/* true to indicate this is the high 32-bit word of a 64-bit value */
	bool arg_h_flg;
	/* argument bpf offset */
	unsigned int arg_offset;

	/* comparison operator */
	enum scmp_compare op;
	enum scmp_compare op_orig;
	/* syscall argument value */
	uint32_t mask;
	uint32_t datum;
	scmp_datum_t datum_full;

	/* actions */
	bool act_t_flg;
	bool act_f_flg;
	uint32_t act_t;
	uint32_t act_f;

	/* list of nodes on this level */
	struct db_arg_chain_tree *lvl_prv, *lvl_nxt;

	/* next node in the chain */
	struct db_arg_chain_tree *nxt_t;
	struct db_arg_chain_tree *nxt_f;

	unsigned int refcnt;
};
#define ARG_MASK_MAX		((uint32_t)-1)

struct db_sys_list {
	/* native syscall number */
	unsigned int num;

	/* priority - higher is better */
	unsigned int priority;

	/* the argument chain heads */
	struct db_arg_chain_tree *chains;
	unsigned int node_cnt;

	/* action in the case of no argument chains */
	uint32_t action;

	struct db_sys_list *next;
	/* temporary use only by the BPF generator */
	struct db_sys_list *pri_prv, *pri_nxt;

	bool valid;
};

struct db_filter_attr {
	/* action to take if we don't match an explicit allow/deny */
	uint32_t act_default;
	/* action to take if we don't match the architecture */
	uint32_t act_badarch;
	/* NO_NEW_PRIVS related attributes */
	uint32_t nnp_enable;
	/* SECCOMP_FILTER_FLAG_TSYNC related attributes */
	uint32_t tsync_enable;
	/* allow rules with a -1 syscall value */
	uint32_t api_tskip;
	/* SECCOMP_FILTER_FLAG_LOG related attributes */
	uint32_t log_enable;
	/* SPEC_ALLOW related attributes */
	uint32_t spec_allow;
	/* SCMP_FLTATR_CTL_OPTIMIZE related attributes */
	uint32_t optimize;
	/* return the raw system return codes */
	uint32_t api_sysrawrc;
	/* request SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV */
	uint32_t wait_killable_recv;
};

struct db_filter {
	/* target architecture */
	const struct arch_def *arch;

	/* syscall filters, kept as a sorted single-linked list */
	struct db_sys_list *syscalls;
	unsigned int syscall_cnt;

	/* list of rules used to build the filters, kept in order */
	struct db_api_rule_list *rules;
};

struct db_filter_snap {
	/* individual filters */
	struct db_filter **filters;
	unsigned int filter_cnt;
	bool shadow;

	struct db_filter_snap *next;
};

struct db_filter_col {
	/* verification / state */
	int state;

	/* attributes */
	struct db_filter_attr attr;

	/* individual filters */
	int endian;
	struct db_filter **filters;
	unsigned int filter_cnt;

	/* transaction snapshots */
	struct db_filter_snap *snapshots;

	/* userspace notification */
	bool notify_used;

	/* precomputed programs */
	struct bpf_program *prgm_bpf;
};

/**
 * Iterate over each item in the DB list
 * @param iter the iterator
 * @param list the list
 *
 * This macro acts as for()/while() conditional and iterates the following
 * statement for each item in the given list.
 *
 */
#define db_list_foreach(iter,list) \
	for (iter = (list); iter != NULL; iter = iter->next)

struct db_api_rule_list *db_rule_dup(const struct db_api_rule_list *src);

struct db_filter_col *db_col_init(uint32_t def_action);
int db_col_reset(struct db_filter_col *col, uint32_t def_action);
void db_col_release(struct db_filter_col *col);

int db_col_valid(struct db_filter_col *col);

int db_col_action_valid(const struct db_filter_col *col, uint32_t action);

int db_col_merge(struct db_filter_col *col_dst, struct db_filter_col *col_src);

int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token);

int db_col_attr_get(const struct db_filter_col *col,
		    enum scmp_filter_attr attr, uint32_t *value);
uint32_t db_col_attr_read(const struct db_filter_col *col,
			  enum scmp_filter_attr attr);
int db_col_attr_set(struct db_filter_col *col,
		    enum scmp_filter_attr attr, uint32_t value);

int db_col_db_new(struct db_filter_col *col, const struct arch_def *arch);
int db_col_db_add(struct db_filter_col *col, struct db_filter *db);
int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token);

int db_col_rule_add(struct db_filter_col *col,
		    bool strict, uint32_t action, int syscall,
		    unsigned int arg_cnt, const struct scmp_arg_cmp *arg_array);

int db_col_syscall_priority(struct db_filter_col *col,
			    int syscall, uint8_t priority);

int db_col_transaction_start(struct db_filter_col *col);
void db_col_transaction_abort(struct db_filter_col *col);
void db_col_transaction_commit(struct db_filter_col *col);

int db_col_precompute(struct db_filter_col *col);
void db_col_precompute_reset(struct db_filter_col *col);

int db_rule_add(struct db_filter *db, const struct db_api_rule_list *rule);

#endif