1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 07/2001 Ported by Wayne Boyer 5f08c3bdfSopenharmony_ci * 06/2019 Ported to new library: Christian Amann <camann@suse.com> 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci/* 8f08c3bdfSopenharmony_ci * This test verifies that: 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * 1) lstat(2) returns -1 and sets errno to EACCES if search permission is 11f08c3bdfSopenharmony_ci * denied on a component of the path prefix. 12f08c3bdfSopenharmony_ci * 2) lstat(2) returns -1 and sets errno to ENOENT if the specified file 13f08c3bdfSopenharmony_ci * does not exists or empty string. 14f08c3bdfSopenharmony_ci * 3) lstat(2) returns -1 and sets errno to EFAULT if pathname points 15f08c3bdfSopenharmony_ci * outside user's accessible address space. 16f08c3bdfSopenharmony_ci * 4) lstat(2) returns -1 and sets errno to ENAMETOOLONG if the pathname 17f08c3bdfSopenharmony_ci * component is too long. 18f08c3bdfSopenharmony_ci * 5) lstat(2) returns -1 and sets errno to ENOTDIR if the directory 19f08c3bdfSopenharmony_ci * component in pathname is not a directory. 20f08c3bdfSopenharmony_ci * 6) lstat(2) returns -1 and sets errno to ELOOP if the pathname has too 21f08c3bdfSopenharmony_ci * many symbolic links encountered while traversing. 22f08c3bdfSopenharmony_ci */ 23f08c3bdfSopenharmony_ci 24f08c3bdfSopenharmony_ci#include <errno.h> 25f08c3bdfSopenharmony_ci#include <pwd.h> 26f08c3bdfSopenharmony_ci#include <stdlib.h> 27f08c3bdfSopenharmony_ci#include <string.h> 28f08c3bdfSopenharmony_ci#include <unistd.h> 29f08c3bdfSopenharmony_ci#include <sys/types.h> 30f08c3bdfSopenharmony_ci#include <sys/stat.h> 31f08c3bdfSopenharmony_ci#include "tst_test.h" 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci#define MODE_RWX 0777 34f08c3bdfSopenharmony_ci#define MODE_RW0 0666 35f08c3bdfSopenharmony_ci#define TEST_DIR "test_dir" 36f08c3bdfSopenharmony_ci#define TEST_FILE "test_file" 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci#define TEST_ELOOP "/test_eloop" 39f08c3bdfSopenharmony_ci#define TEST_ENOENT "" 40f08c3bdfSopenharmony_ci#define TEST_EACCES TEST_DIR"/test_eacces" 41f08c3bdfSopenharmony_ci#define TEST_ENOTDIR TEST_FILE"/test_enotdir" 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_cistatic char longpathname[PATH_MAX + 2]; 44f08c3bdfSopenharmony_cistatic char elooppathname[sizeof(TEST_ELOOP) * 43]; 45f08c3bdfSopenharmony_cistatic struct stat stat_buf; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic struct test_case_t { 48f08c3bdfSopenharmony_ci char *pathname; 49f08c3bdfSopenharmony_ci int exp_errno; 50f08c3bdfSopenharmony_ci} test_cases[] = { 51f08c3bdfSopenharmony_ci {TEST_EACCES, EACCES}, 52f08c3bdfSopenharmony_ci {TEST_ENOENT, ENOENT}, 53f08c3bdfSopenharmony_ci {NULL, EFAULT}, 54f08c3bdfSopenharmony_ci {longpathname, ENAMETOOLONG}, 55f08c3bdfSopenharmony_ci {TEST_ENOTDIR, ENOTDIR}, 56f08c3bdfSopenharmony_ci {elooppathname, ELOOP}, 57f08c3bdfSopenharmony_ci}; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_cistatic void run(unsigned int n) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci struct test_case_t *tc = &test_cases[n]; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci TEST(lstat(tc->pathname, &stat_buf)); 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci if (TST_RET != -1) { 66f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "lstat() returned %ld, expected -1", 67f08c3bdfSopenharmony_ci TST_RET); 68f08c3bdfSopenharmony_ci return; 69f08c3bdfSopenharmony_ci } 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci if (tc->exp_errno == TST_ERR) { 72f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "lstat() failed as expected"); 73f08c3bdfSopenharmony_ci } else { 74f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 75f08c3bdfSopenharmony_ci "lstat() failed unexpectedly; expected: %s - got", 76f08c3bdfSopenharmony_ci tst_strerrno(tc->exp_errno)); 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci} 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_cistatic void setup(void) 81f08c3bdfSopenharmony_ci{ 82f08c3bdfSopenharmony_ci int i; 83f08c3bdfSopenharmony_ci struct passwd *ltpuser; 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci /* Drop privileges for EACCES test */ 86f08c3bdfSopenharmony_ci if (geteuid() == 0) { 87f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM("nobody"); 88f08c3bdfSopenharmony_ci SAFE_SETEUID(ltpuser->pw_uid); 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci memset(longpathname, 'a', PATH_MAX+1); 92f08c3bdfSopenharmony_ci longpathname[PATH_MAX+1] = '\0'; 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci SAFE_MKDIR(TEST_DIR, MODE_RWX); 95f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_EACCES, MODE_RWX, NULL); 96f08c3bdfSopenharmony_ci SAFE_TOUCH(TEST_FILE, MODE_RWX, NULL); 97f08c3bdfSopenharmony_ci SAFE_CHMOD(TEST_DIR, MODE_RW0); 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci SAFE_MKDIR("test_eloop", MODE_RWX); 100f08c3bdfSopenharmony_ci SAFE_SYMLINK("../test_eloop", "test_eloop/test_eloop"); 101f08c3bdfSopenharmony_ci /* 102f08c3bdfSopenharmony_ci * NOTE: The ELOOP test is written based on the fact that the 103f08c3bdfSopenharmony_ci * consecutive symlinks limit in the kernel is hardwired to 40. 104f08c3bdfSopenharmony_ci */ 105f08c3bdfSopenharmony_ci elooppathname[0] = '.'; 106f08c3bdfSopenharmony_ci for (i = 0; i < 43; i++) 107f08c3bdfSopenharmony_ci strcat(elooppathname, TEST_ELOOP); 108f08c3bdfSopenharmony_ci} 109f08c3bdfSopenharmony_ci 110f08c3bdfSopenharmony_cistatic void cleanup(void) 111f08c3bdfSopenharmony_ci{ 112f08c3bdfSopenharmony_ci SAFE_CHMOD(TEST_DIR, MODE_RWX); 113f08c3bdfSopenharmony_ci} 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_cistatic struct tst_test test = { 116f08c3bdfSopenharmony_ci .test = run, 117f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(test_cases), 118f08c3bdfSopenharmony_ci .setup = setup, 119f08c3bdfSopenharmony_ci .cleanup = cleanup, 120f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 121f08c3bdfSopenharmony_ci}; 122