Home | History | Annotate | Download | only in execve
      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 (at) 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 
     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 
    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