diff options
Diffstat (limited to 'kernel/seccomp.c')
-rw-r--r-- | kernel/seccomp.c | 21 |
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 | */ |
337 | static inline pid_t seccomp_can_sync_threads(void) | 337 | static 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 | */ |
507 | static long seccomp_attach_filter(unsigned int flags, | 510 | static 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(¤t->signal->cred_guard_mutex); | 1317 | mutex_unlock(¤t->signal->cred_guard_mutex); |
1305 | out_put_fd: | 1318 | out_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); |