1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2018 Linux Test Project 4f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 5f08c3bdfSopenharmony_ci * Copyright (c) Renaud Lottiaux <Renaud.Lottiaux@kerlabs.com> 6f08c3bdfSopenharmony_ci * Ported to LTP: Wayne Boyer 7f08c3bdfSopenharmony_ci */ 8f08c3bdfSopenharmony_ci 9f08c3bdfSopenharmony_ci/* 10f08c3bdfSopenharmony_ci * Testcase to check execve sets the following errnos correctly: 11f08c3bdfSopenharmony_ci * 1. ENAMETOOLONG 12f08c3bdfSopenharmony_ci * 2. ENOENT 13f08c3bdfSopenharmony_ci * 3. ENOTDIR 14f08c3bdfSopenharmony_ci * 4. EFAULT 15f08c3bdfSopenharmony_ci * 5. EACCES 16f08c3bdfSopenharmony_ci * 6. ENOEXEC 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * ALGORITHM 19f08c3bdfSopenharmony_ci * 1. Attempt to execve(2) a file whose name is more than 20f08c3bdfSopenharmony_ci * VFS_MAXNAMLEN fails with ENAMETOOLONG. 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * 2. Attempt to execve(2) a file which doesn't exist fails with 23f08c3bdfSopenharmony_ci * ENOENT. 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * 3. Attempt to execve(2) a pathname (executabl) comprising of a 26f08c3bdfSopenharmony_ci * directory, which doesn't exist fails with ENOTDIR. 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * 4. Attempt to execve(2) a filename not within the address space 29f08c3bdfSopenharmony_ci * of the process fails with EFAULT. 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * 5. Attempt to execve(2) a filename that does not have executable 32f08c3bdfSopenharmony_ci * permission - fails with EACCES. 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci * 6. Attempt to execve(2) a zero length file with executable 35f08c3bdfSopenharmony_ci * permissions - fails with ENOEXEC. 36f08c3bdfSopenharmony_ci */ 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci#ifndef _GNU_SOURCE 39f08c3bdfSopenharmony_ci#define _GNU_SOURCE 40f08c3bdfSopenharmony_ci#endif 41f08c3bdfSopenharmony_ci#include <sys/types.h> 42f08c3bdfSopenharmony_ci#include <sys/mman.h> 43f08c3bdfSopenharmony_ci#include <sys/stat.h> 44f08c3bdfSopenharmony_ci#include <errno.h> 45f08c3bdfSopenharmony_ci#include <fcntl.h> 46f08c3bdfSopenharmony_ci#include <pwd.h> 47f08c3bdfSopenharmony_ci#include <stdio.h> 48f08c3bdfSopenharmony_ci#include <unistd.h> 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci#include "tst_test.h" 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_cistatic char nobody_uid[] = "nobody"; 53f08c3bdfSopenharmony_cistatic struct passwd *ltpuser; 54f08c3bdfSopenharmony_cistatic char long_fname[] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyzabcdefghijklmnopqrstmnopqrstuvwxyz"; 55f08c3bdfSopenharmony_cistatic char no_dir[] = "testdir"; 56f08c3bdfSopenharmony_cistatic char test_name3[1024]; 57f08c3bdfSopenharmony_cistatic char test_name5[1024]; 58f08c3bdfSopenharmony_cistatic char test_name6[1024]; 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic struct tcase { 61f08c3bdfSopenharmony_ci char *tname; 62f08c3bdfSopenharmony_ci int error; 63f08c3bdfSopenharmony_ci} tcases[] = { 64f08c3bdfSopenharmony_ci /* the file name is greater than VFS_MAXNAMELEN - ENAMTOOLONG */ 65f08c3bdfSopenharmony_ci {long_fname, ENAMETOOLONG}, 66f08c3bdfSopenharmony_ci /* the filename does not exist - ENOENT */ 67f08c3bdfSopenharmony_ci {no_dir, ENOENT}, 68f08c3bdfSopenharmony_ci /* the path contains a directory name which doesn't exist - ENOTDIR */ 69f08c3bdfSopenharmony_ci {test_name3, ENOTDIR}, 70f08c3bdfSopenharmony_ci /* the filename isn't part of the process address space - EFAULT */ 71f08c3bdfSopenharmony_ci {NULL, EFAULT}, 72f08c3bdfSopenharmony_ci /* the filename does not have execute permission - EACCES */ 73f08c3bdfSopenharmony_ci {test_name5, EACCES}, 74f08c3bdfSopenharmony_ci /* the file is zero length with execute permissions - ENOEXEC */ 75f08c3bdfSopenharmony_ci {test_name6, ENOEXEC} 76f08c3bdfSopenharmony_ci}; 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_cistatic void setup(void) 79f08c3bdfSopenharmony_ci{ 80f08c3bdfSopenharmony_ci char *cwdname = NULL; 81f08c3bdfSopenharmony_ci unsigned i; 82f08c3bdfSopenharmony_ci int fd; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci umask(0); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM(nobody_uid); 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_ci SAFE_SETGID(ltpuser->pw_gid); 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci cwdname = SAFE_GETCWD(cwdname, 0); 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci sprintf(test_name5, "%s/fake", cwdname); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci fd = SAFE_CREAT(test_name5, 0444); 95f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci sprintf(test_name3, "%s/fake", test_name5); 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci /* creat() and close a zero length file with executeable permission */ 100f08c3bdfSopenharmony_ci sprintf(test_name6, "%s/execve03", cwdname); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci fd = SAFE_CREAT(test_name6, 0755); 103f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(tcases); i++) { 106f08c3bdfSopenharmony_ci if (!tcases[i].tname) 107f08c3bdfSopenharmony_ci tcases[i].tname = tst_get_bad_addr(NULL); 108f08c3bdfSopenharmony_ci } 109f08c3bdfSopenharmony_ci} 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_cistatic void verify_execve(unsigned int i) 112f08c3bdfSopenharmony_ci{ 113f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[i]; 114f08c3bdfSopenharmony_ci char *argv[2] = {tc->tname, NULL}; 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci TEST(execve(tc->tname, argv, NULL)); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci if (TST_RET != -1) { 119f08c3bdfSopenharmony_ci tst_res(TFAIL, "call succeeded unexpectedly"); 120f08c3bdfSopenharmony_ci return; 121f08c3bdfSopenharmony_ci } 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci if (TST_ERR == tc->error) { 124f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "execve failed as expected"); 125f08c3bdfSopenharmony_ci return; 126f08c3bdfSopenharmony_ci } 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "execve failed unexpectedly; expected %s", 129f08c3bdfSopenharmony_ci strerror(tc->error)); 130f08c3bdfSopenharmony_ci} 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_cistatic struct tst_test test = { 133f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 134f08c3bdfSopenharmony_ci .test = verify_execve, 135f08c3bdfSopenharmony_ci .needs_root = 1, 136f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 137f08c3bdfSopenharmony_ci .child_needs_reinit = 1, 138f08c3bdfSopenharmony_ci .setup = setup, 139f08c3bdfSopenharmony_ci}; 140