1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2014-2020 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * errno tests for setns(2) - reassociate thread with a namespace 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci#define _GNU_SOURCE 8f08c3bdfSopenharmony_ci#include <sys/stat.h> 9f08c3bdfSopenharmony_ci#include <sys/types.h> 10f08c3bdfSopenharmony_ci#include <errno.h> 11f08c3bdfSopenharmony_ci#include <sched.h> 12f08c3bdfSopenharmony_ci#include <pwd.h> 13f08c3bdfSopenharmony_ci#include <string.h> 14f08c3bdfSopenharmony_ci#include "config.h" 15f08c3bdfSopenharmony_ci#include "tst_test.h" 16f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 17f08c3bdfSopenharmony_ci#include "setns.h" 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_cistatic const char nobody_uid[] = "nobody"; 20f08c3bdfSopenharmony_cistatic struct passwd *ltpuser; 21f08c3bdfSopenharmony_cistatic int regular_fd; 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistruct testcase_t { 24f08c3bdfSopenharmony_ci const char *msg; 25f08c3bdfSopenharmony_ci int fd; 26f08c3bdfSopenharmony_ci int ns_type; 27f08c3bdfSopenharmony_ci int exp_ret; 28f08c3bdfSopenharmony_ci int exp_errno; 29f08c3bdfSopenharmony_ci int skip; 30f08c3bdfSopenharmony_ci void (*setup) (struct testcase_t *, int i); 31f08c3bdfSopenharmony_ci void (*cleanup) (struct testcase_t *); 32f08c3bdfSopenharmony_ci}; 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_cistatic void setup0(struct testcase_t *t, int i) 35f08c3bdfSopenharmony_ci{ 36f08c3bdfSopenharmony_ci t->ns_type = ns_types[i]; 37f08c3bdfSopenharmony_ci} 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic void setup1(struct testcase_t *t, int i) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci t->ns_type = ns_types[i]; 42f08c3bdfSopenharmony_ci t->fd = regular_fd; 43f08c3bdfSopenharmony_ci} 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void setup2(struct testcase_t *t, int i) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci t->fd = ns_fds[i]; 48f08c3bdfSopenharmony_ci} 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic void setup3(struct testcase_t *t, int i) 51f08c3bdfSopenharmony_ci{ 52f08c3bdfSopenharmony_ci if (ns_total < 2) { 53f08c3bdfSopenharmony_ci t->skip = 1; 54f08c3bdfSopenharmony_ci return; 55f08c3bdfSopenharmony_ci } 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci t->fd = ns_fds[i]; 58f08c3bdfSopenharmony_ci t->ns_type = ns_types[(i+1) % ns_total]; 59f08c3bdfSopenharmony_ci} 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistatic void setup4(struct testcase_t *t, int i) 62f08c3bdfSopenharmony_ci{ 63f08c3bdfSopenharmony_ci SAFE_SETEUID(ltpuser->pw_uid); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci t->fd = ns_fds[i]; 66f08c3bdfSopenharmony_ci t->ns_type = ns_types[i]; 67f08c3bdfSopenharmony_ci} 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_cistatic void cleanup4(LTP_ATTRIBUTE_UNUSED struct testcase_t *t) 70f08c3bdfSopenharmony_ci{ 71f08c3bdfSopenharmony_ci SAFE_SETEUID(0); 72f08c3bdfSopenharmony_ci} 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_cistatic struct testcase_t tcases[] = { 75f08c3bdfSopenharmony_ci { 76f08c3bdfSopenharmony_ci .msg = "invalid fd", 77f08c3bdfSopenharmony_ci .fd = -1, 78f08c3bdfSopenharmony_ci .exp_ret = -1, 79f08c3bdfSopenharmony_ci .exp_errno = EBADF, 80f08c3bdfSopenharmony_ci .setup = setup0, 81f08c3bdfSopenharmony_ci }, 82f08c3bdfSopenharmony_ci { 83f08c3bdfSopenharmony_ci .msg = "regular file fd", 84f08c3bdfSopenharmony_ci .exp_ret = -1, 85f08c3bdfSopenharmony_ci .exp_errno = EINVAL, 86f08c3bdfSopenharmony_ci .setup = setup1, 87f08c3bdfSopenharmony_ci }, 88f08c3bdfSopenharmony_ci { 89f08c3bdfSopenharmony_ci .msg = "invalid ns_type", 90f08c3bdfSopenharmony_ci .ns_type = -1, 91f08c3bdfSopenharmony_ci .exp_ret = -1, 92f08c3bdfSopenharmony_ci .exp_errno = EINVAL, 93f08c3bdfSopenharmony_ci .setup = setup2, 94f08c3bdfSopenharmony_ci }, 95f08c3bdfSopenharmony_ci { 96f08c3bdfSopenharmony_ci .msg = "mismatch ns_type/fd", 97f08c3bdfSopenharmony_ci .exp_ret = -1, 98f08c3bdfSopenharmony_ci .exp_errno = EINVAL, 99f08c3bdfSopenharmony_ci .setup = setup3, 100f08c3bdfSopenharmony_ci }, 101f08c3bdfSopenharmony_ci { 102f08c3bdfSopenharmony_ci .msg = "without CAP_SYS_ADMIN", 103f08c3bdfSopenharmony_ci .exp_ret = -1, 104f08c3bdfSopenharmony_ci .exp_errno = EPERM, 105f08c3bdfSopenharmony_ci .setup = setup4, 106f08c3bdfSopenharmony_ci .cleanup = cleanup4, 107f08c3bdfSopenharmony_ci } 108f08c3bdfSopenharmony_ci}; 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_cistatic void test_setns(unsigned int testno) 111f08c3bdfSopenharmony_ci{ 112f08c3bdfSopenharmony_ci int ret, i; 113f08c3bdfSopenharmony_ci struct testcase_t *t = &tcases[testno]; 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci for (i = 0; i < ns_total; i++) { 116f08c3bdfSopenharmony_ci if (t->setup) 117f08c3bdfSopenharmony_ci t->setup(t, i); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci if (t->skip) { 120f08c3bdfSopenharmony_ci tst_res(TCONF, "skip %s", t->msg); 121f08c3bdfSopenharmony_ci continue; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci tst_res(TINFO, "setns(%d, 0x%x)", t->fd, t->ns_type); 125f08c3bdfSopenharmony_ci ret = tst_syscall(__NR_setns, t->fd, t->ns_type); 126f08c3bdfSopenharmony_ci if (ret == t->exp_ret) { 127f08c3bdfSopenharmony_ci if (ret == -1 && errno == t->exp_errno) { 128f08c3bdfSopenharmony_ci tst_res(TPASS, "%s exp_errno=%d (%s)", 129f08c3bdfSopenharmony_ci t->msg, t->exp_errno, 130f08c3bdfSopenharmony_ci tst_strerrno(t->exp_errno)); 131f08c3bdfSopenharmony_ci } else { 132f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, "%s exp_errno=%d (%s)", 133f08c3bdfSopenharmony_ci t->msg, t->exp_errno, 134f08c3bdfSopenharmony_ci tst_strerrno(t->exp_errno)); 135f08c3bdfSopenharmony_ci } 136f08c3bdfSopenharmony_ci } else { 137f08c3bdfSopenharmony_ci tst_res(TFAIL, "%s ret=%d expected=%d", 138f08c3bdfSopenharmony_ci t->msg, ret, t->exp_ret); 139f08c3bdfSopenharmony_ci } 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci if (t->cleanup) 142f08c3bdfSopenharmony_ci t->cleanup(t); 143f08c3bdfSopenharmony_ci } 144f08c3bdfSopenharmony_ci} 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_cistatic void setup(void) 147f08c3bdfSopenharmony_ci{ 148f08c3bdfSopenharmony_ci /* runtime check if syscall is supported */ 149f08c3bdfSopenharmony_ci tst_syscall(__NR_setns, -1, 0); 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci init_available_ns(); 152f08c3bdfSopenharmony_ci if (ns_total == 0) 153f08c3bdfSopenharmony_ci tst_brk(TCONF, "no ns types/proc entries"); 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM(nobody_uid); 156f08c3bdfSopenharmony_ci regular_fd = SAFE_OPEN("dummy", O_RDWR|O_CREAT, 0600); 157f08c3bdfSopenharmony_ci SAFE_UNLINK("dummy"); 158f08c3bdfSopenharmony_ci} 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_cistatic void cleanup(void) 161f08c3bdfSopenharmony_ci{ 162f08c3bdfSopenharmony_ci close_ns_fds(); 163f08c3bdfSopenharmony_ci if (regular_fd) 164f08c3bdfSopenharmony_ci SAFE_CLOSE(regular_fd); 165f08c3bdfSopenharmony_ci} 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_cistatic struct tst_test test = { 168f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 169f08c3bdfSopenharmony_ci .test = test_setns, 170f08c3bdfSopenharmony_ci .setup = setup, 171f08c3bdfSopenharmony_ci .cleanup = cleanup, 172f08c3bdfSopenharmony_ci .needs_root = 1, 173f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 174f08c3bdfSopenharmony_ci}; 175f08c3bdfSopenharmony_ci 176