• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2018 Linux Test Project
3  * Copyright (c) International Business Machines  Corp., 2001
4  *
5  *  07/2001 Ported by Wayne Boyer
6  *  21/04/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 /*
23  * NAME
24  *	execve03.c
25  *
26  * DESCRIPTION
27  *	Testcase to check execve sets the following errnos correctly:
28  *	1.	ENAMETOOLONG
29  *	2.	ENOENT
30  *	3.	ENOTDIR
31  *	4.	EFAULT
32  *	5.	EACCES
33  *	6.	ENOEXEC
34  *
35  * ALGORITHM
36  *	1.	Attempt to execve(2) a file whose name is more than
37  *		VFS_MAXNAMLEN fails with ENAMETOOLONG.
38  *
39  *	2.	Attempt to execve(2) a file which doesn't exist fails with
40  *		ENOENT.
41  *
42  *	3.	Attempt to execve(2) a pathname (executabl) comprising of a
43  *		directory, which doesn't exist fails with ENOTDIR.
44  *
45  *	4.	Attempt to execve(2) a filename not within the address space
46  *		of the process fails with EFAULT.
47  *
48  *	5.	Attempt to execve(2) a filename that does not have executable
49  *		permission - fails with EACCES.
50  *
51  *	6.	Attempt to execve(2) a zero length file with executable
52  *		permissions - fails with ENOEXEC.
53  *
54  * HISTORY
55  *	07/2001 Ported by Wayne Boyer
56  */
57 
58 #ifndef _GNU_SOURCE
59 #define _GNU_SOURCE
60 #endif
61 #include <sys/types.h>
62 #include <sys/mman.h>
63 #include <sys/stat.h>
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <pwd.h>
67 #include <stdio.h>
68 #include <unistd.h>
69 
70 #include "tst_test.h"
71 
72 static char nobody_uid[] = "nobody";
73 static struct passwd *ltpuser;
74 static char long_fname[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz";
75 static char no_dir[] = "testdir";
76 static char test_name3[1024];
77 static char test_name5[1024];
78 static char test_name6[1024];
79 
80 static struct tcase {
81 	char *tname;
82 	int error;
83 } tcases[] = {
84 	/* the file name is greater than VFS_MAXNAMELEN - ENAMTOOLONG */
85 	{long_fname, ENAMETOOLONG},
86 	/* the filename does not exist - ENOENT */
87 	{no_dir, ENOENT},
88 	/* the path contains a directory name which doesn't exist - ENOTDIR */
89 	{test_name3, ENOTDIR},
90 	/* the filename isn't part of the process address space - EFAULT */
91 	{NULL, EFAULT},
92 	/* the filename does not have execute permission - EACCES */
93 	{test_name5, EACCES},
94 	/* the file is zero length with execute permissions - ENOEXEC */
95 	{test_name6, ENOEXEC}
96 };
97 
setup(void)98 static void setup(void)
99 {
100 	char *cwdname = NULL;
101 	unsigned i;
102 	int fd;
103 
104 	umask(0);
105 
106 	ltpuser = SAFE_GETPWNAM(nobody_uid);
107 
108 	SAFE_SETGID(ltpuser->pw_gid);
109 
110 	cwdname = SAFE_GETCWD(cwdname, 0);
111 
112 	sprintf(test_name5, "%s/fake", cwdname);
113 
114 	fd = SAFE_CREAT(test_name5, 0444);
115 	SAFE_CLOSE(fd);
116 
117 	sprintf(test_name3, "%s/fake", test_name5);
118 
119 	/* creat() and close a zero length file with executeable permission */
120 	sprintf(test_name6, "%s/execve03", cwdname);
121 
122 	fd = SAFE_CREAT(test_name6, 0755);
123 	SAFE_CLOSE(fd);
124 
125 	for (i = 0; i < ARRAY_SIZE(tcases); i++) {
126 		if (!tcases[i].tname)
127 			tcases[i].tname = tst_get_bad_addr(NULL);
128 	}
129 }
130 
verify_execve(unsigned int i)131 static void verify_execve(unsigned int i)
132 {
133 	struct tcase *tc = &tcases[i];
134 	char *argv[2] = {tc->tname, NULL};
135 
136 	TEST(execve(tc->tname, argv, NULL));
137 
138 	if (TST_RET != -1) {
139 		tst_res(TFAIL, "call succeeded unexpectedly");
140 		return;
141 	}
142 
143 	if (TST_ERR == tc->error) {
144 		tst_res(TPASS | TTERRNO, "execve failed as expected");
145 		return;
146 	}
147 
148 	tst_res(TFAIL | TTERRNO, "execve failed unexpectedly; expected %s",
149 		strerror(tc->error));
150 }
151 
152 static struct tst_test test = {
153 	.tcnt = ARRAY_SIZE(tcases),
154 	.test = verify_execve,
155 	.needs_root = 1,
156 	.needs_tmpdir = 1,
157 	.child_needs_reinit = 1,
158 	.setup = setup,
159 };
160