aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/seccomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/seccomp.c')
-rw-r--r--kernel/seccomp.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 54a0347ca812..a635ecba6fe2 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -149,7 +149,7 @@ static void populate_seccomp_data(struct seccomp_data *sd)
149 149
150 sd->nr = syscall_get_nr(task, regs); 150 sd->nr = syscall_get_nr(task, regs);
151 sd->arch = syscall_get_arch(); 151 sd->arch = syscall_get_arch();
152 syscall_get_arguments(task, regs, 0, 6, args); 152 syscall_get_arguments(task, regs, args);
153 sd->args[0] = args[0]; 153 sd->args[0] = args[0];
154 sd->args[1] = args[1]; 154 sd->args[1] = args[1];
155 sd->args[2] = args[2]; 155 sd->args[2] = args[2];
@@ -331,7 +331,7 @@ static int is_ancestor(struct seccomp_filter *parent,
331 * Expects sighand and cred_guard_mutex locks to be held. 331 * Expects sighand and cred_guard_mutex locks to be held.
332 * 332 *
333 * Returns 0 on success, -ve on error, or the pid of a thread which was 333 * Returns 0 on success, -ve on error, or the pid of a thread which was
334 * either not in the correct seccomp mode or it did not have an ancestral 334 * either not in the correct seccomp mode or did not have an ancestral
335 * seccomp filter. 335 * seccomp filter.
336 */ 336 */
337static inline pid_t seccomp_can_sync_threads(void) 337static inline pid_t seccomp_can_sync_threads(void)
@@ -502,7 +502,10 @@ out:
502 * 502 *
503 * Caller must be holding current->sighand->siglock lock. 503 * Caller must be holding current->sighand->siglock lock.
504 * 504 *
505 * Returns 0 on success, -ve on error. 505 * Returns 0 on success, -ve on error, or
506 * - in TSYNC mode: the pid of a thread which was either not in the correct
507 * seccomp mode or did not have an ancestral seccomp filter
508 * - in NEW_LISTENER mode: the fd of the new listener
506 */ 509 */
507static long seccomp_attach_filter(unsigned int flags, 510static long seccomp_attach_filter(unsigned int flags,
508 struct seccomp_filter *filter) 511 struct seccomp_filter *filter)
@@ -1258,6 +1261,16 @@ static long seccomp_set_mode_filter(unsigned int flags,
1258 if (flags & ~SECCOMP_FILTER_FLAG_MASK) 1261 if (flags & ~SECCOMP_FILTER_FLAG_MASK)
1259 return -EINVAL; 1262 return -EINVAL;
1260 1263
1264 /*
1265 * In the successful case, NEW_LISTENER returns the new listener fd.
1266 * But in the failure case, TSYNC returns the thread that died. If you
1267 * combine these two flags, there's no way to tell whether something
1268 * succeeded or failed. So, let's disallow this combination.
1269 */
1270 if ((flags & SECCOMP_FILTER_FLAG_TSYNC) &&
1271 (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER))
1272 return -EINVAL;
1273
1261 /* Prepare the new filter before holding any locks. */ 1274 /* Prepare the new filter before holding any locks. */
1262 prepared = seccomp_prepare_user_filter(filter); 1275 prepared = seccomp_prepare_user_filter(filter);
1263 if (IS_ERR(prepared)) 1276 if (IS_ERR(prepared))
@@ -1304,7 +1317,7 @@ out:
1304 mutex_unlock(&current->signal->cred_guard_mutex); 1317 mutex_unlock(&current->signal->cred_guard_mutex);
1305out_put_fd: 1318out_put_fd:
1306 if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) { 1319 if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
1307 if (ret < 0) { 1320 if (ret) {
1308 listener_f->private_data = NULL; 1321 listener_f->private_data = NULL;
1309 fput(listener_f); 1322 fput(listener_f);
1310 put_unused_fd(listener); 1323 put_unused_fd(listener);