blob: cc8c86188081a6c8c360d1137b296e251307b10d [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
subrata_modake7899782009-05-27 13:36:34 +00003 * Copyright (c) International Business Machines Corp., 2001
plars865695b2001-08-27 22:15:12 +00004 *
subrata_modake7899782009-05-27 13:36:34 +00005 * 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.
plars865695b2001-08-27 22:15:12 +00009 *
subrata_modake7899782009-05-27 13:36:34 +000010 * 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.
plars865695b2001-08-27 22:15:12 +000014 *
subrata_modake7899782009-05-27 13:36:34 +000015 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * NAME
subrata_modake7899782009-05-27 13:36:34 +000022 * execve04.c
plars865695b2001-08-27 22:15:12 +000023 *
24 * DESCRIPTION
subrata_modake7899782009-05-27 13:36:34 +000025 * Testcase to check execve sets the following errnos correctly:
26 * 1. ETXTBSY
plars865695b2001-08-27 22:15:12 +000027 *
28 * ALGORITHM
subrata_modake7899782009-05-27 13:36:34 +000029 * 1. Attempt to execve(2) a file which is being opened by another
30 * process for writing fails with ETXTBSY.
plars865695b2001-08-27 22:15:12 +000031 *
32 * USAGE: <for command-line>
33 * execve04 -F <test file> [-c n] [-e] [-i n] [-I x] [-P x] [-t]
subrata_modake7899782009-05-27 13:36:34 +000034 * where, -c n : Run n copies concurrently.
35 * -e : Turn on errno logging.
36 * -i n : Execute test n times.
37 * -I x : Execute test for x seconds.
38 * -P x : Pause for x seconds between iterations.
39 * -t : Turn on syscall timing.
plars865695b2001-08-27 22:15:12 +000040 *
41 * HISTORY
42 * 07/2001 Ported by Wayne Boyer
subrata_modake7899782009-05-27 13:36:34 +000043 * 04/2008 Roy Lee <roylee@andestech.com>
44 * - Fix a synchronization issue.
45 * On a loaded system, the 'execving' child can get access
46 * to the file before the 'opening' child does, hence results
47 * in an unexpected opening fail.
plars865695b2001-08-27 22:15:12 +000048 *
49 * RESTRICTIONS
subrata_modake7899782009-05-27 13:36:34 +000050 * must be run with -F <test file> option
plars865695b2001-08-27 22:15:12 +000051 */
52
Garrett Cooperc585a272010-12-20 03:04:07 -080053#ifndef _GNU_SOURCE
54#define _GNU_SOURCE
55#endif
subrata_modake7899782009-05-27 13:36:34 +000056#include <sys/types.h>
57#include <sys/wait.h>
Garrett Cooperc585a272010-12-20 03:04:07 -080058#include <errno.h>
59#include <fcntl.h>
subrata_modake7899782009-05-27 13:36:34 +000060#include <libgen.h>
Garrett Cooperc585a272010-12-20 03:04:07 -080061#include <stdio.h>
62
subrata_modake7899782009-05-27 13:36:34 +000063#include "test.h"
subrata_modake7899782009-05-27 13:36:34 +000064#include "libtestsuite.h"
plars865695b2001-08-27 22:15:12 +000065
Garrett Cooperc585a272010-12-20 03:04:07 -080066char *test_app;
plars865695b2001-08-27 22:15:12 +000067char *TCID = "execve04";
68int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000069
Garrett Cooper775c33d2010-12-20 01:57:37 -080070void setup(char *);
plars865695b2001-08-27 22:15:12 +000071void cleanup(void);
72void help(void);
subrata_modake7899782009-05-27 13:36:34 +000073void do_child_1(void);
74void do_child_2(void);
plars865695b2001-08-27 22:15:12 +000075
subrata_modake7899782009-05-27 13:36:34 +000076int start_sync_pipes[2];
77int end_sync_pipes[2];
plars865695b2001-08-27 22:15:12 +000078
79int Fflag = 0;
subrata_modake7899782009-05-27 13:36:34 +000080
81#ifdef UCLINUX
82#define PIPE_NAME_START "execve04_start"
83#define PIPE_NAME_END "execve04_end"
84#else
85#define PIPE_NAME_START NULL
86#define PIPE_NAME_END NULL
87#endif
plars865695b2001-08-27 22:15:12 +000088
plars865695b2001-08-27 22:15:12 +000089option_t options[] = {
Garrett Cooperc585a272010-12-20 03:04:07 -080090 {"F:", &Fflag, &test_app},
plars865695b2001-08-27 22:15:12 +000091 {NULL, NULL, NULL}
92};
93
subrata_modak56207ce2009-03-23 13:35:39 +000094int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000095{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020096 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020097 const char *msg;
subrata_modake7899782009-05-27 13:36:34 +000098 pid_t pid, pid1;
Garrett Cooper775c33d2010-12-20 01:57:37 -080099 int retval = 3, status;
subrata_modake7899782009-05-27 13:36:34 +0000100 char *argv[1], *env[1];
plars865695b2001-08-27 22:15:12 +0000101
Garrett Cooper775c33d2010-12-20 01:57:37 -0800102 if ((msg = parse_opts(ac, av, options, &help)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800103 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modake7899782009-05-27 13:36:34 +0000104#ifdef UCLINUX
Garrett Cooperc585a272010-12-20 03:04:07 -0800105 maybe_run_child(&do_child_1, "nS", 1, &test_app);
subrata_modake7899782009-05-27 13:36:34 +0000106#endif
plars865695b2001-08-27 22:15:12 +0000107
Garrett Cooper775c33d2010-12-20 01:57:37 -0800108 if (!Fflag)
109 tst_brkm(TBROK, NULL,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800110 "You must specify an executable file with the -F option.");
plars865695b2001-08-27 22:15:12 +0000111
Garrett Cooper775c33d2010-12-20 01:57:37 -0800112 setup(*av);
plars865695b2001-08-27 22:15:12 +0000113
plars865695b2001-08-27 22:15:12 +0000114 for (lc = 0; TEST_LOOPING(lc); lc++) {
115
Caspar Zhangd59a6592013-03-07 14:59:12 +0800116 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000117
subrata_modake7899782009-05-27 13:36:34 +0000118 if (sync_pipe_create(start_sync_pipes, PIPE_NAME_START) == -1)
119 tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
120 if (sync_pipe_create(end_sync_pipes, PIPE_NAME_END) == -1)
121 tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
plars865695b2001-08-27 22:15:12 +0000122
subrata_modake7899782009-05-27 13:36:34 +0000123 /*
124 * to test whether execve(2) sets ETXTBSY when a second
125 * child process attempts to execve the executable opened
126 * by the first child process
127 */
Garrett Cooper775c33d2010-12-20 01:57:37 -0800128 if ((pid = FORK_OR_VFORK()) == -1)
subrata_modake7899782009-05-27 13:36:34 +0000129 tst_brkm(TBROK, cleanup, "fork #1 failed");
Garrett Cooper775c33d2010-12-20 01:57:37 -0800130 else if (pid == 0) {
subrata_modake7899782009-05-27 13:36:34 +0000131#ifdef UCLINUX
Garrett Cooperc585a272010-12-20 03:04:07 -0800132 if (self_exec(av[0], "nS", 1, test_app) < 0)
subrata_modake7899782009-05-27 13:36:34 +0000133 tst_brkm(TBROK, cleanup, "self_exec failed");
subrata_modake7899782009-05-27 13:36:34 +0000134#else
135 do_child_1();
136#endif
137 }
plars865695b2001-08-27 22:15:12 +0000138
subrata_modake7899782009-05-27 13:36:34 +0000139 if (sync_pipe_wait(start_sync_pipes) == -1)
140 tst_brkm(TBROK, cleanup, "sync_pipe_wait failed");
141
142 if (sync_pipe_close(start_sync_pipes, PIPE_NAME_START) == -1)
143 tst_brkm(TBROK, cleanup, "sync_pipe_close failed");
144
145 if ((pid1 = FORK_OR_VFORK()) == -1)
146 tst_brkm(TBROK, cleanup, "fork #2 failed");
147
Garrett Cooper775c33d2010-12-20 01:57:37 -0800148 if (pid1 == 0) {
Garrett Cooperc585a272010-12-20 03:04:07 -0800149
150 retval = 3;
151
subrata_modake7899782009-05-27 13:36:34 +0000152 argv[0] = 0;
153 env[0] = 0;
154
155 /* do not interfere with end synchronization of first
156 * child */
157 sync_pipe_close(end_sync_pipes, PIPE_NAME_END);
158
Garrett Cooperc585a272010-12-20 03:04:07 -0800159 TEST(execve(test_app, argv, env));
subrata_modake7899782009-05-27 13:36:34 +0000160
subrata_modake7899782009-05-27 13:36:34 +0000161 if (TEST_ERRNO != ETXTBSY) {
162 retval = 1;
Garrett Cooperc585a272010-12-20 03:04:07 -0800163 perror("didn't get ETXTBSY\n");
164 } else
165 printf("execve failed with ETXTBSY as "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 "expected\n");
subrata_modake7899782009-05-27 13:36:34 +0000167 exit(retval);
subrata_modake7899782009-05-27 13:36:34 +0000168 }
Garrett Cooper775c33d2010-12-20 01:57:37 -0800169 /* wait for the child to finish */
Garrett Cooperc585a272010-12-20 03:04:07 -0800170 if (waitpid(pid1, &status, 0) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800171 tst_brkm(TBROK | TERRNO, cleanup, "waitpid failed");
Garrett Cooper775c33d2010-12-20 01:57:37 -0800172 if (WIFEXITED(status) && WEXITSTATUS(status) == 3)
Garrett Cooperc585a272010-12-20 03:04:07 -0800173 tst_resm(TPASS, "execve failed as expected");
Garrett Cooper775c33d2010-12-20 01:57:37 -0800174 else
175 tst_resm(TFAIL, "execve succeeded, expected failure");
176
177 /* terminate first child */
178 sync_pipe_notify(end_sync_pipes);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800179 (void)waitpid(pid, NULL, 0);
subrata_modake7899782009-05-27 13:36:34 +0000180 }
Garrett Cooperc585a272010-12-20 03:04:07 -0800181 cleanup();
subrata_modake7899782009-05-27 13:36:34 +0000182
Garrett Cooper53740502010-12-16 00:04:01 -0800183 tst_exit();
plars865695b2001-08-27 22:15:12 +0000184}
185
Mike Frysingerc57fba52014-04-09 18:56:30 -0400186void help(void)
plars865695b2001-08-27 22:15:12 +0000187{
subrata_modake7899782009-05-27 13:36:34 +0000188 printf(" -F <test name> : for example, 'execve04 -F test3'\n");
plars865695b2001-08-27 22:15:12 +0000189}
190
Garrett Cooper775c33d2010-12-20 01:57:37 -0800191void setup(char *argv0)
plars865695b2001-08-27 22:15:12 +0000192{
Garrett Cooper775c33d2010-12-20 01:57:37 -0800193 char *cmd, *pwd = NULL;
Garrett Cooperc585a272010-12-20 03:04:07 -0800194 char test_path[MAXPATHLEN];
Garrett Cooper775c33d2010-12-20 01:57:37 -0800195
Garrett Cooperc585a272010-12-20 03:04:07 -0800196 if (test_app[0] == '/')
197 strncpy(test_path, test_app, sizeof(test_path));
198 else {
199 if ((pwd = get_current_dir_name()) == NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800200 tst_brkm(TBROK | TERRNO, NULL, "getcwd failed");
Garrett Cooper775c33d2010-12-20 01:57:37 -0800201
Garrett Cooperc585a272010-12-20 03:04:07 -0800202 snprintf(test_path, sizeof(test_path), "%s/%s",
Wanlong Gao354ebb42012-12-07 10:10:04 +0800203 pwd, basename(test_app));
Garrett Cooper775c33d2010-12-20 01:57:37 -0800204
Garrett Cooperc585a272010-12-20 03:04:07 -0800205 free(pwd);
206 }
207
Cyril Hrubisd218f342014-09-23 13:14:56 +0200208 cmd = malloc(strlen(test_path) + strlen("cp -p \"") + strlen("\" .") + 1);
Garrett Cooper775c33d2010-12-20 01:57:37 -0800209 if (cmd == NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800210 tst_brkm(TBROK | TERRNO, NULL, "Cannot alloc command string");
plars865695b2001-08-27 22:15:12 +0000211
subrata_modak635f2a42008-11-11 06:17:04 +0000212 tst_sig(FORK, DEF_HANDLER, cleanup);
plars865695b2001-08-27 22:15:12 +0000213
plars865695b2001-08-27 22:15:12 +0000214 tst_tmpdir();
215
Garrett Cooperc585a272010-12-20 03:04:07 -0800216 sprintf(cmd, "cp -p \"%s\" .", test_path);
Garrett Cooper775c33d2010-12-20 01:57:37 -0800217 if (system(cmd) != 0)
Garrett Cooperc585a272010-12-20 03:04:07 -0800218 tst_brkm(TBROK, NULL, "command failed: %s", cmd);
subrata_modake7899782009-05-27 13:36:34 +0000219 free(cmd);
plars865695b2001-08-27 22:15:12 +0000220}
221
Mike Frysingerc57fba52014-04-09 18:56:30 -0400222void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000223{
plars865695b2001-08-27 22:15:12 +0000224 tst_rmdir();
225
plars865695b2001-08-27 22:15:12 +0000226}
subrata_modake7899782009-05-27 13:36:34 +0000227
Mike Frysingerc57fba52014-04-09 18:56:30 -0400228void do_child_1(void)
subrata_modake7899782009-05-27 13:36:34 +0000229{
230 int fildes;
231
232#ifdef UCLINUX
233 if (sync_pipe_create(start_sync_pipes, PIPE_NAME_START) == -1)
234 tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
235 if (sync_pipe_create(end_sync_pipes, PIPE_NAME_END) == -1)
236 tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
237#endif
238
Garrett Cooperc585a272010-12-20 03:04:07 -0800239 if ((fildes = open(test_app, O_WRONLY)) == -1) {
240 printf("%s\n", test_app);
Garrett Cooper775c33d2010-12-20 01:57:37 -0800241 perror("open failed");
subrata_modake7899782009-05-27 13:36:34 +0000242 exit(1);
243 }
244
245 if (sync_pipe_notify(start_sync_pipes) == -1) {
Garrett Cooper775c33d2010-12-20 01:57:37 -0800246 perror("sync_pipe_notify failed");
subrata_modake7899782009-05-27 13:36:34 +0000247 exit(1);
248 }
249
250 if (sync_pipe_close(start_sync_pipes, PIPE_NAME_START) == -1) {
Garrett Cooper775c33d2010-12-20 01:57:37 -0800251 perror("sync_pipe_close failed");
subrata_modake7899782009-05-27 13:36:34 +0000252 exit(1);
253 }
254
subrata_modake7899782009-05-27 13:36:34 +0000255 if (sync_pipe_wait(end_sync_pipes) == -1) {
Garrett Cooper775c33d2010-12-20 01:57:37 -0800256 perror("sync_pipe_wait failed");
subrata_modake7899782009-05-27 13:36:34 +0000257 exit(1);
258 }
259 exit(0);
Garrett Cooper775c33d2010-12-20 01:57:37 -0800260}