1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2018 Linux Test Project
4f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001
5f08c3bdfSopenharmony_ci * Copyright (c) Renaud Lottiaux <Renaud.Lottiaux@kerlabs.com>
6f08c3bdfSopenharmony_ci * Ported to LTP: Wayne Boyer
7f08c3bdfSopenharmony_ci */
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ci/*
10f08c3bdfSopenharmony_ci *	Testcase to check execve sets the following errnos correctly:
11f08c3bdfSopenharmony_ci *	1.	ENAMETOOLONG
12f08c3bdfSopenharmony_ci *	2.	ENOENT
13f08c3bdfSopenharmony_ci *	3.	ENOTDIR
14f08c3bdfSopenharmony_ci *	4.	EFAULT
15f08c3bdfSopenharmony_ci *	5.	EACCES
16f08c3bdfSopenharmony_ci *	6.	ENOEXEC
17f08c3bdfSopenharmony_ci *
18f08c3bdfSopenharmony_ci * ALGORITHM
19f08c3bdfSopenharmony_ci *	1.	Attempt to execve(2) a file whose name is more than
20f08c3bdfSopenharmony_ci *		VFS_MAXNAMLEN fails with ENAMETOOLONG.
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci *	2.	Attempt to execve(2) a file which doesn't exist fails with
23f08c3bdfSopenharmony_ci *		ENOENT.
24f08c3bdfSopenharmony_ci *
25f08c3bdfSopenharmony_ci *	3.	Attempt to execve(2) a pathname (executabl) comprising of a
26f08c3bdfSopenharmony_ci *		directory, which doesn't exist fails with ENOTDIR.
27f08c3bdfSopenharmony_ci *
28f08c3bdfSopenharmony_ci *	4.	Attempt to execve(2) a filename not within the address space
29f08c3bdfSopenharmony_ci *		of the process fails with EFAULT.
30f08c3bdfSopenharmony_ci *
31f08c3bdfSopenharmony_ci *	5.	Attempt to execve(2) a filename that does not have executable
32f08c3bdfSopenharmony_ci *		permission - fails with EACCES.
33f08c3bdfSopenharmony_ci *
34f08c3bdfSopenharmony_ci *	6.	Attempt to execve(2) a zero length file with executable
35f08c3bdfSopenharmony_ci *		permissions - fails with ENOEXEC.
36f08c3bdfSopenharmony_ci */
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#ifndef _GNU_SOURCE
39f08c3bdfSopenharmony_ci#define _GNU_SOURCE
40f08c3bdfSopenharmony_ci#endif
41f08c3bdfSopenharmony_ci#include <sys/types.h>
42f08c3bdfSopenharmony_ci#include <sys/mman.h>
43f08c3bdfSopenharmony_ci#include <sys/stat.h>
44f08c3bdfSopenharmony_ci#include <errno.h>
45f08c3bdfSopenharmony_ci#include <fcntl.h>
46f08c3bdfSopenharmony_ci#include <pwd.h>
47f08c3bdfSopenharmony_ci#include <stdio.h>
48f08c3bdfSopenharmony_ci#include <unistd.h>
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci#include "tst_test.h"
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_cistatic char nobody_uid[] = "nobody";
53f08c3bdfSopenharmony_cistatic struct passwd *ltpuser;
54f08c3bdfSopenharmony_cistatic char long_fname[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz";
55f08c3bdfSopenharmony_cistatic char no_dir[] = "testdir";
56f08c3bdfSopenharmony_cistatic char test_name3[1024];
57f08c3bdfSopenharmony_cistatic char test_name5[1024];
58f08c3bdfSopenharmony_cistatic char test_name6[1024];
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_cistatic struct tcase {
61f08c3bdfSopenharmony_ci	char *tname;
62f08c3bdfSopenharmony_ci	int error;
63f08c3bdfSopenharmony_ci} tcases[] = {
64f08c3bdfSopenharmony_ci	/* the file name is greater than VFS_MAXNAMELEN - ENAMTOOLONG */
65f08c3bdfSopenharmony_ci	{long_fname, ENAMETOOLONG},
66f08c3bdfSopenharmony_ci	/* the filename does not exist - ENOENT */
67f08c3bdfSopenharmony_ci	{no_dir, ENOENT},
68f08c3bdfSopenharmony_ci	/* the path contains a directory name which doesn't exist - ENOTDIR */
69f08c3bdfSopenharmony_ci	{test_name3, ENOTDIR},
70f08c3bdfSopenharmony_ci	/* the filename isn't part of the process address space - EFAULT */
71f08c3bdfSopenharmony_ci	{NULL, EFAULT},
72f08c3bdfSopenharmony_ci	/* the filename does not have execute permission - EACCES */
73f08c3bdfSopenharmony_ci	{test_name5, EACCES},
74f08c3bdfSopenharmony_ci	/* the file is zero length with execute permissions - ENOEXEC */
75f08c3bdfSopenharmony_ci	{test_name6, ENOEXEC}
76f08c3bdfSopenharmony_ci};
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_cistatic void setup(void)
79f08c3bdfSopenharmony_ci{
80f08c3bdfSopenharmony_ci	char *cwdname = NULL;
81f08c3bdfSopenharmony_ci	unsigned i;
82f08c3bdfSopenharmony_ci	int fd;
83f08c3bdfSopenharmony_ci
84f08c3bdfSopenharmony_ci	umask(0);
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	ltpuser = SAFE_GETPWNAM(nobody_uid);
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci	SAFE_SETGID(ltpuser->pw_gid);
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci	cwdname = SAFE_GETCWD(cwdname, 0);
91f08c3bdfSopenharmony_ci
92f08c3bdfSopenharmony_ci	sprintf(test_name5, "%s/fake", cwdname);
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ci	fd = SAFE_CREAT(test_name5, 0444);
95f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	sprintf(test_name3, "%s/fake", test_name5);
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	/* creat() and close a zero length file with executeable permission */
100f08c3bdfSopenharmony_ci	sprintf(test_name6, "%s/execve03", cwdname);
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ci	fd = SAFE_CREAT(test_name6, 0755);
103f08c3bdfSopenharmony_ci	SAFE_CLOSE(fd);
104f08c3bdfSopenharmony_ci
105f08c3bdfSopenharmony_ci	for (i = 0; i < ARRAY_SIZE(tcases); i++) {
106f08c3bdfSopenharmony_ci		if (!tcases[i].tname)
107f08c3bdfSopenharmony_ci			tcases[i].tname = tst_get_bad_addr(NULL);
108f08c3bdfSopenharmony_ci	}
109f08c3bdfSopenharmony_ci}
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_cistatic void verify_execve(unsigned int i)
112f08c3bdfSopenharmony_ci{
113f08c3bdfSopenharmony_ci	struct tcase *tc = &tcases[i];
114f08c3bdfSopenharmony_ci	char *argv[2] = {tc->tname, NULL};
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_ci	TEST(execve(tc->tname, argv, NULL));
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	if (TST_RET != -1) {
119f08c3bdfSopenharmony_ci		tst_res(TFAIL, "call succeeded unexpectedly");
120f08c3bdfSopenharmony_ci		return;
121f08c3bdfSopenharmony_ci	}
122f08c3bdfSopenharmony_ci
123f08c3bdfSopenharmony_ci	if (TST_ERR == tc->error) {
124f08c3bdfSopenharmony_ci		tst_res(TPASS | TTERRNO, "execve failed as expected");
125f08c3bdfSopenharmony_ci		return;
126f08c3bdfSopenharmony_ci	}
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ci	tst_res(TFAIL | TTERRNO, "execve failed unexpectedly; expected %s",
129f08c3bdfSopenharmony_ci		strerror(tc->error));
130f08c3bdfSopenharmony_ci}
131f08c3bdfSopenharmony_ci
132f08c3bdfSopenharmony_cistatic struct tst_test test = {
133f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
134f08c3bdfSopenharmony_ci	.test = verify_execve,
135f08c3bdfSopenharmony_ci	.needs_root = 1,
136f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
137f08c3bdfSopenharmony_ci	.child_needs_reinit = 1,
138f08c3bdfSopenharmony_ci	.setup = setup,
139f08c3bdfSopenharmony_ci};
140