1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd., 2015 4f08c3bdfSopenharmony_ci * Copyright (C) 2022 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com> 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/*\ 8f08c3bdfSopenharmony_ci * [Description] 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * Verify that if a process created via fork(2) or clone(2) without the 11f08c3bdfSopenharmony_ci * CLONE_NEWUSER flag is a member of the same user namespace as its parent. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * When unshare an user namespace, the calling process is moved into a new user 14f08c3bdfSopenharmony_ci * namespace which is not shared with any previously existing process. 15f08c3bdfSopenharmony_ci */ 16f08c3bdfSopenharmony_ci 17f08c3bdfSopenharmony_ci#define _GNU_SOURCE 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#include <stdio.h> 20f08c3bdfSopenharmony_ci#include "tst_test.h" 21f08c3bdfSopenharmony_ci#include "lapi/sched.h" 22f08c3bdfSopenharmony_ci#include "common.h" 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_cistatic void child_fn1(void) 25f08c3bdfSopenharmony_ci{ 26f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(0); 27f08c3bdfSopenharmony_ci} 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_cistatic unsigned int getusernsidbypid(int pid) 30f08c3bdfSopenharmony_ci{ 31f08c3bdfSopenharmony_ci char path[BUFSIZ]; 32f08c3bdfSopenharmony_ci char userid[BUFSIZ]; 33f08c3bdfSopenharmony_ci unsigned int id = 0; 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci sprintf(path, "/proc/%d/ns/user", pid); 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci SAFE_READLINK(path, userid, BUFSIZ); 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci if (sscanf(userid, "user:[%u]", &id) < 0) 40f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "sscanf failure"); 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci return id; 43f08c3bdfSopenharmony_ci} 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void run(void) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci const struct tst_clone_args args1 = { .exit_signal = SIGCHLD }; 48f08c3bdfSopenharmony_ci const struct tst_clone_args args2 = { 49f08c3bdfSopenharmony_ci .flags = CLONE_NEWUSER, 50f08c3bdfSopenharmony_ci .exit_signal = SIGCHLD, 51f08c3bdfSopenharmony_ci }; 52f08c3bdfSopenharmony_ci int cpid1, cpid2, cpid3; 53f08c3bdfSopenharmony_ci unsigned int parentuserns, cpid1userns, cpid2userns, newparentuserns; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci parentuserns = getusernsidbypid(getpid()); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci cpid1 = SAFE_CLONE(&args1); 58f08c3bdfSopenharmony_ci if (!cpid1) { 59f08c3bdfSopenharmony_ci child_fn1(); 60f08c3bdfSopenharmony_ci return; 61f08c3bdfSopenharmony_ci } 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci cpid1userns = getusernsidbypid(cpid1); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci /* A process created via fork(2) or clone(2) without the 68f08c3bdfSopenharmony_ci * CLONE_NEWUSER flag is a member of the same user namespace as its 69f08c3bdfSopenharmony_ci * parent 70f08c3bdfSopenharmony_ci */ 71f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(parentuserns, cpid1userns); 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci cpid2 = SAFE_CLONE(&args2); 74f08c3bdfSopenharmony_ci if (!cpid2) { 75f08c3bdfSopenharmony_ci child_fn1(); 76f08c3bdfSopenharmony_ci return; 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci cpid2userns = getusernsidbypid(cpid2); 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci TST_EXP_EXPR(parentuserns != cpid2userns, 84f08c3bdfSopenharmony_ci "parent namespace != child namespace"); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci cpid3 = SAFE_FORK(); 87f08c3bdfSopenharmony_ci if (!cpid3) { 88f08c3bdfSopenharmony_ci SAFE_UNSHARE(CLONE_NEWUSER); 89f08c3bdfSopenharmony_ci newparentuserns = getusernsidbypid(getpid()); 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci /* When unshare an user namespace, the calling process 92f08c3bdfSopenharmony_ci * is moved into a new user namespace which is not shared 93f08c3bdfSopenharmony_ci * with any previously existing process 94f08c3bdfSopenharmony_ci */ 95f08c3bdfSopenharmony_ci TST_EXP_EXPR(parentuserns != newparentuserns, 96f08c3bdfSopenharmony_ci "parent namespace != unshared child namespace"); 97f08c3bdfSopenharmony_ci } 98f08c3bdfSopenharmony_ci} 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_cistatic struct tst_test test = { 101f08c3bdfSopenharmony_ci .test_all = run, 102f08c3bdfSopenharmony_ci .needs_root = 1, 103f08c3bdfSopenharmony_ci .forks_child = 1, 104f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 105f08c3bdfSopenharmony_ci .needs_kconfigs = (const char *[]) { 106f08c3bdfSopenharmony_ci "CONFIG_USER_NS", 107f08c3bdfSopenharmony_ci NULL, 108f08c3bdfSopenharmony_ci }, 109f08c3bdfSopenharmony_ci}; 110