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 * functional test for setns(2) - reassociate thread with a namespace 6f08c3bdfSopenharmony_ci * 1. create child with CLONE_NEWUTS, set different hostname in child, 7f08c3bdfSopenharmony_ci * set namespace back to parent ns and check that hostname has changed 8f08c3bdfSopenharmony_ci * 2. create child with CLONE_NEWIPC, set up shared memory in parent 9f08c3bdfSopenharmony_ci * and verify that child can't shmat it, then set namespace 10f08c3bdfSopenharmony_ci * back to parent one and verify that child is able to do shmat 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci#define _GNU_SOURCE 13f08c3bdfSopenharmony_ci#include <sys/ipc.h> 14f08c3bdfSopenharmony_ci#include <sys/shm.h> 15f08c3bdfSopenharmony_ci#include <sys/stat.h> 16f08c3bdfSopenharmony_ci#include <sys/types.h> 17f08c3bdfSopenharmony_ci#include <sys/utsname.h> 18f08c3bdfSopenharmony_ci#include <sys/wait.h> 19f08c3bdfSopenharmony_ci#include <errno.h> 20f08c3bdfSopenharmony_ci#include <sched.h> 21f08c3bdfSopenharmony_ci#include <stdlib.h> 22f08c3bdfSopenharmony_ci#include <string.h> 23f08c3bdfSopenharmony_ci#include "config.h" 24f08c3bdfSopenharmony_ci#include "tst_test.h" 25f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h" 26f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 27f08c3bdfSopenharmony_ci#include "setns.h" 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#define CHILD_STACK_SIZE (1024*1024) 30f08c3bdfSopenharmony_ci#define CP "(child) " 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_cistatic char *dummy_hostname = "setns_dummy_uts"; 33f08c3bdfSopenharmony_cistatic int ns_ipc_fd; 34f08c3bdfSopenharmony_cistatic int ns_uts_fd; 35f08c3bdfSopenharmony_cistatic key_t ipc_key; 36f08c3bdfSopenharmony_cistatic int shmid; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_cistatic void setup(void); 39f08c3bdfSopenharmony_cistatic void cleanup(void); 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_cistatic int do_child_newuts(void *arg) 42f08c3bdfSopenharmony_ci{ 43f08c3bdfSopenharmony_ci struct utsname uts, uts_parent; 44f08c3bdfSopenharmony_ci int ns_flag = *(int *)arg; 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci if (uname(&uts_parent) == -1) 47f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"uname"); 48f08c3bdfSopenharmony_ci tst_res(TINFO, CP"hostname (inherited from parent): %s", 49f08c3bdfSopenharmony_ci uts_parent.nodename); 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci if (sethostname(dummy_hostname, strlen(dummy_hostname)) == -1) 52f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"sethostname"); 53f08c3bdfSopenharmony_ci if (uname(&uts) == -1) 54f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"uname"); 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci tst_res(TINFO, CP"hostname changed to: %s", uts.nodename); 57f08c3bdfSopenharmony_ci if (strcmp(uts_parent.nodename, uts.nodename) == 0) { 58f08c3bdfSopenharmony_ci tst_res(TFAIL, CP"expected hostname to be different"); 59f08c3bdfSopenharmony_ci return 1; 60f08c3bdfSopenharmony_ci } else { 61f08c3bdfSopenharmony_ci tst_res(TPASS, CP"hostname is different in parent/child"); 62f08c3bdfSopenharmony_ci } 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci tst_res(TINFO, CP"attempting to switch ns back to parent ns"); 65f08c3bdfSopenharmony_ci if (tst_syscall(__NR_setns, ns_uts_fd, ns_flag) == -1) { 66f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"setns"); 67f08c3bdfSopenharmony_ci return 2; 68f08c3bdfSopenharmony_ci } 69f08c3bdfSopenharmony_ci if (uname(&uts) == -1) 70f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"uname"); 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci tst_res(TINFO, CP"hostname: %s", uts.nodename); 73f08c3bdfSopenharmony_ci if (strcmp(uts_parent.nodename, uts.nodename) != 0) { 74f08c3bdfSopenharmony_ci tst_res(TFAIL, CP"expected hostname to match parent"); 75f08c3bdfSopenharmony_ci return 3; 76f08c3bdfSopenharmony_ci } else { 77f08c3bdfSopenharmony_ci tst_res(TPASS, CP"hostname now as expected"); 78f08c3bdfSopenharmony_ci } 79f08c3bdfSopenharmony_ci return 0; 80f08c3bdfSopenharmony_ci} 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_cistatic int do_child_newipc(void *arg) 83f08c3bdfSopenharmony_ci{ 84f08c3bdfSopenharmony_ci void *p; 85f08c3bdfSopenharmony_ci int ns_flag = *(int *)arg; 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci p = shmat(shmid, NULL, 0); 88f08c3bdfSopenharmony_ci if (p == (void *) -1) { 89f08c3bdfSopenharmony_ci tst_res(TPASS|TERRNO, CP"shmat failed as expected"); 90f08c3bdfSopenharmony_ci } else { 91f08c3bdfSopenharmony_ci tst_res(TFAIL, CP"shmat unexpectedly suceeded"); 92f08c3bdfSopenharmony_ci shmdt(p); 93f08c3bdfSopenharmony_ci return 1; 94f08c3bdfSopenharmony_ci } 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci tst_res(TINFO, CP"attempting to switch ns back to parent ns"); 97f08c3bdfSopenharmony_ci if (tst_syscall(__NR_setns, ns_ipc_fd, ns_flag) == -1) { 98f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"setns"); 99f08c3bdfSopenharmony_ci return 2; 100f08c3bdfSopenharmony_ci } 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci p = shmat(shmid, NULL, 0); 103f08c3bdfSopenharmony_ci if (p == (void *) -1) { 104f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, CP"shmat failed after setns"); 105f08c3bdfSopenharmony_ci return 3; 106f08c3bdfSopenharmony_ci } else { 107f08c3bdfSopenharmony_ci tst_res(TPASS, CP"shmat suceeded"); 108f08c3bdfSopenharmony_ci shmdt(p); 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci return 0; 112f08c3bdfSopenharmony_ci} 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_cistatic void test_flag(int clone_flag, int ns_flag, int (*fn) (void *arg)) 115f08c3bdfSopenharmony_ci{ 116f08c3bdfSopenharmony_ci void *child_stack; 117f08c3bdfSopenharmony_ci int ret, status; 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci child_stack = SAFE_MALLOC(CHILD_STACK_SIZE); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci tst_res(TINFO, "creating child with clone_flag=0x%x, ns_flag=0x%x", 122f08c3bdfSopenharmony_ci clone_flag, ns_flag); 123f08c3bdfSopenharmony_ci ret = ltp_clone(SIGCHLD|clone_flag, fn, &ns_flag, 124f08c3bdfSopenharmony_ci CHILD_STACK_SIZE, child_stack); 125f08c3bdfSopenharmony_ci if (ret == -1) 126f08c3bdfSopenharmony_ci tst_brk(TBROK|TERRNO, "ltp_clone"); 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci SAFE_WAITPID(ret, &status, 0); 129f08c3bdfSopenharmony_ci free(child_stack); 130f08c3bdfSopenharmony_ci} 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_civoid test_all(void) 133f08c3bdfSopenharmony_ci{ 134f08c3bdfSopenharmony_ci if (ns_uts_fd != -1) { 135f08c3bdfSopenharmony_ci tst_res(TINFO, "test_newuts"); 136f08c3bdfSopenharmony_ci test_flag(CLONE_NEWUTS, CLONE_NEWUTS, do_child_newuts); 137f08c3bdfSopenharmony_ci test_flag(CLONE_NEWUTS, 0, do_child_newuts); 138f08c3bdfSopenharmony_ci } else 139f08c3bdfSopenharmony_ci tst_res(TCONF, "CLONE_NEWUTS is not supported"); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci if (ns_ipc_fd != -1) { 142f08c3bdfSopenharmony_ci tst_res(TINFO, "test_newipc"); 143f08c3bdfSopenharmony_ci test_flag(CLONE_NEWIPC, CLONE_NEWIPC, do_child_newipc); 144f08c3bdfSopenharmony_ci test_flag(CLONE_NEWIPC, 0, do_child_newipc); 145f08c3bdfSopenharmony_ci } else 146f08c3bdfSopenharmony_ci tst_res(TCONF, "CLONE_NEWIPC is not supported"); 147f08c3bdfSopenharmony_ci} 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_cistatic void setup(void) 150f08c3bdfSopenharmony_ci{ 151f08c3bdfSopenharmony_ci char tmp[PATH_MAX]; 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci /* runtime check if syscall is supported */ 154f08c3bdfSopenharmony_ci tst_syscall(__NR_setns, -1, 0); 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci /* check if kernel has CONFIG_*_NS set and exports /proc entries */ 157f08c3bdfSopenharmony_ci ns_ipc_fd = get_ns_fd(getpid(), "ipc"); 158f08c3bdfSopenharmony_ci ns_uts_fd = get_ns_fd(getpid(), "uts"); 159f08c3bdfSopenharmony_ci if (ns_ipc_fd == -1 && ns_uts_fd == -1) 160f08c3bdfSopenharmony_ci tst_brk(TCONF, "your kernel has CONFIG_IPC_NS, " 161f08c3bdfSopenharmony_ci "CONFIG_UTS_NS or CONFIG_PROC disabled"); 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci SAFE_GETCWD(tmp, PATH_MAX); 164f08c3bdfSopenharmony_ci ipc_key = ftok(tmp, 65); 165f08c3bdfSopenharmony_ci shmid = SAFE_SHMGET(ipc_key, getpagesize(), IPC_CREAT | 0666); 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_cistatic void cleanup(void) 169f08c3bdfSopenharmony_ci{ 170f08c3bdfSopenharmony_ci if (ns_ipc_fd != -1) 171f08c3bdfSopenharmony_ci SAFE_CLOSE(ns_ipc_fd); 172f08c3bdfSopenharmony_ci if (ns_uts_fd != -1) 173f08c3bdfSopenharmony_ci SAFE_CLOSE(ns_uts_fd); 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci SAFE_SHMCTL(shmid, IPC_RMID, NULL); 176f08c3bdfSopenharmony_ci} 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_cistatic struct tst_test test = { 179f08c3bdfSopenharmony_ci .test_all = test_all, 180f08c3bdfSopenharmony_ci .setup = setup, 181f08c3bdfSopenharmony_ci .cleanup = cleanup, 182f08c3bdfSopenharmony_ci .needs_root = 1, 183f08c3bdfSopenharmony_ci}; 184