1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 07/2001 Ported by Wayne Boyer 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * 23 * Test Description: 24 * Verify that, 25 * 1) mknod(2) returns -1 and sets errno to EPERM if the process id of 26 * the caller is not super-user. 27 * 2) mknod(2) returns -1 and sets errno to EACCES if parent directory 28 * does not allow write permission to the process. 29 * 3) mknod(2) returns -1 and sets errno to EROFS if pathname refers to 30 * a file on a read-only file system. 31 * 4) mknod(2) returns -1 and sets errno to ELOOP if too many symbolic 32 * links were encountered in resolving pathname. 33 * 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <errno.h> 40 #include <string.h> 41 #include <signal.h> 42 #include <pwd.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <sys/mount.h> 46 47 #include "test.h" 48 #include "safe_macros.h" 49 50 #define DIR_TEMP "testdir_1" 51 #define DIR_TEMP_MODE (S_IRUSR | S_IXUSR) 52 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 53 S_IXGRP|S_IROTH|S_IXOTH) 54 #define MNT_POINT "mntpoint" 55 56 #define FIFO_MODE (S_IFIFO | S_IRUSR | S_IRGRP | S_IROTH) 57 #define SOCKET_MODE (S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) 58 #define CHR_MODE (S_IFCHR | S_IRUSR | S_IWUSR) 59 #define BLK_MODE (S_IFBLK | S_IRUSR | S_IWUSR) 60 61 #define ELOPFILE "/test_eloop" 62 63 static char elooppathname[sizeof(ELOPFILE) * 43] = "."; 64 65 static const char *device; 66 static int mount_flag; 67 68 static struct test_case_t { 69 char *pathname; 70 int mode; 71 int exp_errno; 72 } test_cases[] = { 73 { "testdir_1/tnode_1", SOCKET_MODE, EACCES }, 74 { "testdir_1/tnode_2", FIFO_MODE, EACCES }, 75 { "tnode_3", CHR_MODE, EPERM }, 76 { "tnode_4", BLK_MODE, EPERM }, 77 { "mntpoint/tnode_5", SOCKET_MODE, EROFS }, 78 { elooppathname, FIFO_MODE, ELOOP }, 79 }; 80 81 char *TCID = "mknod07"; 82 int TST_TOTAL = ARRAY_SIZE(test_cases); 83 84 static void setup(void); 85 static void mknod_verify(const struct test_case_t *test_case); 86 static void cleanup(void); 87 88 int main(int ac, char **av) 89 { 90 int lc; 91 int i; 92 93 tst_parse_opts(ac, av, NULL, NULL); 94 95 setup(); 96 97 for (lc = 0; TEST_LOOPING(lc); lc++) { 98 tst_count = 0; 99 100 for (i = 0; i < TST_TOTAL; i++) 101 mknod_verify(&test_cases[i]); 102 } 103 104 cleanup(); 105 tst_exit(); 106 } 107 108 static void setup(void) 109 { 110 int i; 111 struct passwd *ltpuser; 112 const char *fs_type; 113 114 tst_require_root(); 115 116 tst_sig(NOFORK, DEF_HANDLER, cleanup); 117 118 tst_tmpdir(); 119 120 fs_type = tst_dev_fs_type(); 121 device = tst_acquire_device(cleanup); 122 123 if (!device) 124 tst_brkm(TCONF, cleanup, "Failed to acquire device"); 125 126 tst_mkfs(cleanup, device, fs_type, NULL, NULL); 127 128 TEST_PAUSE; 129 130 /* mount a read-only file system for EROFS test */ 131 SAFE_MKDIR(cleanup, MNT_POINT, DIR_MODE); 132 SAFE_MOUNT(cleanup, device, MNT_POINT, fs_type, MS_RDONLY, NULL); 133 mount_flag = 1; 134 135 ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 136 SAFE_SETEUID(cleanup, ltpuser->pw_uid); 137 138 SAFE_MKDIR(cleanup, DIR_TEMP, DIR_TEMP_MODE); 139 140 /* 141 * NOTE: the ELOOP test is written based on that the consecutive 142 * symlinks limits in kernel is hardwired to 40. 143 */ 144 SAFE_MKDIR(cleanup, "test_eloop", DIR_MODE); 145 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop"); 146 for (i = 0; i < 43; i++) 147 strcat(elooppathname, ELOPFILE); 148 } 149 150 static void mknod_verify(const struct test_case_t *test_case) 151 { 152 TEST(mknod(test_case->pathname, test_case->mode, 0)); 153 154 if (TEST_RETURN != -1) { 155 tst_resm(TFAIL, "mknod succeeded unexpectedly"); 156 return; 157 } 158 159 if (TEST_ERRNO == test_case->exp_errno) { 160 tst_resm(TPASS | TTERRNO, "mknod failed as expected"); 161 } else { 162 tst_resm(TFAIL | TTERRNO, 163 "mknod failed unexpectedly; expected: " 164 "%d - %s", test_case->exp_errno, 165 strerror(test_case->exp_errno)); 166 } 167 } 168 169 static void cleanup(void) 170 { 171 if (seteuid(0) == -1) 172 tst_resm(TWARN | TERRNO, "seteuid(0) failed"); 173 174 if (mount_flag && tst_umount(MNT_POINT) < 0) 175 tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 176 177 if (device) 178 tst_release_device(device); 179 180 tst_rmdir(); 181 } 182