summaryrefslogtreecommitdiff
path: root/src/db.h
blob: 1f67b5dc45f810f5e51d5b4213f34a0b2b9acf92 (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
/**
 * Enhanced Seccomp Filter DB
 *
 * Copyright (c) 2012,2016 Red Hat <pmoore@redhat.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"

/* 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;
	struct db_api_arg *args;
	unsigned int args_cnt;

	struct db_api_rule_list *prev, *next;
};

struct db_arg_chain_tree {
	/* argument number (a0 = 0, a1 = 1, etc.) */
	unsigned int arg;
	/* argument bpf offset */
	unsigned int arg_offset;

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

	/* 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)
#define db_chain_lt(x,y) \
	(((x)->arg < (y)->arg) || \
	 (((x)->arg == (y)->arg) && \
	  (((x)->op < (y)->op) || (((x)->mask & (y)->mask) == (y)->mask))))
#define db_chain_eq(x,y) \
	(((x)->arg == (y)->arg) && \
	 ((x)->op == (y)->op) && ((x)->datum == (y)->datum) && \
	 ((x)->mask == (y)->mask))
#define db_chain_gt(x,y) \
	(((x)->arg > (y)->arg) || \
	 (((x)->arg == (y)->arg) && \
	  (((x)->op > (y)->op) || (((x)->mask & (y)->mask) != (y)->mask))))
#define db_chain_action(x) \
	(((x)->act_t_flg) || ((x)->act_f_flg))
#define db_chain_zombie(x) \
	((x)->nxt_t == NULL && !((x)->act_t_flg) && \
	 (x)->nxt_f == NULL && !((x)->act_f_flg))
#define db_chain_leaf(x) \
	((x)->nxt_t == NULL && (x)->nxt_f == NULL)
#define db_chain_eq_result(x,y) \
	((((x)->nxt_t != NULL && (y)->nxt_t != NULL) || \
	  ((x)->nxt_t == NULL && (y)->nxt_t == NULL)) && \
	 (((x)->nxt_f != NULL && (y)->nxt_f != NULL) || \
	  ((x)->nxt_f == NULL && (y)->nxt_f == NULL)) && \
	 ((x)->act_t_flg == (y)->act_t_flg) && \
	 ((x)->act_f_flg == (y)->act_f_flg) && \
	 (((x)->act_t_flg && (x)->act_t == (y)->act_t) || \
	  (!((x)->act_t_flg))) && \
	 (((x)->act_f_flg && (x)->act_f == (y)->act_f) || \
	  (!((x)->act_f_flg))))

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;
};

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

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

	/* 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;

	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;
};

/**
 * 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)

int db_action_valid(uint32_t action);

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_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);
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_rule_add(struct db_filter *db, const struct db_api_rule_list *rule);

#endif