1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2020 Viresh Kumar <viresh.kumar@linaro.org> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/*\ 7f08c3bdfSopenharmony_ci * [Description] 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * Basic clone3() test to check various failures. 10f08c3bdfSopenharmony_ci */ 11f08c3bdfSopenharmony_ci 12f08c3bdfSopenharmony_ci#define _GNU_SOURCE 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include <stdlib.h> 15f08c3bdfSopenharmony_ci#include <assert.h> 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci#include "tst_test.h" 18f08c3bdfSopenharmony_ci#include "lapi/sched.h" 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_cistatic struct clone_args *valid_args, *invalid_args; 21f08c3bdfSopenharmony_ciunsigned long stack; 22f08c3bdfSopenharmony_cistatic int *invalid_address; 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic struct tcase { 25f08c3bdfSopenharmony_ci const char *name; 26f08c3bdfSopenharmony_ci struct clone_args **args; 27f08c3bdfSopenharmony_ci size_t size; 28f08c3bdfSopenharmony_ci uint64_t flags; 29f08c3bdfSopenharmony_ci int **pidfd; 30f08c3bdfSopenharmony_ci int exit_signal; 31f08c3bdfSopenharmony_ci unsigned long stack; 32f08c3bdfSopenharmony_ci unsigned long stack_size; 33f08c3bdfSopenharmony_ci unsigned long tls; 34f08c3bdfSopenharmony_ci int exp_errno; 35f08c3bdfSopenharmony_ci} tcases[] = { 36f08c3bdfSopenharmony_ci {"invalid args", &invalid_args, sizeof(*valid_args), 0, NULL, SIGCHLD, 0, 0, 0, EFAULT}, 37f08c3bdfSopenharmony_ci {"zero size", &valid_args, 0, 0, NULL, SIGCHLD, 0, 0, 0, EINVAL}, 38f08c3bdfSopenharmony_ci {"short size", &valid_args, sizeof(struct clone_args_minimal) - 1, 0, NULL, SIGCHLD, 0, 0, 0, EINVAL}, 39f08c3bdfSopenharmony_ci {"extra size", &valid_args, sizeof(*valid_args) + 1, 0, NULL, SIGCHLD, 0, 0, 0, EFAULT}, 40f08c3bdfSopenharmony_ci {"sighand-no-VM", &valid_args, sizeof(*valid_args), CLONE_SIGHAND, NULL, SIGCHLD, 0, 0, 0, EINVAL}, 41f08c3bdfSopenharmony_ci {"thread-no-sighand", &valid_args, sizeof(*valid_args), CLONE_THREAD, NULL, SIGCHLD, 0, 0, 0, EINVAL}, 42f08c3bdfSopenharmony_ci {"fs-newns", &valid_args, sizeof(*valid_args), CLONE_FS | CLONE_NEWNS, NULL, SIGCHLD, 0, 0, 0, EINVAL}, 43f08c3bdfSopenharmony_ci {"invalid pidfd", &valid_args, sizeof(*valid_args), CLONE_PIDFD, &invalid_address, SIGCHLD, 0, 0, 0, EFAULT}, 44f08c3bdfSopenharmony_ci {"invalid signal", &valid_args, sizeof(*valid_args), 0, NULL, CSIGNAL + 1, 0, 0, 0, EINVAL}, 45f08c3bdfSopenharmony_ci {"zero-stack-size", &valid_args, sizeof(*valid_args), 0, NULL, SIGCHLD, (unsigned long)&stack, 0, 0, EINVAL}, 46f08c3bdfSopenharmony_ci {"invalid-stack", &valid_args, sizeof(*valid_args), 0, NULL, SIGCHLD, 0, 4, 0, EINVAL}, 47f08c3bdfSopenharmony_ci /* 48f08c3bdfSopenharmony_ci * Don't test CLONE_CHILD_SETTID and CLONE_PARENT_SETTID: 49f08c3bdfSopenharmony_ci * When the parent tid is written to the memory location for 50f08c3bdfSopenharmony_ci * CLONE_PARENT_SETTID we're past the point of no return of process 51f08c3bdfSopenharmony_ci * creation, i.e. the return value from put_user() isn't checked and 52f08c3bdfSopenharmony_ci * can't be checked anymore so you'd never receive EFAULT for a bogus 53f08c3bdfSopenharmony_ci * parent_tid memory address. 54f08c3bdfSopenharmony_ci * 55f08c3bdfSopenharmony_ci * https://lore.kernel.org/linux-m68k/20200627122332.ki2otaiw3v7wndbl@wittgenstein/T/#u 56f08c3bdfSopenharmony_ci */ 57f08c3bdfSopenharmony_ci}; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_cistatic void setup(void) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci clone3_supported_by_kernel(); 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci TST_EXP_EQ_SZ(sizeof(struct clone_args_minimal), 64); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci void *p = tst_get_bad_addr(NULL); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci invalid_args = p; 68f08c3bdfSopenharmony_ci invalid_address = p; 69f08c3bdfSopenharmony_ci} 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistatic void run(unsigned int n) 72f08c3bdfSopenharmony_ci{ 73f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 74f08c3bdfSopenharmony_ci struct clone_args *args = *tc->args; 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci if (args == valid_args) { 77f08c3bdfSopenharmony_ci args->flags = tc->flags; 78f08c3bdfSopenharmony_ci if (tc->pidfd) 79f08c3bdfSopenharmony_ci args->pidfd = (uint64_t)(*tc->pidfd); 80f08c3bdfSopenharmony_ci else 81f08c3bdfSopenharmony_ci args->pidfd = 0; 82f08c3bdfSopenharmony_ci args->exit_signal = tc->exit_signal; 83f08c3bdfSopenharmony_ci args->stack = tc->stack; 84f08c3bdfSopenharmony_ci args->stack_size = tc->stack_size; 85f08c3bdfSopenharmony_ci args->tls = tc->tls; 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci TEST(clone3(args, tc->size)); 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci if (!TST_RET) 91f08c3bdfSopenharmony_ci exit(EXIT_SUCCESS); 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci if (TST_RET >= 0) { 94f08c3bdfSopenharmony_ci tst_res(TFAIL, "%s: clone3() passed unexpectedly", tc->name); 95f08c3bdfSopenharmony_ci return; 96f08c3bdfSopenharmony_ci } 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci if (tc->exp_errno != TST_ERR) { 99f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "%s: clone3() should fail with %s", 100f08c3bdfSopenharmony_ci tc->name, tst_strerrno(tc->exp_errno)); 101f08c3bdfSopenharmony_ci return; 102f08c3bdfSopenharmony_ci } 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "%s: clone3() failed as expected", tc->name); 105f08c3bdfSopenharmony_ci} 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_cistatic struct tst_test test = { 108f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 109f08c3bdfSopenharmony_ci .test = run, 110f08c3bdfSopenharmony_ci .setup = setup, 111f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 112f08c3bdfSopenharmony_ci .bufs = (struct tst_buffers []) { 113f08c3bdfSopenharmony_ci {&valid_args, .size = sizeof(*valid_args)}, 114f08c3bdfSopenharmony_ci {}, 115f08c3bdfSopenharmony_ci } 116f08c3bdfSopenharmony_ci}; 117