1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/* Copyright (c) 2018 FUJITSU LIMITED. All rights reserved.
3f08c3bdfSopenharmony_ci * Authors: Jinhui huang <huangjh.jy@cn.fujitsu.com>
4f08c3bdfSopenharmony_ci */
5f08c3bdfSopenharmony_ci
6f08c3bdfSopenharmony_ci/* Test Description:
7f08c3bdfSopenharmony_ci *  Check various errnos for execveat(2):
8f08c3bdfSopenharmony_ci *    1) execveat() fails and returns EBADF if dirfd is a invalid file
9f08c3bdfSopenharmony_ci *	 descriptor.
10f08c3bdfSopenharmony_ci *    2) execveat() fails and returns EINVAL if flag specified is invalid.
11f08c3bdfSopenharmony_ci *    3) execveat() fails and returns ELOOP if the file identified by dirfd and
12f08c3bdfSopenharmony_ci *       pathname is a symbolic link and flag includes AT_SYMLINK_NOFOLLOW.
13f08c3bdfSopenharmony_ci *    4) execveat() fails and returns ENOTDIR if pathname is relative and dirfd
14f08c3bdfSopenharmony_ci *       is a file descriptor referring to a file other than a directory.
15f08c3bdfSopenharmony_ci */
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#define _GNU_SOURCE
18f08c3bdfSopenharmony_ci#include "config.h"
19f08c3bdfSopenharmony_ci
20f08c3bdfSopenharmony_ci#include <stdio.h>
21f08c3bdfSopenharmony_ci#include <errno.h>
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_ci#include "tst_test.h"
24f08c3bdfSopenharmony_ci#include "lapi/execveat.h"
25f08c3bdfSopenharmony_ci#include "lapi/fcntl.h"
26f08c3bdfSopenharmony_ci#include "execveat.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#define TESTDIR "testdir"
29f08c3bdfSopenharmony_ci#define TEST_APP "execveat_errno"
30f08c3bdfSopenharmony_ci#define TEST_SYMLINK "execveat_symlink"
31f08c3bdfSopenharmony_ci#define TEST_REL_APP TESTDIR"/"TEST_APP
32f08c3bdfSopenharmony_ci#define TEST_ERL_SYMLINK TESTDIR"/"TEST_SYMLINK
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_cistatic int bad_fd = -1, fd;
35f08c3bdfSopenharmony_cistatic char app_abs_path[512], app_sym_path[512];
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_cistatic struct tcase {
38f08c3bdfSopenharmony_ci	int *fd;
39f08c3bdfSopenharmony_ci	char *pathname;
40f08c3bdfSopenharmony_ci	int flag;
41f08c3bdfSopenharmony_ci	int exp_err;
42f08c3bdfSopenharmony_ci} tcases[] = {
43f08c3bdfSopenharmony_ci	{&bad_fd, "", AT_EMPTY_PATH, EBADF},
44f08c3bdfSopenharmony_ci	{&fd, app_abs_path, -1, EINVAL},
45f08c3bdfSopenharmony_ci	{&fd, app_sym_path, AT_SYMLINK_NOFOLLOW, ELOOP},
46f08c3bdfSopenharmony_ci	{&fd, TEST_REL_APP, 0, ENOTDIR},
47f08c3bdfSopenharmony_ci};
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_cistatic void verify_execveat(unsigned int i)
50f08c3bdfSopenharmony_ci{
51f08c3bdfSopenharmony_ci	struct tcase *tc = &tcases[i];
52f08c3bdfSopenharmony_ci	char *argv[2] = {TEST_APP, NULL};
53f08c3bdfSopenharmony_ci	pid_t pid;
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
56f08c3bdfSopenharmony_ci	if (pid == 0) {
57f08c3bdfSopenharmony_ci		TEST(execveat(*tc->fd, tc->pathname, argv, environ, tc->flag));
58f08c3bdfSopenharmony_ci		if (tc->exp_err != TST_ERR) {
59f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
60f08c3bdfSopenharmony_ci				"execveat() fails unexpectedly, expected: %s",
61f08c3bdfSopenharmony_ci				tst_strerrno(tc->exp_err));
62f08c3bdfSopenharmony_ci		} else {
63f08c3bdfSopenharmony_ci			tst_res(TPASS | TTERRNO,
64f08c3bdfSopenharmony_ci				"execveat() fails as expected");
65f08c3bdfSopenharmony_ci		}
66f08c3bdfSopenharmony_ci	}
67f08c3bdfSopenharmony_ci}
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_cistatic void setup(void)
70f08c3bdfSopenharmony_ci{
71f08c3bdfSopenharmony_ci	char cur_dir_path[512];
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	check_execveat();
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	SAFE_MKDIR(TESTDIR, 0777);
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	SAFE_CP(TEST_APP, TEST_REL_APP);
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_ci	SAFE_GETCWD(cur_dir_path, sizeof(cur_dir_path));
80f08c3bdfSopenharmony_ci	sprintf(app_abs_path, "%s/%s", cur_dir_path, TEST_REL_APP);
81f08c3bdfSopenharmony_ci	sprintf(app_sym_path, "%s/%s", cur_dir_path, TEST_ERL_SYMLINK);
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	SAFE_SYMLINK(TEST_REL_APP, TEST_ERL_SYMLINK);
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ci	fd = SAFE_OPEN(TEST_REL_APP, O_PATH);
86f08c3bdfSopenharmony_ci}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_cistatic void cleanup(void)
89f08c3bdfSopenharmony_ci{
90f08c3bdfSopenharmony_ci	if (fd > 0)
91f08c3bdfSopenharmony_ci		SAFE_CLOSE(fd);
92f08c3bdfSopenharmony_ci}
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_cistatic struct tst_test test = {
95f08c3bdfSopenharmony_ci	.resource_files = (const char *const []) {
96f08c3bdfSopenharmony_ci		TEST_APP,
97f08c3bdfSopenharmony_ci		NULL
98f08c3bdfSopenharmony_ci	},
99f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
100f08c3bdfSopenharmony_ci	.test = verify_execveat,
101f08c3bdfSopenharmony_ci	.child_needs_reinit = 1,
102f08c3bdfSopenharmony_ci	.forks_child = 1,
103f08c3bdfSopenharmony_ci	.cleanup = cleanup,
104f08c3bdfSopenharmony_ci	.setup = setup,
105f08c3bdfSopenharmony_ci};
106