1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci * Test case to check that kill() fails when passed a pid owned by another user.
6f08c3bdfSopenharmony_ci *
7f08c3bdfSopenharmony_ci * HISTORY
8f08c3bdfSopenharmony_ci *	07/2001 Ported by Wayne Boyer
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *      26/02/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
11f08c3bdfSopenharmony_ci *      - Fix wrong return value check on shmat system call (leading to
12f08c3bdfSopenharmony_ci *        segfault in case of error with this syscall).
13f08c3bdfSopenharmony_ci *      - Fix deletion of IPC memory segment. Segment was not correctly
14f08c3bdfSopenharmony_ci *        deleted due to the change of uid during the test.
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * RESTRICTIONS
17f08c3bdfSopenharmony_ci *	This test must be run as root.
18f08c3bdfSopenharmony_ci */
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#include <sys/wait.h>
21f08c3bdfSopenharmony_ci#include <pwd.h>
22f08c3bdfSopenharmony_ci#include <stdlib.h>
23f08c3bdfSopenharmony_ci#include "tst_test.h"
24f08c3bdfSopenharmony_ci#include "libnewipc.h"
25f08c3bdfSopenharmony_ci#include "tst_safe_sysv_ipc.h"
26f08c3bdfSopenharmony_ci#include "tst_safe_macros.h"
27f08c3bdfSopenharmony_ci#include "tst_uid.h"
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_cistatic uid_t test_users[2];
30f08c3bdfSopenharmony_cistatic int *flag;
31f08c3bdfSopenharmony_cistatic int shm_id = -1;
32f08c3bdfSopenharmony_cistatic key_t shm_key;
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_cistatic void wait_for_flag(int value)
35f08c3bdfSopenharmony_ci{
36f08c3bdfSopenharmony_ci	while (1) {
37f08c3bdfSopenharmony_ci		if (*flag == value)
38f08c3bdfSopenharmony_ci			break;
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci		usleep(100);
41f08c3bdfSopenharmony_ci	}
42f08c3bdfSopenharmony_ci}
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_cistatic void do_master_child(void)
45f08c3bdfSopenharmony_ci{
46f08c3bdfSopenharmony_ci	pid_t pid1;
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci	*flag = 0;
49f08c3bdfSopenharmony_ci	pid1 = SAFE_FORK();
50f08c3bdfSopenharmony_ci	if (pid1 == 0) {
51f08c3bdfSopenharmony_ci		SAFE_SETREUID(test_users[0], test_users[0]);
52f08c3bdfSopenharmony_ci		*flag = 1;
53f08c3bdfSopenharmony_ci		wait_for_flag(2);
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci		exit(0);
56f08c3bdfSopenharmony_ci	}
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	SAFE_SETREUID(test_users[1], test_users[1]);
59f08c3bdfSopenharmony_ci	wait_for_flag(1);
60f08c3bdfSopenharmony_ci	TEST(kill(pid1, SIGKILL));
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	*flag = 2;
63f08c3bdfSopenharmony_ci	SAFE_WAITPID(pid1, NULL, 0);
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci	if (TST_RET == 0)
66f08c3bdfSopenharmony_ci		tst_brk(TFAIL, "kill succeeded unexpectedly");
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci	if (TST_ERR == EPERM)
69f08c3bdfSopenharmony_ci		tst_res(TPASS, "kill failed with EPERM");
70f08c3bdfSopenharmony_ci	else
71f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO, "kill failed expected EPERM, but got");
72f08c3bdfSopenharmony_ci}
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_cistatic void verify_kill(void)
75f08c3bdfSopenharmony_ci{
76f08c3bdfSopenharmony_ci	pid_t pid;
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
79f08c3bdfSopenharmony_ci	if (pid == 0) {
80f08c3bdfSopenharmony_ci		do_master_child();
81f08c3bdfSopenharmony_ci		exit(0);
82f08c3bdfSopenharmony_ci	}
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	tst_reap_children();
85f08c3bdfSopenharmony_ci}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_cistatic void setup(void)
88f08c3bdfSopenharmony_ci{
89f08c3bdfSopenharmony_ci	shm_key = GETIPCKEY();
90f08c3bdfSopenharmony_ci	shm_id = SAFE_SHMGET(shm_key, getpagesize(), 0666 | IPC_CREAT);
91f08c3bdfSopenharmony_ci	flag = SAFE_SHMAT(shm_id, 0, 0);
92f08c3bdfSopenharmony_ci	tst_get_uids(test_users, 0, 2);
93f08c3bdfSopenharmony_ci}
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_cistatic void cleanup(void)
96f08c3bdfSopenharmony_ci{
97f08c3bdfSopenharmony_ci	if (shm_id != -1)
98f08c3bdfSopenharmony_ci		SAFE_SHMCTL(shm_id, IPC_RMID, NULL);
99f08c3bdfSopenharmony_ci}
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_cistatic struct tst_test test = {
102f08c3bdfSopenharmony_ci	.setup = setup,
103f08c3bdfSopenharmony_ci	.cleanup = cleanup,
104f08c3bdfSopenharmony_ci	.test_all = verify_kill,
105f08c3bdfSopenharmony_ci	.needs_root = 1,
106f08c3bdfSopenharmony_ci	.forks_child = 1,
107f08c3bdfSopenharmony_ci};
108