aboutsummaryrefslogtreecommitdiffstats
path: root/src/fseccomp/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fseccomp/syscall.c')
-rw-r--r--src/fseccomp/syscall.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/fseccomp/syscall.c b/src/fseccomp/syscall.c
new file mode 100644
index 000000000..7c2c4cbb2
--- /dev/null
+++ b/src/fseccomp/syscall.c
@@ -0,0 +1,146 @@
1/*
2 * Copyright (C) 2014-2016 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "fseccomp.h"
21#include <sys/syscall.h>
22
23typedef struct {
24 char *name;
25 int nr;
26} SyscallEntry;
27
28static SyscallEntry syslist[] = {
29//
30// code generated using tools/extract-syscall
31//
32#include "../include/syscall.h"
33//
34// end of generated code
35//
36}; // end of syslist
37
38// return -1 if error, or syscall number
39int syscall_find_name(const char *name) {
40 int i;
41 int elems = sizeof(syslist) / sizeof(syslist[0]);
42 for (i = 0; i < elems; i++) {
43 if (strcmp(name, syslist[i].name) == 0)
44 return syslist[i].nr;
45 }
46
47 return -1;
48}
49
50char *syscall_find_nr(int nr) {
51 int i;
52 int elems = sizeof(syslist) / sizeof(syslist[0]);
53 for (i = 0; i < elems; i++) {
54 if (nr == syslist[i].nr)
55 return syslist[i].name;
56 }
57
58 return "unknown";
59}
60
61void syscall_print(void) {
62 int i;
63 int elems = sizeof(syslist) / sizeof(syslist[0]);
64 for (i = 0; i < elems; i++) {
65 printf("%d\t- %s\n", syslist[i].nr, syslist[i].name);
66 }
67 printf("\n");
68}
69
70// allowed input:
71// - syscall
72// - syscall(error)
73static void syscall_process_name(const char *name, int *syscall_nr, int *error_nr) {
74 assert(name);
75 if (strlen(name) == 0)
76 goto error;
77 *error_nr = -1;
78
79 // syntax check
80 char *str = strdup(name);
81 if (!str)
82 errExit("strdup");
83
84 char *syscall_name = str;
85 char *error_name = strchr(str, ':');
86 if (error_name) {
87 *error_name = '\0';
88 error_name++;
89 }
90 if (strlen(syscall_name) == 0) {
91 free(str);
92 goto error;
93 }
94
95 *syscall_nr = syscall_find_name(syscall_name);
96 if (error_name) {
97 *error_nr = errno_find_name(error_name);
98 if (*error_nr == -1)
99 *syscall_nr = -1;
100 }
101
102 free(str);
103 return;
104
105error:
106 fprintf(stderr, "Error fseccomp: invalid syscall list entry %s\n", name);
107 exit(1);
108}
109
110// return 1 if error, 0 if OK
111int syscall_check_list(const char *slist, void (*callback)(int fd, int syscall, int arg), int fd, int arg) {
112 // don't allow empty lists
113 if (slist == NULL || *slist == '\0') {
114 fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
115 exit(1);
116 }
117
118 // work on a copy of the string
119 char *str = strdup(slist);
120 if (!str)
121 errExit("strdup");
122
123 char *ptr =strtok(str, ",");
124 if (ptr == NULL) {
125 fprintf(stderr, "Error fseccomp: empty syscall lists are not allowed\n");
126 exit(1);
127 }
128
129 while (ptr) {
130 int syscall_nr;
131 int error_nr;
132 syscall_process_name(ptr, &syscall_nr, &error_nr);
133 if (syscall_nr == -1)
134 fprintf(stderr, "Warning fseccomp: syscall %s not found\n", ptr);
135 else if (callback != NULL) {
136 if (error_nr != -1)
137 filter_add_errno(fd, syscall_nr, error_nr);
138 else
139 callback(fd, syscall_nr, arg);
140 }
141 ptr = strtok(NULL, ",");
142 }
143
144 free(str);
145 return 0;
146}