summaryrefslogtreecommitdiff
path: root/src/db.h
blob: 376cbc33354e33896fe8b8ff7887282a1adbd5a7 (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
/**
 * Enhanced Seccomp Filter DB
 *
 * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
 * Author: Paul Moore <pmoore@redhat.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_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;
};

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

/**
 * 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);
void 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_add(struct db_filter_col *col, struct db_filter *db);
int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token);

struct db_filter *db_init(const struct arch_def *arch);
void db_reset(struct db_filter *db);
void db_release(struct db_filter *db);

int db_syscall_priority(struct db_filter *db,
			unsigned int syscall, uint8_t priority);

int db_rule_add(struct db_filter *db, uint32_t action, unsigned int syscall,
		struct db_api_arg *chain);

#endif