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 user ID has no mapping inside the namespace, user ID and
11f08c3bdfSopenharmony_ci * group ID will be the value defined in the file /proc/sys/kernel/overflowuid
12f08c3bdfSopenharmony_ci * (defaults to 65534) and /proc/sys/kernel/overflowgid (defaults to 65534). A
13f08c3bdfSopenharmony_ci * child process has a full set of permitted and effective capabilities, even
14f08c3bdfSopenharmony_ci * though the program was run from an unprivileged account.
15f08c3bdfSopenharmony_ci */
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#include "tst_test.h"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci#ifdef HAVE_LIBCAP
20f08c3bdfSopenharmony_ci#define _GNU_SOURCE
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_ci#include <stdio.h>
23f08c3bdfSopenharmony_ci#include "config.h"
24f08c3bdfSopenharmony_ci#include <sys/capability.h>
25f08c3bdfSopenharmony_ci#include "lapi/sched.h"
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#define OVERFLOWUIDPATH "/proc/sys/kernel/overflowuid"
28f08c3bdfSopenharmony_ci#define OVERFLOWGIDPATH "/proc/sys/kernel/overflowgid"
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_cistatic long overflowuid;
31f08c3bdfSopenharmony_cistatic long overflowgid;
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_cistatic void child_fn1(void)
34f08c3bdfSopenharmony_ci{
35f08c3bdfSopenharmony_ci	int uid, gid;
36f08c3bdfSopenharmony_ci	cap_t caps;
37f08c3bdfSopenharmony_ci	int i, last_cap;
38f08c3bdfSopenharmony_ci	cap_flag_value_t flag_val;
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci	uid = geteuid();
41f08c3bdfSopenharmony_ci	gid = getegid();
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci	tst_res(TINFO, "USERNS test is running in a new user namespace.");
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ci	TST_EXP_EQ_LI(uid, overflowuid);
46f08c3bdfSopenharmony_ci	TST_EXP_EQ_LI(gid, overflowgid);
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci	caps = cap_get_proc();
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	SAFE_FILE_SCANF("/proc/sys/kernel/cap_last_cap", "%d", &last_cap);
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci	for (i = 0; i <= last_cap; i++) {
53f08c3bdfSopenharmony_ci		cap_get_flag(caps, i, CAP_EFFECTIVE, &flag_val);
54f08c3bdfSopenharmony_ci		if (!flag_val)
55f08c3bdfSopenharmony_ci			break;
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci		cap_get_flag(caps, i, CAP_PERMITTED, &flag_val);
58f08c3bdfSopenharmony_ci		if (!flag_val)
59f08c3bdfSopenharmony_ci			break;
60f08c3bdfSopenharmony_ci	}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	if (!flag_val)
63f08c3bdfSopenharmony_ci		tst_res(TFAIL, "unexpected effective/permitted caps at %d", i);
64f08c3bdfSopenharmony_ci	else
65f08c3bdfSopenharmony_ci		tst_res(TPASS, "expected capabilities");
66f08c3bdfSopenharmony_ci}
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_cistatic void setup(void)
69f08c3bdfSopenharmony_ci{
70f08c3bdfSopenharmony_ci	SAFE_FILE_SCANF(OVERFLOWUIDPATH, "%ld", &overflowuid);
71f08c3bdfSopenharmony_ci	SAFE_FILE_SCANF(OVERFLOWGIDPATH, "%ld", &overflowgid);
72f08c3bdfSopenharmony_ci}
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_cistatic void run(void)
75f08c3bdfSopenharmony_ci{
76f08c3bdfSopenharmony_ci	const struct tst_clone_args args = {
77f08c3bdfSopenharmony_ci		.flags = CLONE_NEWUSER,
78f08c3bdfSopenharmony_ci		.exit_signal = SIGCHLD,
79f08c3bdfSopenharmony_ci	};
80f08c3bdfSopenharmony_ci
81f08c3bdfSopenharmony_ci	if (!SAFE_CLONE(&args)) {
82f08c3bdfSopenharmony_ci		child_fn1();
83f08c3bdfSopenharmony_ci		return;
84f08c3bdfSopenharmony_ci	}
85f08c3bdfSopenharmony_ci}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_cistatic struct tst_test test = {
88f08c3bdfSopenharmony_ci	.setup = setup,
89f08c3bdfSopenharmony_ci	.test_all = run,
90f08c3bdfSopenharmony_ci	.needs_root = 1,
91f08c3bdfSopenharmony_ci	.forks_child = 1,
92f08c3bdfSopenharmony_ci	.caps = (struct tst_cap []) {
93f08c3bdfSopenharmony_ci		TST_CAP(TST_CAP_DROP, CAP_NET_RAW),
94f08c3bdfSopenharmony_ci		{}
95f08c3bdfSopenharmony_ci	},
96f08c3bdfSopenharmony_ci	.needs_kconfigs = (const char *[]) {
97f08c3bdfSopenharmony_ci		"CONFIG_USER_NS",
98f08c3bdfSopenharmony_ci		NULL,
99f08c3bdfSopenharmony_ci	},
100f08c3bdfSopenharmony_ci};
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ci#else
103f08c3bdfSopenharmony_ciTST_TEST_TCONF("System is missing libcap");
104f08c3bdfSopenharmony_ci#endif
105