blob: 06b0480260e138c7b836c68678b6c62c323b0d7b [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20/*
21 * NAME
22 * execve02.c
23 *
24 * DESCRIPTION
25 * Testcase to check whether execve(2) sets errno to EACCES correctly
26 *
27 * ALGORITHM
28 * 1. Attempt to execve(2) an executable owned by root with
29 * no execute permissions for the other users, fails when
30 * execve(2) is used as a non-root user (ltpuser1). The errno
31 * should be EACCES.
32 *
33 * USAGE: <for command-line>
34 * execve02 -F <test file> [-c n] [-e] [-i n] [-I x] [-P x] [-t]
35 * where, -c n : Run n copies concurrently.
36 * -e : Turn on errno logging.
37 * -i n : Execute test n times.
38 * -I x : Execute test for x seconds.
39 * -P x : Pause for x seconds between iterations.
40 * -t : Turn on syscall timing.
41 *
42 * HISTORY
43 * 07/2001 Ported by Wayne Boyer
44 *
subrata_modak4374a712008-04-22 06:57:32 +000045 * 21/04/2008 Renaud Lottiaux (Renaud.Lottiaux@kerlabs.com)
46 * - Fix concurrency issue. In case of concurrent executions, all tasks
47 * was using the same file, changing its mode and leading to invalid
48 * mode for some of them.
49 *
plars865695b2001-08-27 22:15:12 +000050 * RESTRICTIONS
51 * Must run test with the -F <test file> option.
52 */
53
54#include <stdio.h>
55#include <unistd.h>
56#include <errno.h>
57#include <pwd.h>
subrata_modak4374a712008-04-22 06:57:32 +000058#include <string.h>
59#include <libgen.h>
robbiewf7dc1be2003-03-14 16:20:37 +000060#include <sys/types.h>
61#include <sys/stat.h>
62#include <sys/wait.h>
plars865695b2001-08-27 22:15:12 +000063#include "test.h"
64#include "usctest.h"
65
66char *TCID = "execve02";
67int TST_TOTAL = 1;
68extern int Tst_count;
69
70void setup(void);
71void cleanup(void);
72void help(void);
73
74int exp_enos[] = {EACCES, 0};
75
76int Fflag = 0;
77char *fname;
78
79/* for test specific parse_opts options - in this case "-F" */
80option_t options[] = {
81 {"F:", &Fflag, &fname},
82 {NULL, NULL, NULL}
83};
84
85char user1name[] = "nobody";
86extern struct passwd * my_getpwnam(char *);
87struct passwd *ltpuser1;
88
robbiewf7dc1be2003-03-14 16:20:37 +000089int
plars865695b2001-08-27 22:15:12 +000090main(int ac, char **av)
91{
92 int lc; /* loop counter */
93 char *msg; /* message returned from parse_opts */
robbiewb851d7b2001-09-14 20:45:29 +000094 int e_code, status, retval=0;
plars865695b2001-08-27 22:15:12 +000095 pid_t pid;
96
97 /* parse standard options */
98 if ((msg = parse_opts(ac, av, options, &help)) != (char *)NULL) {
99 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
100 /*NOTREACHED*/
101 }
102
103 if (!Fflag) {
104 tst_resm(TWARN, "You must specify a test executable with"
105 "the -F option.");
106 tst_resm(TWARN, "Run '%s -h' for option information.", TCID);
107 tst_exit();
108 }
109
110 setup();
111
112 TEST_EXP_ENOS(exp_enos);
113
114 /* check looping state if -i option given */
115 for (lc = 0; TEST_LOOPING(lc); lc++) {
116
117 /* reset Tst_count in case we are looping */
118 Tst_count = 0;
119
120 if (chmod(fname, 0700) != 0) {
121 tst_resm(TFAIL, "Failed to change permissions of "
122 "test file");
123 }
124
robbiewd34d5812005-07-11 22:28:09 +0000125 if ((pid = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000126 tst_brkm(TBROK, cleanup, "fork() failed");
127 }
128
129 if (pid == 0) { /* child */
130 if (seteuid(ltpuser1->pw_uid) == -1) {
131 tst_brkm(TBROK, cleanup, "setuid() failed");
132 }
133
134 TEST(execve(fname, NULL, NULL));
135
136 TEST_ERROR_LOG(TEST_ERRNO);
137
138 if (TEST_ERRNO != EACCES) {
robbiewb079c392001-09-17 18:37:12 +0000139 retval=1;
plars865695b2001-08-27 22:15:12 +0000140 tst_resm(TFAIL, "Expected EACCES got %d",
141 TEST_ERRNO);
142 } else {
143 tst_resm(TPASS, "Received EACCES");
144 }
145
146 /* change back to root */
147 if (seteuid(0) == -1) {
148 tst_brkm(TBROK, cleanup, "setuid(0) failed");
149 }
150
151 /* reset the file permissions */
152 if (chmod(fname, 0755) == -1) {
153 tst_brkm(TBROK, cleanup, "chmod() #2 failed");
154 }
plarsda858742002-09-25 17:34:14 +0000155 exit(retval);
plars865695b2001-08-27 22:15:12 +0000156 } else {
robbiewb851d7b2001-09-14 20:45:29 +0000157 /* wait for the child to finish */
158 wait(&status);
159 /* make sure the child returned a good exit status */
160 e_code = status >> 8;
161 if ((e_code != 0) || (retval != 0)) {
162 tst_resm(TFAIL, "Failures reported above");
163 }
164
165 cleanup();
plars865695b2001-08-27 22:15:12 +0000166 }
167 }
plars865695b2001-08-27 22:15:12 +0000168
169 /*NOTREACHED*/
robbiewf9cb9162003-03-25 18:49:24 +0000170 return(0);
plars865695b2001-08-27 22:15:12 +0000171}
172
173/*
174 * help() - Prints out the help message for the -F option defined
175 * by this test.
176 */
177void
178help()
179{
180 printf(" -F <test file> : for example, 'execve02 -F test3'\n");
181}
182
183/*
184 * setup() - performs all ONE TIME setup for this test.
185 */
186void
187setup()
188{
subrata_modak4374a712008-04-22 06:57:32 +0000189 char *cmd, *dirc, *basec, *bname, *dname, *path, *pwd = NULL;
190 int res;
191
plars865695b2001-08-27 22:15:12 +0000192 if (geteuid() != 0) {
193 tst_brkm(TBROK, tst_exit, "Test must be run as root");
194 }
195
196 /* capture signals */
197 tst_sig(FORK, DEF_HANDLER, cleanup);
198
199 /* Pause if that option was specified */
200 TEST_PAUSE;
201
subrata_modak4374a712008-04-22 06:57:32 +0000202 /* Get file name of the passed test file and the absolute path to it.
203 * We will need these informations to copy the test file in the temp
204 * directory.
205 */
206 dirc = strdup(fname);
207 basec = strdup(fname);
208 dname = dirname(dirc);
209 bname = basename(basec);
210
211 if (dname[0] == '/')
212 path = dname;
213 else {
214 if ((pwd = getcwd(NULL, 0)) == NULL) {
215 tst_brkm(TBROK, tst_exit, "Could not get current directory");
216 }
217 path = malloc (strlen(path) + strlen(pwd) + 2);
218 if (path == NULL) {
219 tst_brkm(TBROK, tst_exit, "Cannot alloc path string");
220 }
221 sprintf (path, "%s/%s", pwd, dname);
222 }
223
224 /* make a temp dir and cd to it */
225 tst_tmpdir();
226
227 /* Copy the given test file to the private temp directory.
228 */
229 cmd = malloc (strlen(path) + strlen(bname) + 15);
230 if (cmd == NULL) {
231 tst_brkm(TBROK, tst_exit, "Cannot alloc command string");
232 }
233
234 sprintf (cmd, "cp -p %s/%s .", path, bname);
235 res = system (cmd);
236 free (cmd);
237 if (res == -1) {
238 tst_brkm(TBROK, tst_exit, "Cannot copy file %s", fname);
239 }
240
241 fname = bname;
242
plars865695b2001-08-27 22:15:12 +0000243 umask(0);
244
245 ltpuser1 = my_getpwnam(user1name);
246}
247
248/*
249 * cleanup() - performs all ONE TIME cleanup for this test at
250 * completion or premature exit.
251 */
252void
253cleanup()
254{
255 /*
256 * print timing stats if that option was specified.
257 * print errno log if that option was specified.
258 */
259 TEST_CLEANUP;
260
subrata_modak4374a712008-04-22 06:57:32 +0000261 /* remove files and temp dir */
262 tst_rmdir();
263
264
plars865695b2001-08-27 22:15:12 +0000265 /* exit with return code appropriate for results */
266 tst_exit();
267}