| @@ -2406,6 +2406,16 @@ long _do_fork(struct kernel_clone_args *args) · 2405 unmodified lines |
| 2406 | 2406 | return nr; |
| 2407 | 2407 | } |
| 2408 | 2408 | |
| 2409 | +bool legacy_clone_args_valid(const struct kernel_clone_args *kargs) |
| 2410 | +{ |
| 2411 | + /* clone(CLONE_PIDFD) uses parent_tidptr to return a pidfd */ |
| 2412 | + if ((kargs->flags & CLONE_PIDFD) && |
| 2413 | + (kargs->flags & CLONE_PARENT_SETTID)) |
| 2414 | + return false; |
| 2415 | + |
| 2416 | + return true; |
| 2417 | +} |
| 2418 | + |
| 2409 | 2419 | #ifndef CONFIG_HAVE_COPY_THREAD_TLS |
| 2410 | 2420 | /* For compatibility with architectures that call do_fork directly rather than |
| 2411 | 2421 | * using the syscall entry points below. */ |
| @@ -2417,6 +2427,7 @@ long do_fork(unsigned long clone_flags, · 5 unmodified lines |
| 2417 | 2427 | { |
| 2418 | 2428 | struct kernel_clone_args args = { |
| 2419 | 2429 | .flags = (clone_flags & ~CSIGNAL), |
| 2430 | + .pidfd = parent_tidptr, |
| 2420 | 2431 | .child_tid = child_tidptr, |
| 2421 | 2432 | .parent_tid = parent_tidptr, |
| 2422 | 2433 | .exit_signal = (clone_flags & CSIGNAL), |
| @@ -2424,6 +2435,9 @@ long do_fork(unsigned long clone_flags, · 1 unmodified line |
| 2424 | 2435 | .stack_size = stack_size, |
| 2425 | 2436 | }; |
| 2426 | 2437 | |
| 2438 | + if (!legacy_clone_args_valid(&args)) |
| 2439 | + return -EINVAL; |
| 2440 | + |
| 2427 | 2441 | return _do_fork(&args); |
| 2428 | 2442 | } |
| 2429 | 2443 | #endif |
| @@ -2505,8 +2519,7 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, · 75 unmodified lines |
| 2505 | 2519 | .tls = tls, |
| 2506 | 2520 | }; |
| 2507 | 2521 | |
| 2508 | | − /* clone(CLONE_PIDFD) uses parent_tidptr to return a pidfd */ |
| 2509 | | − if ((clone_flags & CLONE_PIDFD) && (clone_flags & CLONE_PARENT_SETTID)) |
| 2522 | + if (!legacy_clone_args_valid(&args)) |
| 2510 | 2523 | return -EINVAL; |
| 2511 | 2524 | |
| 2512 | 2525 | return _do_fork(&args); |