Bundle libseccomp 2.3.1
[linux-seccomp.git] / libseccomp / src / api.c
CommitLineData
8befd5cc
MG
1/**
2 * Seccomp Library API
3 *
4 * Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com>
5 * Author: Paul Moore <paul@paul-moore.com>
6 */
7
8/*
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of version 2.1 of the GNU Lesser General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This library is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, see <http://www.gnu.org/licenses>.
20 */
21
22#include <endian.h>
23#include <errno.h>
24#include <inttypes.h>
25#include <unistd.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdbool.h>
30
31#include <seccomp.h>
32
33#include "arch.h"
34#include "db.h"
35#include "gen_pfc.h"
36#include "gen_bpf.h"
37#include "system.h"
38
39#define API __attribute__((visibility("default")))
40
41const struct scmp_version library_version = {
42 .major = SCMP_VER_MAJOR,
43 .minor = SCMP_VER_MINOR,
44 .micro = SCMP_VER_MICRO,
45};
46
47/**
48 * Validate a filter context
49 * @param ctx the filter context
50 *
51 * Attempt to validate the provided filter context. Returns zero if the
52 * context is valid, negative values on failure.
53 *
54 */
55static int _ctx_valid(const scmp_filter_ctx *ctx)
56{
57 return db_col_valid((struct db_filter_col *)ctx);
58}
59
60/**
61 * Validate a syscall number
62 * @param syscall the syscall number
63 *
64 * Attempt to perform basic syscall number validation. Returns zero of the
65 * syscall appears valid, negative values on failure.
66 *
67 */
68static int _syscall_valid(int syscall)
69{
70 if (syscall <= -1 && syscall >= -99)
71 return -EINVAL;
72 return 0;
73}
74
75/* NOTE - function header comment in include/seccomp.h */
76API const struct scmp_version *seccomp_version(void)
77{
78 return &library_version;
79}
80
81/* NOTE - function header comment in include/seccomp.h */
82API scmp_filter_ctx seccomp_init(uint32_t def_action)
83{
84 if (db_action_valid(def_action) < 0)
85 return NULL;
86
87 return db_col_init(def_action);
88}
89
90/* NOTE - function header comment in include/seccomp.h */
91API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)
92{
93 struct db_filter_col *col = (struct db_filter_col *)ctx;
94
95 if (ctx == NULL || db_action_valid(def_action) < 0)
96 return -EINVAL;
97
98 return db_col_reset(col, def_action);
99}
100
101/* NOTE - function header comment in include/seccomp.h */
102API void seccomp_release(scmp_filter_ctx ctx)
103{
104 db_col_release((struct db_filter_col *)ctx);
105}
106
107/* NOTE - function header comment in include/seccomp.h */
108API int seccomp_merge(scmp_filter_ctx ctx_dst,
109 scmp_filter_ctx ctx_src)
110{
111 struct db_filter_col *col_dst = (struct db_filter_col *)ctx_dst;
112 struct db_filter_col *col_src = (struct db_filter_col *)ctx_src;
113
114 if (db_col_valid(col_dst) || db_col_valid(col_src))
115 return -EINVAL;
116
117 /* NOTE: only the default action, NNP, and TSYNC settings must match */
118 if ((col_dst->attr.act_default != col_src->attr.act_default) ||
119 (col_dst->attr.nnp_enable != col_src->attr.nnp_enable) ||
120 (col_dst->attr.tsync_enable != col_src->attr.tsync_enable))
121 return -EINVAL;
122
123 return db_col_merge(col_dst, col_src);
124}
125
126/* NOTE - function header comment in include/seccomp.h */
127API uint32_t seccomp_arch_resolve_name(const char *arch_name)
128{
129 const struct arch_def *arch;
130
131 if (arch_name == NULL)
132 return 0;
133
134 arch = arch_def_lookup_name(arch_name);
135 if (arch == NULL)
136 return 0;
137
138 return arch->token;
139}
140
141/* NOTE - function header comment in include/seccomp.h */
142API uint32_t seccomp_arch_native(void)
143{
144 return arch_def_native->token;
145}
146
147/* NOTE - function header comment in include/seccomp.h */
148API int seccomp_arch_exist(const scmp_filter_ctx ctx,
149 uint32_t arch_token)
150{
151 struct db_filter_col *col = (struct db_filter_col *)ctx;
152
153 if (arch_token == 0)
154 arch_token = arch_def_native->token;
155
156 if (arch_valid(arch_token))
157 return -EINVAL;
158
159 return (db_col_arch_exist(col, arch_token) ? 0 : -EEXIST);
160}
161
162/* NOTE - function header comment in include/seccomp.h */
163API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
164{
165 const struct arch_def *arch;
166 struct db_filter_col *col = (struct db_filter_col *)ctx;
167
168 if (arch_token == 0)
169 arch_token = arch_def_native->token;
170
171 if (arch_valid(arch_token))
172 return -EINVAL;
173 if (db_col_arch_exist(col, arch_token))
174 return -EEXIST;
175
176 arch = arch_def_lookup(arch_token);
177 if (arch == NULL)
178 return -EFAULT;
179 return db_col_db_new(col, arch);
180}
181
182/* NOTE - function header comment in include/seccomp.h */
183API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
184{
185 struct db_filter_col *col = (struct db_filter_col *)ctx;
186
187 if (arch_token == 0)
188 arch_token = arch_def_native->token;
189
190 if (arch_valid(arch_token))
191 return -EINVAL;
192 if (db_col_arch_exist(col, arch_token) != -EEXIST)
193 return -EEXIST;
194
195 return db_col_db_remove(col, arch_token);
196}
197
198/* NOTE - function header comment in include/seccomp.h */
199API int seccomp_load(const scmp_filter_ctx ctx)
200{
201 struct db_filter_col *col;
202
203 if (_ctx_valid(ctx))
204 return -EINVAL;
205 col = (struct db_filter_col *)ctx;
206
207 return sys_filter_load(col);
208}
209
210/* NOTE - function header comment in include/seccomp.h */
211API int seccomp_attr_get(const scmp_filter_ctx ctx,
212 enum scmp_filter_attr attr, uint32_t *value)
213{
214 if (_ctx_valid(ctx))
215 return -EINVAL;
216
217 return db_col_attr_get((const struct db_filter_col *)ctx, attr, value);
218}
219
220/* NOTE - function header comment in include/seccomp.h */
221API int seccomp_attr_set(scmp_filter_ctx ctx,
222 enum scmp_filter_attr attr, uint32_t value)
223{
224 if (_ctx_valid(ctx))
225 return -EINVAL;
226
227 return db_col_attr_set((struct db_filter_col *)ctx, attr, value);
228}
229
230/* NOTE - function header comment in include/seccomp.h */
231API char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num)
232{
233 const struct arch_def *arch;
234 const char *name;
235
236 if (arch_token == 0)
237 arch_token = arch_def_native->token;
238 if (arch_valid(arch_token))
239 return NULL;
240 arch = arch_def_lookup(arch_token);
241 if (arch == NULL)
242 return NULL;
243
244 name = arch_syscall_resolve_num(arch, num);
245 if (name == NULL)
246 return NULL;
247
248 return strdup(name);
249}
250
251/* NOTE - function header comment in include/seccomp.h */
252API int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)
253{
254 const struct arch_def *arch;
255
256 if (name == NULL)
257 return __NR_SCMP_ERROR;
258
259 if (arch_token == 0)
260 arch_token = arch_def_native->token;
261 if (arch_valid(arch_token))
262 return __NR_SCMP_ERROR;
263 arch = arch_def_lookup(arch_token);
264 if (arch == NULL)
265 return __NR_SCMP_ERROR;
266
267 return arch_syscall_resolve_name(arch, name);
268}
269
270/* NOTE - function header comment in include/seccomp.h */
271API int seccomp_syscall_resolve_name_rewrite(uint32_t arch_token,
272 const char *name)
273{
274 int rc;
275 int syscall;
276 const struct arch_def *arch;
277
278 if (name == NULL)
279 return __NR_SCMP_ERROR;
280
281 if (arch_token == 0)
282 arch_token = arch_def_native->token;
283 if (arch_valid(arch_token))
284 return __NR_SCMP_ERROR;
285 arch = arch_def_lookup(arch_token);
286 if (arch == NULL)
287 return __NR_SCMP_ERROR;
288
289 syscall = arch_syscall_resolve_name(arch, name);
290 if (syscall == __NR_SCMP_ERROR)
291 return __NR_SCMP_ERROR;
292 rc = arch_syscall_rewrite(arch, &syscall);
293 if (rc == -EDOM)
294 /* if we can't rewrite the syscall, just pass it through */
295 return syscall;
296 else if (rc < 0)
297 return __NR_SCMP_ERROR;
298
299 return syscall;
300}
301
302/* NOTE - function header comment in include/seccomp.h */
303API int seccomp_syscall_resolve_name(const char *name)
304{
305 return seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, name);
306}
307
308/* NOTE - function header comment in include/seccomp.h */
309API int seccomp_syscall_priority(scmp_filter_ctx ctx,
310 int syscall, uint8_t priority)
311{
312 struct db_filter_col *col = (struct db_filter_col *)ctx;
313
314 if (db_col_valid(col) || _syscall_valid(syscall))
315 return -EINVAL;
316
317 return db_col_syscall_priority(col, syscall, priority);
318}
319
320/* NOTE - function header comment in include/seccomp.h */
321API int seccomp_rule_add_array(scmp_filter_ctx ctx,
322 uint32_t action, int syscall,
323 unsigned int arg_cnt,
324 const struct scmp_arg_cmp *arg_array)
325{
326 int rc;
327 struct db_filter_col *col = (struct db_filter_col *)ctx;
328
329 if (arg_cnt > ARG_COUNT_MAX)
330 return -EINVAL;
331 if (arg_cnt > 0 && arg_array == NULL)
332 return -EINVAL;
333
334 if (db_col_valid(col) || _syscall_valid(syscall))
335 return -EINVAL;
336
337 rc = db_action_valid(action);
338 if (rc < 0)
339 return rc;
340 if (action == col->attr.act_default)
341 return -EPERM;
342
343 return db_col_rule_add(col, 0, action, syscall, arg_cnt, arg_array);
344}
345
346/* NOTE - function header comment in include/seccomp.h */
347API int seccomp_rule_add(scmp_filter_ctx ctx,
348 uint32_t action, int syscall,
349 unsigned int arg_cnt, ...)
350{
351 int rc;
352 int iter;
353 struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
354 va_list arg_list;
355
356 /* arg_cnt is unsigned, so no need to check the lower bound */
357 if (arg_cnt > ARG_COUNT_MAX)
358 return -EINVAL;
359
360 va_start(arg_list, arg_cnt);
361 for (iter = 0; iter < arg_cnt; ++iter)
362 arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
363 rc = seccomp_rule_add_array(ctx, action, syscall, arg_cnt, arg_array);
364 va_end(arg_list);
365
366 return rc;
367}
368
369/* NOTE - function header comment in include/seccomp.h */
370API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
371 uint32_t action, int syscall,
372 unsigned int arg_cnt,
373 const struct scmp_arg_cmp *arg_array)
374{
375 int rc;
376 struct db_filter_col *col = (struct db_filter_col *)ctx;
377
378 if (arg_cnt > ARG_COUNT_MAX)
379 return -EINVAL;
380 if (arg_cnt > 0 && arg_array == NULL)
381 return -EINVAL;
382
383 if (db_col_valid(col) || _syscall_valid(syscall))
384 return -EINVAL;
385
386 rc = db_action_valid(action);
387 if (rc < 0)
388 return rc;
389 if (action == col->attr.act_default)
390 return -EPERM;
391
392 if (col->filter_cnt > 1)
393 return -EOPNOTSUPP;
394
395 return db_col_rule_add(col, 1, action, syscall, arg_cnt, arg_array);
396}
397
398/* NOTE - function header comment in include/seccomp.h */
399API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
400 uint32_t action, int syscall,
401 unsigned int arg_cnt, ...)
402{
403 int rc;
404 int iter;
405 struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
406 va_list arg_list;
407
408 /* arg_cnt is unsigned, so no need to check the lower bound */
409 if (arg_cnt > ARG_COUNT_MAX)
410 return -EINVAL;
411
412 va_start(arg_list, arg_cnt);
413 for (iter = 0; iter < arg_cnt; ++iter)
414 arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
415 rc = seccomp_rule_add_exact_array(ctx,
416 action, syscall, arg_cnt, arg_array);
417 va_end(arg_list);
418
419 return rc;
420}
421
422/* NOTE - function header comment in include/seccomp.h */
423API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
424{
425 if (_ctx_valid(ctx))
426 return -EINVAL;
427
428 return gen_pfc_generate((struct db_filter_col *)ctx, fd);
429}
430
431/* NOTE - function header comment in include/seccomp.h */
432API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
433{
434 int rc;
435 struct bpf_program *program;
436
437 if (_ctx_valid(ctx))
438 return -EINVAL;
439
440 program = gen_bpf_generate((struct db_filter_col *)ctx);
441 if (program == NULL)
442 return -ENOMEM;
443 rc = write(fd, program->blks, BPF_PGM_SIZE(program));
444 gen_bpf_release(program);
445 if (rc < 0)
446 return -errno;
447
448 return 0;
449}
This page took 0.032272 seconds and 4 git commands to generate.