Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/file/src/seccomp.c
39478 views
1
/*
2
* Redistribution and use in source and binary forms, with or without
3
* modification, are permitted provided that the following conditions
4
* are met:
5
* 1. Redistributions of source code must retain the above copyright
6
* notice immediately at the beginning of the file, without modification,
7
* this list of conditions, and the following disclaimer.
8
* 2. Redistributions in binary form must reproduce the above copyright
9
* notice, this list of conditions and the following disclaimer in the
10
* documentation and/or other materials provided with the distribution.
11
*
12
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
16
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
* SUCH DAMAGE.
23
*/
24
/*
25
* libseccomp hooks.
26
*/
27
#include "file.h"
28
29
#ifndef lint
30
FILE_RCSID("@(#)$File: seccomp.c,v 1.29 2024/09/29 16:49:25 christos Exp $")
31
#endif /* lint */
32
33
#if HAVE_LIBSECCOMP
34
#include <seccomp.h> /* libseccomp */
35
#include <sys/prctl.h> /* prctl */
36
#include <sys/ioctl.h>
37
#include <sys/socket.h>
38
#include <termios.h>
39
#include <fcntl.h>
40
#include <stdlib.h>
41
#include <errno.h>
42
43
#define DENY_RULE(call) \
44
do \
45
if (seccomp_rule_add (ctx, SCMP_ACT_KILL, SCMP_SYS(call), 0) == -1) \
46
goto out; \
47
while (/*CONSTCOND*/0)
48
#define ALLOW_RULE(call) \
49
do \
50
if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(call), 0) == -1) \
51
goto out; \
52
while (/*CONSTCOND*/0)
53
54
#define ALLOW_IOCTL_RULE(param) \
55
do \
56
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, \
57
SCMP_CMP(1, SCMP_CMP_EQ, (scmp_datum_t)param, \
58
(scmp_datum_t)0)) == -1) \
59
goto out; \
60
while (/*CONSTCOND*/0)
61
62
static scmp_filter_ctx ctx;
63
64
int
65
enable_sandbox(void)
66
{
67
68
// prevent child processes from getting more priv e.g. via setuid,
69
// capabilities, ...
70
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1)
71
return -1;
72
73
#if 0
74
if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1)
75
return -1;
76
#endif
77
78
// initialize the filter
79
ctx = seccomp_init(SCMP_ACT_KILL);
80
if (ctx == NULL)
81
return -1;
82
83
ALLOW_RULE(access);
84
ALLOW_RULE(brk);
85
ALLOW_RULE(close);
86
ALLOW_RULE(dup2);
87
ALLOW_RULE(exit);
88
ALLOW_RULE(exit_group);
89
#ifdef __NR_faccessat
90
ALLOW_RULE(faccessat);
91
#endif
92
ALLOW_RULE(fcntl);
93
ALLOW_RULE(fcntl64);
94
#ifdef __NR_fstat
95
ALLOW_RULE(fstat);
96
#endif
97
ALLOW_RULE(fstat64);
98
#ifdef __NR_fstatat64
99
ALLOW_RULE(fstatat64);
100
#endif
101
ALLOW_RULE(futex);
102
ALLOW_RULE(getdents);
103
#ifdef __NR_getdents64
104
ALLOW_RULE(getdents64);
105
#endif
106
#ifdef FIONREAD
107
// called in src/compress.c under sread
108
ALLOW_IOCTL_RULE(FIONREAD);
109
#endif
110
#ifdef TIOCGWINSZ
111
// musl libc may call ioctl TIOCGWINSZ on stdout
112
ALLOW_IOCTL_RULE(TIOCGWINSZ);
113
#endif
114
#ifdef TCGETS
115
// glibc may call ioctl TCGETS on stdout on physical terminal
116
ALLOW_IOCTL_RULE(TCGETS);
117
#endif
118
ALLOW_RULE(lseek);
119
ALLOW_RULE(_llseek);
120
ALLOW_RULE(lstat);
121
ALLOW_RULE(lstat64);
122
ALLOW_RULE(madvise);
123
ALLOW_RULE(mmap);
124
ALLOW_RULE(mmap2);
125
ALLOW_RULE(mprotect);
126
ALLOW_RULE(mremap);
127
ALLOW_RULE(munmap);
128
#ifdef __NR_newfstatat
129
ALLOW_RULE(newfstatat);
130
#endif
131
ALLOW_RULE(open);
132
ALLOW_RULE(openat);
133
ALLOW_RULE(pread64);
134
ALLOW_RULE(read);
135
ALLOW_RULE(readlink);
136
#ifdef __NR_readlinkat
137
ALLOW_RULE(readlinkat);
138
#endif
139
ALLOW_RULE(rt_sigaction);
140
ALLOW_RULE(rt_sigprocmask);
141
ALLOW_RULE(rt_sigreturn);
142
ALLOW_RULE(select);
143
ALLOW_RULE(stat);
144
ALLOW_RULE(statx);
145
ALLOW_RULE(stat64);
146
ALLOW_RULE(sysinfo);
147
ALLOW_RULE(umask); // Used in file_pipe2file()
148
ALLOW_RULE(getpid); // Used by glibc in file_pipe2file()
149
ALLOW_RULE(getrandom); // Used by glibc in file_pipe2file()
150
ALLOW_RULE(unlink);
151
ALLOW_RULE(utimes);
152
ALLOW_RULE(write);
153
ALLOW_RULE(writev);
154
155
156
#if 0
157
// needed by valgrind
158
ALLOW_RULE(gettid);
159
ALLOW_RULE(rt_sigtimedwait);
160
#endif
161
162
#if 0
163
/* special restrictions for socket, only allow AF_UNIX/AF_LOCAL */
164
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
165
SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) == -1)
166
goto out;
167
168
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
169
SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) == -1)
170
goto out;
171
172
173
/* special restrictions for open, prevent opening files for writing */
174
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1,
175
SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) == -1)
176
goto out;
177
178
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1,
179
SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) == -1)
180
goto out;
181
182
if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), 1,
183
SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) == -1)
184
goto out;
185
186
187
/* allow stderr */
188
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
189
SCMP_CMP(0, SCMP_CMP_EQ, 2)) == -1)
190
goto out;
191
#endif
192
193
#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
194
/* allow glibc to name malloc areas */
195
if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 2,
196
SCMP_CMP32(0, SCMP_CMP_EQ, PR_SET_VMA),
197
SCMP_CMP64(1, SCMP_CMP_EQ, PR_SET_VMA_ANON_NAME)) == -1)
198
goto out;
199
#endif
200
201
// applying filter...
202
if (seccomp_load(ctx) == -1)
203
goto out;
204
// free ctx after the filter has been loaded into the kernel
205
seccomp_release(ctx);
206
return 0;
207
208
out:
209
// something went wrong
210
seccomp_release(ctx);
211
return -1;
212
}
213
#endif
214
215