blob: 02c1363a8f3bcdf35a00ae36aa09e76416c9c460 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +08004 * 07/2001 Ported by Wayne Boyer
plars865695b2001-08-27 22:15:12 +00005 *
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
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080017 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000019 */
20
21/*
plars865695b2001-08-27 22:15:12 +000022 *
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.
Xiaoguang Wang1e24e422014-02-26 20:32:26 +080029 * 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.
plars865695b2001-08-27 22:15:12 +000033 *
plars865695b2001-08-27 22:15:12 +000034 */
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>
Xiaoguang Wang1e24e422014-02-26 20:32:26 +080045#include <sys/mount.h>
plars865695b2001-08-27 22:15:12 +000046
47#include "test.h"
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080048#include "safe_macros.h"
plars865695b2001-08-27 22:15:12 +000049
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080050#define DIR_TEMP "testdir_1"
51#define DIR_TEMP_MODE (S_IRUSR | S_IXUSR)
Xiaoguang Wang1e24e422014-02-26 20:32:26 +080052#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
53 S_IXGRP|S_IROTH|S_IXOTH)
54#define MNT_POINT "mntpoint"
plars865695b2001-08-27 22:15:12 +000055
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080056#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)
plars865695b2001-08-27 22:15:12 +000060
Xiaoguang Wang1e24e422014-02-26 20:32:26 +080061#define ELOPFILE "/test_eloop"
62
63static char elooppathname[sizeof(ELOPFILE) * 43] = ".";
64
Cyril Hrubis41028182014-06-19 17:27:33 +020065static const char *device;
Xiaoguang Wang1e24e422014-02-26 20:32:26 +080066static int mount_flag;
67
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080068static struct test_case_t {
plars865695b2001-08-27 22:15:12 +000069 char *pathname;
plars865695b2001-08-27 22:15:12 +000070 int mode;
71 int exp_errno;
Garrett Cooper4d0292e2010-12-19 06:53:26 -080072} test_cases[] = {
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080073 { "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 },
Xiaoguang Wang1e24e422014-02-26 20:32:26 +080077 { "mntpoint/tnode_5", SOCKET_MODE, EROFS },
78 { elooppathname, FIFO_MODE, ELOOP },
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080079};
plars865695b2001-08-27 22:15:12 +000080
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020081char *TCID = "mknod07";
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080082int TST_TOTAL = ARRAY_SIZE(test_cases);
plars865695b2001-08-27 22:15:12 +000083
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080084static void setup(void);
85static void mknod_verify(const struct test_case_t *test_case);
86static void cleanup(void);
plars865695b2001-08-27 22:15:12 +000087
subrata_modak56207ce2009-03-23 13:35:39 +000088int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +000089{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020090 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020091 const char *msg;
Cyril Hrubis89af32a2012-10-24 16:39:11 +020092 int i;
plars865695b2001-08-27 22:15:12 +000093
Cyril Hrubis41028182014-06-19 17:27:33 +020094 msg = parse_opts(ac, av, NULL, NULL);
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +080095 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +000096 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -080097
plars865695b2001-08-27 22:15:12 +000098 setup();
99
plars865695b2001-08-27 22:15:12 +0000100 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800101 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000102
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800103 for (i = 0; i < TST_TOTAL; i++)
104 mknod_verify(&test_cases[i]);
Garrett Cooper2c282152010-12-16 00:55:50 -0800105 }
plars865695b2001-08-27 22:15:12 +0000106
plars865695b2001-08-27 22:15:12 +0000107 cleanup();
Garrett Cooper4d0292e2010-12-19 06:53:26 -0800108 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800109}
plars865695b2001-08-27 22:15:12 +0000110
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800111static void setup(void)
plars865695b2001-08-27 22:15:12 +0000112{
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800113 int i;
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800114 struct passwd *ltpuser;
Cyril Hrubis41028182014-06-19 17:27:33 +0200115 const char *fs_type;
plars865695b2001-08-27 22:15:12 +0000116
Garrett Cooper4d0292e2010-12-19 06:53:26 -0800117 tst_require_root(NULL);
118
plars865695b2001-08-27 22:15:12 +0000119 tst_sig(NOFORK, DEF_HANDLER, cleanup);
120
plars865695b2001-08-27 22:15:12 +0000121 tst_tmpdir();
122
Cyril Hrubis41028182014-06-19 17:27:33 +0200123 fs_type = tst_dev_fs_type();
124 device = tst_acquire_device(cleanup);
125
126 if (!device)
127 tst_brkm(TCONF, cleanup, "Failed to acquire device");
128
129 tst_mkfs(cleanup, device, fs_type, NULL);
130
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800131 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000132
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800133 /* mount a read-only file system for EROFS test */
134 SAFE_MKDIR(cleanup, MNT_POINT, DIR_MODE);
Cyril Hrubis41028182014-06-19 17:27:33 +0200135 if (mount(device, MNT_POINT, fs_type, MS_RDONLY, NULL) < 0) {
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800136 tst_brkm(TBROK | TERRNO, cleanup,
137 "mount device:%s failed", device);
138 }
139 mount_flag = 1;
140
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800141 ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
142 SAFE_SETEUID(cleanup, ltpuser->pw_uid);
plars865695b2001-08-27 22:15:12 +0000143
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800144 SAFE_MKDIR(cleanup, DIR_TEMP, DIR_TEMP_MODE);
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800145
146 /*
147 * NOTE: the ELOOP test is written based on that the consecutive
148 * symlinks limits in kernel is hardwired to 40.
149 */
150 SAFE_MKDIR(cleanup, "test_eloop", DIR_MODE);
151 SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop");
152 for (i = 0; i < 43; i++)
153 strcat(elooppathname, ELOPFILE);
plars865695b2001-08-27 22:15:12 +0000154}
155
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800156static void mknod_verify(const struct test_case_t *test_case)
plars865695b2001-08-27 22:15:12 +0000157{
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800158 TEST(mknod(test_case->pathname, test_case->mode, 0));
159
160 if (TEST_RETURN != -1) {
161 tst_resm(TFAIL, "mknod succeeded unexpectedly");
162 return;
163 }
164
165 if (TEST_ERRNO == test_case->exp_errno) {
166 tst_resm(TPASS | TTERRNO, "mknod failed as expected");
167 } else {
168 tst_resm(TFAIL | TTERRNO,
169 "mknod failed unexpectedly; expected: "
170 "%d - %s", test_case->exp_errno,
171 strerror(test_case->exp_errno));
172 }
plars865695b2001-08-27 22:15:12 +0000173}
174
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800175static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000176{
subrata_modak56207ce2009-03-23 13:35:39 +0000177 if (seteuid(0) == -1)
Xiaoguang Wang47f7fa02014-02-26 20:32:25 +0800178 tst_resm(TWARN | TERRNO, "seteuid(0) failed");
plars865695b2001-08-27 22:15:12 +0000179
Cyril Hrubisc60a2302015-01-29 16:28:24 +0100180 if (mount_flag && tst_umount(MNT_POINT) < 0)
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800181 tst_resm(TWARN | TERRNO, "umount device:%s failed", device);
182
Cyril Hrubis41028182014-06-19 17:27:33 +0200183 if (device)
184 tst_release_device(NULL, device);
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800185
Cyril Hrubis41028182014-06-19 17:27:33 +0200186 tst_rmdir();
Xiaoguang Wang1e24e422014-02-26 20:32:26 +0800187}