1 /*
2  * Copyright (c) International Business Machines  Corp., 2001
3  * Copyright (c) 2015 Cyril Hrubis <chrubis@suse.cz>
4  *
5  *  07/2001 Ported by Wayne Boyer
6  *  04/2008 Roy Lee <roylee@andestech.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
16  * the 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, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 /*
24  * Attempt to execve(2) a file which is being opened by another process for
25  * writing fails with ETXTBSY.
26  */
27 
28 #ifndef _GNU_SOURCE
29 #define _GNU_SOURCE
30 #endif
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <libgen.h>
36 #include <stdio.h>
37 
38 #include "test.h"
39 #include "safe_macros.h"
40 
41 #define TEST_APP "execve_child"
42 
43 char *TCID = "execve04";
44 int TST_TOTAL = 1;
45 
46 static void setup(void);
47 static void cleanup(void);
48 static void do_child(void);
49 
main(int ac,char ** av)50 int main(int ac, char **av)
51 {
52 	int lc;
53 	pid_t pid;
54 	char *argv[2] = {TEST_APP, NULL};
55 	char *env[1] = {NULL};
56 
57 	tst_parse_opts(ac, av, NULL, NULL);
58 
59 #ifdef UCLINUX
60 	maybe_run_child(&do_child, "");
61 #endif
62 
63 	setup();
64 
65 	for (lc = 0; TEST_LOOPING(lc); lc++) {
66 		if ((pid = FORK_OR_VFORK()) == -1) {
67 			tst_brkm(TBROK, cleanup, "fork failed");
68 		} else if (pid == 0) {
69 #ifdef UCLINUX
70 			if (self_exec(av[0], "") < 0)
71 				tst_brkm(TBROK, cleanup, "self_exec failed");
72 #else
73 			do_child();
74 #endif
75 		}
76 
77 		TST_SAFE_CHECKPOINT_WAIT(cleanup, 0);
78 
79 		TEST(execve(TEST_APP, argv, env));
80 
81 		if (TEST_ERRNO != ETXTBSY)
82 			tst_resm(TFAIL | TTERRNO, "execve succeeded, expected failure");
83 		else
84 			tst_resm(TPASS | TTERRNO, "execve failed as expected");
85 
86 		TST_SAFE_CHECKPOINT_WAKE(cleanup, 0);
87 		SAFE_WAIT(cleanup, NULL);
88 	}
89 
90 	cleanup();
91 	tst_exit();
92 }
93 
setup(void)94 void setup(void)
95 {
96 	char path[PATH_MAX];
97 
98 	if (tst_get_path(TEST_APP, path, sizeof(path))) {
99 		tst_brkm(TBROK, NULL,
100 		         "Couldn't found "TEST_APP" binary in $PATH");
101 	}
102 
103 	tst_tmpdir();
104 
105 	TST_CHECKPOINT_INIT(tst_rmdir);
106 
107 	SAFE_CP(tst_rmdir, path, ".");
108 }
109 
cleanup(void)110 static void cleanup(void)
111 {
112 	tst_rmdir();
113 }
114 
do_child(void)115 static void do_child(void)
116 {
117 	int fd;
118 
119 #ifdef UCLINUX
120 	TST_CHECKPOINT_INIT(NULL);
121 #endif
122 
123 	if ((fd = open(TEST_APP, O_WRONLY)) == -1) {
124 		perror("open failed");
125 		exit(1);
126 	}
127 
128 	TST_SAFE_CHECKPOINT_WAKE_AND_WAIT(NULL, 0);
129 
130 	exit(0);
131 }
132