1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2001
4f08c3bdfSopenharmony_ci * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved.
5f08c3bdfSopenharmony_ci * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
6f08c3bdfSopenharmony_ci * Copyright (C) 2021 SUSE LLC Andrea Cervesato <andrea.cervesato@suse.com>
7f08c3bdfSopenharmony_ci */
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ci/*\
10f08c3bdfSopenharmony_ci * [Description]
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Tests setpgid(2) errors:
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci * - EPERM The process specified by pid must not be a session leader.
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * - EPERM The calling process, process specified by pid and the target
17f08c3bdfSopenharmony_ci *         process group must be in the same session.
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * - EACCESS Proccess cannot change process group ID of a child after child
20f08c3bdfSopenharmony_ci *           has performed exec()
21f08c3bdfSopenharmony_ci */
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_ci#include <unistd.h>
24f08c3bdfSopenharmony_ci#include <sys/wait.h>
25f08c3bdfSopenharmony_ci#include "tst_test.h"
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ci#define TEST_APP "setpgid03_child"
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_cistatic void do_child(void)
30f08c3bdfSopenharmony_ci{
31f08c3bdfSopenharmony_ci	SAFE_SETSID();
32f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE_AND_WAIT(0);
33f08c3bdfSopenharmony_ci}
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_cistatic void run(void)
36f08c3bdfSopenharmony_ci{
37f08c3bdfSopenharmony_ci	pid_t child_pid;
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci	child_pid = SAFE_FORK();
40f08c3bdfSopenharmony_ci	if (!child_pid) {
41f08c3bdfSopenharmony_ci		do_child();
42f08c3bdfSopenharmony_ci		return;
43f08c3bdfSopenharmony_ci	}
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(0);
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ci	TST_EXP_FAIL(setpgid(child_pid, getppid()), EPERM);
48f08c3bdfSopenharmony_ci	/* Child did setsid(), so its PGID is set to its PID. */
49f08c3bdfSopenharmony_ci	TST_EXP_FAIL(setpgid(0, child_pid), EPERM);
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	/* child after exec() we are no longer allowed to set pgid */
54f08c3bdfSopenharmony_ci	child_pid = SAFE_FORK();
55f08c3bdfSopenharmony_ci	if (!child_pid)
56f08c3bdfSopenharmony_ci		SAFE_EXECLP(TEST_APP, TEST_APP, NULL);
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(0);
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_ci	TST_EXP_FAIL(setpgid(child_pid, getppid()), EACCES);
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
63f08c3bdfSopenharmony_ci}
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_cistatic struct tst_test test = {
66f08c3bdfSopenharmony_ci	.test_all = run,
67f08c3bdfSopenharmony_ci	.forks_child = 1,
68f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
69f08c3bdfSopenharmony_ci};
70