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 when a process with non-zero user IDs performs an execve(), 11f08c3bdfSopenharmony_ci * the process's capability sets are cleared. 12f08c3bdfSopenharmony_ci * When a process with zero user IDs performs an execve(), the process's 13f08c3bdfSopenharmony_ci * capability sets are set. 14f08c3bdfSopenharmony_ci */ 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci#include "tst_test.h" 17f08c3bdfSopenharmony_ci#include "config.h" 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#ifdef HAVE_LIBCAP 20f08c3bdfSopenharmony_ci#define _GNU_SOURCE 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_ci#include <stdio.h> 23f08c3bdfSopenharmony_ci#include "lapi/sched.h" 24f08c3bdfSopenharmony_ci#include "common.h" 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#define TEST_APP "userns06_capcheck" 27f08c3bdfSopenharmony_ci 28f08c3bdfSopenharmony_ci#define CHILD1UID 0 29f08c3bdfSopenharmony_ci#define CHILD1GID 0 30f08c3bdfSopenharmony_ci#define CHILD2UID 200 31f08c3bdfSopenharmony_ci#define CHILD2GID 200 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic void child_fn1(void) 34f08c3bdfSopenharmony_ci{ 35f08c3bdfSopenharmony_ci char *const args[] = { TEST_APP, "privileged", NULL }; 36f08c3bdfSopenharmony_ci int ret; 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(0); 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci ret = execv(args[0], args); 41f08c3bdfSopenharmony_ci if (ret == -1) 42f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "execv: unexpected error"); 43f08c3bdfSopenharmony_ci} 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_cistatic void child_fn2(void) 46f08c3bdfSopenharmony_ci{ 47f08c3bdfSopenharmony_ci int uid, gid, ret; 48f08c3bdfSopenharmony_ci char *const args[] = { TEST_APP, "unprivileged", NULL }; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAIT(1); 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci uid = geteuid(); 53f08c3bdfSopenharmony_ci gid = getegid(); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(uid, CHILD2UID); 56f08c3bdfSopenharmony_ci TST_EXP_EQ_LI(gid, CHILD2GID); 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci ret = execv(args[0], args); 59f08c3bdfSopenharmony_ci if (ret == -1) 60f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "execv: unexpected error"); 61f08c3bdfSopenharmony_ci} 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_cistatic void run(void) 64f08c3bdfSopenharmony_ci{ 65f08c3bdfSopenharmony_ci const struct tst_clone_args args = { 66f08c3bdfSopenharmony_ci .flags = CLONE_NEWUSER, 67f08c3bdfSopenharmony_ci .exit_signal = SIGCHLD, 68f08c3bdfSopenharmony_ci }; 69f08c3bdfSopenharmony_ci pid_t cpid1; 70f08c3bdfSopenharmony_ci pid_t cpid2; 71f08c3bdfSopenharmony_ci int parentuid; 72f08c3bdfSopenharmony_ci int parentgid; 73f08c3bdfSopenharmony_ci char path[BUFSIZ]; 74f08c3bdfSopenharmony_ci int fd; 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci parentuid = geteuid(); 77f08c3bdfSopenharmony_ci parentgid = getegid(); 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci cpid1 = SAFE_CLONE(&args); 80f08c3bdfSopenharmony_ci if (!cpid1) { 81f08c3bdfSopenharmony_ci child_fn1(); 82f08c3bdfSopenharmony_ci return; 83f08c3bdfSopenharmony_ci } 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci cpid2 = SAFE_CLONE(&args); 86f08c3bdfSopenharmony_ci if (!cpid2) { 87f08c3bdfSopenharmony_ci child_fn2(); 88f08c3bdfSopenharmony_ci return; 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci if (access("/proc/self/setgroups", F_OK) == 0) { 92f08c3bdfSopenharmony_ci sprintf(path, "/proc/%d/setgroups", cpid1); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci fd = SAFE_OPEN(path, O_WRONLY, 0644); 95f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, "deny", 4); 96f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci sprintf(path, "/proc/%d/setgroups", cpid2); 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci fd = SAFE_OPEN(path, O_WRONLY, 0644); 101f08c3bdfSopenharmony_ci SAFE_WRITE(SAFE_WRITE_ALL, fd, "deny", 4); 102f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci updatemap(cpid1, UID_MAP, CHILD1UID, parentuid); 106f08c3bdfSopenharmony_ci updatemap(cpid2, UID_MAP, CHILD2UID, parentuid); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci updatemap(cpid1, GID_MAP, CHILD1GID, parentgid); 109f08c3bdfSopenharmony_ci updatemap(cpid2, GID_MAP, CHILD2GID, parentgid); 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(0); 112f08c3bdfSopenharmony_ci TST_CHECKPOINT_WAKE(1); 113f08c3bdfSopenharmony_ci} 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_cistatic struct tst_test test = { 116f08c3bdfSopenharmony_ci .test_all = run, 117f08c3bdfSopenharmony_ci .needs_root = 1, 118f08c3bdfSopenharmony_ci .forks_child = 1, 119f08c3bdfSopenharmony_ci .needs_checkpoints = 1, 120f08c3bdfSopenharmony_ci .resource_files = (const char *[]) { 121f08c3bdfSopenharmony_ci TEST_APP, 122f08c3bdfSopenharmony_ci NULL, 123f08c3bdfSopenharmony_ci }, 124f08c3bdfSopenharmony_ci .needs_kconfigs = (const char *[]) { 125f08c3bdfSopenharmony_ci "CONFIG_USER_NS", 126f08c3bdfSopenharmony_ci NULL, 127f08c3bdfSopenharmony_ci }, 128f08c3bdfSopenharmony_ci}; 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci#else 131f08c3bdfSopenharmony_ciTST_TEST_TCONF("System is missing libcap"); 132f08c3bdfSopenharmony_ci#endif 133