1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2007
4f08c3bdfSopenharmony_ci * Copyright (C) 2023 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
5f08c3bdfSopenharmony_ci */
6f08c3bdfSopenharmony_ci
7f08c3bdfSopenharmony_ci/*\
8f08c3bdfSopenharmony_ci * [Description]
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci * Clone two processes using CLONE_NEWUTS, change hostname from the first
11f08c3bdfSopenharmony_ci * container and check if hostname didn't change inside the second one.
12f08c3bdfSopenharmony_ci */
13f08c3bdfSopenharmony_ci
14f08c3bdfSopenharmony_ci#define _GNU_SOURCE
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ci#include "tst_test.h"
17f08c3bdfSopenharmony_ci#include "lapi/sched.h"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci#define HOSTNAME "LTP_HOSTNAME"
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_cistatic char *str_op;
22f08c3bdfSopenharmony_cistatic char *hostname1;
23f08c3bdfSopenharmony_cistatic char *hostname2;
24f08c3bdfSopenharmony_cistatic char originalhost[HOST_NAME_MAX];
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_cistatic void reset_hostname(void)
27f08c3bdfSopenharmony_ci{
28f08c3bdfSopenharmony_ci	SAFE_SETHOSTNAME(originalhost, strlen(originalhost));
29f08c3bdfSopenharmony_ci}
30f08c3bdfSopenharmony_ci
31f08c3bdfSopenharmony_cistatic void child1_run(void)
32f08c3bdfSopenharmony_ci{
33f08c3bdfSopenharmony_ci	SAFE_SETHOSTNAME(HOSTNAME, strlen(HOSTNAME));
34f08c3bdfSopenharmony_ci	SAFE_GETHOSTNAME(hostname1, HOST_NAME_MAX);
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
37f08c3bdfSopenharmony_ci}
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_cistatic void child2_run(void)
40f08c3bdfSopenharmony_ci{
41f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(0);
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci	SAFE_GETHOSTNAME(hostname2, HOST_NAME_MAX);
44f08c3bdfSopenharmony_ci}
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cistatic void run(void)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	const struct tst_clone_args cargs = {
49f08c3bdfSopenharmony_ci		.flags = CLONE_NEWUTS,
50f08c3bdfSopenharmony_ci		.exit_signal = SIGCHLD,
51f08c3bdfSopenharmony_ci	};
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	memset(hostname1, 0, HOST_NAME_MAX);
54f08c3bdfSopenharmony_ci	memset(hostname2, 0, HOST_NAME_MAX);
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci	if (!str_op || !strcmp(str_op, "clone")) {
57f08c3bdfSopenharmony_ci		tst_res(TINFO, "clone() with CLONE_NEWUTS");
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_ci		if (!SAFE_CLONE(&cargs)) {
60f08c3bdfSopenharmony_ci			child1_run();
61f08c3bdfSopenharmony_ci			return;
62f08c3bdfSopenharmony_ci		}
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci		if (!SAFE_CLONE(&cargs)) {
65f08c3bdfSopenharmony_ci			child2_run();
66f08c3bdfSopenharmony_ci			return;
67f08c3bdfSopenharmony_ci		}
68f08c3bdfSopenharmony_ci	} else {
69f08c3bdfSopenharmony_ci		tst_res(TINFO, "unshare() with CLONE_NEWUTS");
70f08c3bdfSopenharmony_ci
71f08c3bdfSopenharmony_ci		if (!SAFE_FORK()) {
72f08c3bdfSopenharmony_ci			SAFE_UNSHARE(CLONE_NEWUTS);
73f08c3bdfSopenharmony_ci			child1_run();
74f08c3bdfSopenharmony_ci			return;
75f08c3bdfSopenharmony_ci		}
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci		if (!SAFE_FORK()) {
78f08c3bdfSopenharmony_ci			SAFE_UNSHARE(CLONE_NEWUTS);
79f08c3bdfSopenharmony_ci			child2_run();
80f08c3bdfSopenharmony_ci			return;
81f08c3bdfSopenharmony_ci		}
82f08c3bdfSopenharmony_ci	}
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	tst_reap_children();
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	TST_EXP_PASS(strcmp(hostname1, HOSTNAME));
87f08c3bdfSopenharmony_ci	TST_EXP_PASS(strcmp(hostname2, originalhost));
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	reset_hostname();
90f08c3bdfSopenharmony_ci}
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_cistatic void setup(void)
93f08c3bdfSopenharmony_ci{
94f08c3bdfSopenharmony_ci	hostname1 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
95f08c3bdfSopenharmony_ci	hostname2 = SAFE_MMAP(NULL, HOST_NAME_MAX, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	memset(originalhost, 0, HOST_NAME_MAX);
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	SAFE_GETHOSTNAME(originalhost, HOST_NAME_MAX);
100f08c3bdfSopenharmony_ci}
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_cistatic void cleanup(void)
103f08c3bdfSopenharmony_ci{
104f08c3bdfSopenharmony_ci	SAFE_MUNMAP(hostname1, HOST_NAME_MAX);
105f08c3bdfSopenharmony_ci	SAFE_MUNMAP(hostname2, HOST_NAME_MAX);
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	reset_hostname();
108f08c3bdfSopenharmony_ci}
109f08c3bdfSopenharmony_ci
110f08c3bdfSopenharmony_cistatic struct tst_test test = {
111f08c3bdfSopenharmony_ci	.test_all = run,
112f08c3bdfSopenharmony_ci	.setup = setup,
113f08c3bdfSopenharmony_ci	.cleanup = cleanup,
114f08c3bdfSopenharmony_ci	.needs_root = 1,
115f08c3bdfSopenharmony_ci	.forks_child = 1,
116f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
117f08c3bdfSopenharmony_ci	.options = (struct tst_option[]) {
118f08c3bdfSopenharmony_ci		{ "m:", &str_op, "Test execution mode <clone|unshare>" },
119f08c3bdfSopenharmony_ci		{},
120f08c3bdfSopenharmony_ci	},
121f08c3bdfSopenharmony_ci};
122