1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2013, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Code to enable sandboxing.
20 #if defined(HAVE_SECCOMP_H) && defined(__linux__)
21 #define USE_LIBSECCOMP
24 #define DEBUGGING_CLOSE
26 #if defined(USE_LIBSECCOMP)
28 #include <sys/syscall.h>
33 /** Variable used for storing all syscall numbers that will be allowed with the
34 * stage 1 general Tor sandbox.
36 static int general_filter
[] = {
39 SCMP_SYS(clock_gettime
),
42 SCMP_SYS(epoll_create
),
48 /* Older libseccomp versions don't define PNR entries for all of these,
49 * so we need to ifdef them here.*/
72 SCMP_SYS(gettimeofday
),
96 SCMP_SYS(rt_sigaction
),
97 SCMP_SYS(rt_sigprocmask
),
98 SCMP_SYS(rt_sigreturn
),
102 SCMP_SYS(set_robust_list
),
103 SCMP_SYS(set_thread_area
),
104 SCMP_SYS(set_tid_address
),
112 SCMP_SYS(exit_group
),
119 SCMP_SYS(getsockname
),
120 SCMP_SYS(getsockopt
),
123 /* This is a kludge; It's necessary on 64-bit with libseccomp 1.0.0; I
124 * don't know if other 64-bit or other versions require it. */
132 SCMP_SYS(setsockopt
),
134 SCMP_SYS(socketpair
),
136 // TODO: remove when accept4 is fixed
137 #ifdef __NR_socketcall
138 SCMP_SYS(socketcall
),
146 * Function responsible for setting up and enabling a global syscall filter.
147 * The function is a prototype developed for stage 1 of sandboxing Tor.
148 * Returns 0 on success.
151 install_glob_syscall_filter(void)
153 int rc
= 0, i
, filter_size
;
156 ctx
= seccomp_init(SCMP_ACT_TRAP
);
158 log_err(LD_BUG
,"(Sandbox) failed to initialise libseccomp context");
163 if (general_filter
!= NULL
) {
164 filter_size
= sizeof(general_filter
) / sizeof(general_filter
[0]);
169 // add general filters
170 for (i
= 0; i
< filter_size
; i
++) {
171 rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, general_filter
[i
], 0);
173 log_err(LD_BUG
,"(Sandbox) failed to add syscall index %d, "
174 "received libseccomp error %d", i
, rc
);
179 rc
= seccomp_load(ctx
);
182 seccomp_release(ctx
);
183 return (rc
< 0 ? -rc
: rc
);
186 /** Additional file descriptor to use when logging seccomp2 failures */
187 static int sigsys_debugging_fd
= -1;
189 /** Use the file descriptor <b>fd</b> to log seccomp2 failures. */
191 sigsys_set_debugging_fd(int fd
)
193 sigsys_debugging_fd
= fd
;
197 * Function called when a SIGSYS is caught by the application. It notifies the
198 * user that an error has occurred and either terminates or allows the
199 * application to continue execution, based on the DEBUGGING_CLOSE symbol.
202 sigsys_debugging(int nr
, siginfo_t
*info
, void *void_context
)
204 ucontext_t
*ctx
= (ucontext_t
*) (void_context
);
206 int rv
= 0, syscall
, length
, err
;
209 if (info
->si_code
!= SYS_SECCOMP
)
215 syscall
= ctx
->uc_mcontext
.gregs
[REG_SYSCALL
];
217 /* XXXX Avoid use of snprintf; it isn't on the list of Stuff You're Allowed
218 * To Do In A Signal Handler. */
219 length
= snprintf(message
, sizeof(message
),
220 "\n\n(Sandbox) bad syscall (%d) was caught.\n",
224 if (sigsys_debugging_fd
>= 0) {
225 rv
= write(sigsys_debugging_fd
, message
, length
);
229 rv
= write(STDOUT_FILENO
, message
, length
);
235 #if defined(DEBUGGING_CLOSE)
237 #endif // DEBUGGING_CLOSE
241 * Function that adds a handler for SIGSYS, which is the signal thrown
242 * when the application is issuing a syscall which is not allowed. The
243 * main purpose of this function is to help with debugging by identifying
247 install_sigsys_debugging(void)
249 struct sigaction act
;
252 memset(&act
, 0, sizeof(act
));
254 sigaddset(&mask
, SIGSYS
);
256 act
.sa_sigaction
= &sigsys_debugging
;
257 act
.sa_flags
= SA_SIGINFO
;
258 if (sigaction(SIGSYS
, &act
, NULL
) < 0) {
259 log_err(LD_BUG
,"(Sandbox) Failed to register SIGSYS signal handler");
263 if (sigprocmask(SIG_UNBLOCK
, &mask
, NULL
)) {
264 log_err(LD_BUG
,"(Sandbox) Failed call to sigprocmask()");
270 #endif // USE_LIBSECCOMP
272 #ifdef USE_LIBSECCOMP
274 * Initialises the syscall sandbox filter for any linux architecture, taking
275 * into account various available features for different linux flavours.
278 initialise_libseccomp_sandbox(void)
280 if (install_sigsys_debugging())
283 if (install_glob_syscall_filter())
289 #endif // USE_LIBSECCOMP
292 * Enables the stage 1 general sandbox. It applies a syscall filter which does
293 * not restrict any Tor features. The filter is representative for the whole
297 tor_global_sandbox(void)
300 #if defined(USE_LIBSECCOMP)
301 return initialise_libseccomp_sandbox();
303 #elif defined(_WIN32)
304 log_warn(LD_BUG
,"Windows sandboxing is not implemented. The feature is "
305 "currently disabled.");
308 #elif defined(TARGET_OS_MAC)
309 log_warn(LD_BUG
,"Mac OSX sandboxing is not implemented. The feature is "
310 "currently disabled");
313 log_warn(LD_BUG
,"Sandboxing is not implemented for your platform. The "
314 "feature is currently disabled");
319 /** Use <b>fd</b> to log non-survivable sandbox violations. */
321 sandbox_set_debugging_fd(int fd
)
323 #ifdef USE_LIBSECCOMP
324 sigsys_set_debugging_fd(fd
);