blob: 6bf7ca7cfbd7dd596529f172ce43683e043fb757 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
Cyril Hrubiscd3beec2014-06-19 15:20:12 +02002 * Copyright (c) International Business Machines Corp., 2001
3 * 07/2001 Ported by Wayne Boyer
4 * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
plars865695b2001-08-27 22:15:12 +00005 *
Cyril Hrubiscd3beec2014-06-19 15:20:12 +02006 * 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.
plars865695b2001-08-27 22:15:12 +000010 *
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020011 * 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.
plars865695b2001-08-27 22:15:12 +000015 *
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020016 * 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
plars865695b2001-08-27 22:15:12 +000019 */
20
21/*
22 * Test Name: chmod06
23 *
24 * Test Description:
25 * Verify that,
26 * 1) chmod(2) returns -1 and sets errno to EPERM if the effective user id
27 * of process does not match the owner of the file and the process is
28 * not super user.
29 * 2) chmod(2) returns -1 and sets errno to EACCES if search permission is
30 * denied on a component of the path prefix.
31 * 3) chmod(2) returns -1 and sets errno to EFAULT if pathname points
32 * outside user's accessible address space.
33 * 4) chmod(2) returns -1 and sets errno to ENAMETOOLONG if the pathname
34 * component is too long.
35 * 5) chmod(2) returns -1 and sets errno to ENOTDIR if the directory
36 * component in pathname is not a directory.
37 * 6) chmod(2) returns -1 and sets errno to ENOENT if the specified file
38 * does not exists.
plars865695b2001-08-27 22:15:12 +000039 */
40
vapier5b31d1b2006-08-21 06:46:26 +000041#ifndef _GNU_SOURCE
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020042# define _GNU_SOURCE
vapier5b31d1b2006-08-21 06:46:26 +000043#endif
44
plars865695b2001-08-27 22:15:12 +000045#include <stdio.h>
46#include <stdlib.h>
47#include <unistd.h>
48#include <fcntl.h>
49#include <errno.h>
50#include <string.h>
51#include <signal.h>
52#include <grp.h>
53#include <pwd.h>
54#include <sys/types.h>
55#include <sys/stat.h>
plars1ad84512002-07-23 13:11:18 +000056#include <sys/mman.h>
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +080057#include <sys/mount.h>
plars865695b2001-08-27 22:15:12 +000058
59#include "test.h"
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +080060#include "safe_macros.h"
plars865695b2001-08-27 22:15:12 +000061
Garrett Cooperc5f40232010-12-17 12:26:46 -080062#define MODE_RWX (S_IRWXU|S_IRWXG|S_IRWXO)
63#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
plars865695b2001-08-27 22:15:12 +000064#define DIR_TEMP "testdir_1"
65#define TEST_FILE1 "tfile_1"
66#define TEST_FILE2 "testdir_1/tfile_2"
67#define TEST_FILE3 "t_file/tfile_3"
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +080068#define TEST_FILE4 "test_file4"
69#define MNT_POINT "mntpoint"
70
71#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
72 S_IXGRP|S_IROTH|S_IXOTH)
plars865695b2001-08-27 22:15:12 +000073
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020074static char long_path[PATH_MAX + 2];
plars865695b2001-08-27 22:15:12 +000075
Cyril Hrubisb1118712014-06-19 16:50:57 +020076static const char *device;
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +080077static int mount_flag;
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020078static uid_t nobody_uid;
79
80static void set_root(void);
81static void set_nobody(void);
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +080082
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020083struct test_case_t {
plars865695b2001-08-27 22:15:12 +000084 char *pathname;
Garrett Cooperc5f40232010-12-17 12:26:46 -080085 mode_t mode;
plars865695b2001-08-27 22:15:12 +000086 int exp_errno;
Cyril Hrubiscd3beec2014-06-19 15:20:12 +020087 void (*setup)(void);
88 void (*cleanup)(void);
89} tc[] = {
90 {TEST_FILE1, FILE_MODE, EPERM, set_nobody, set_root},
91 {TEST_FILE2, FILE_MODE, EACCES, set_nobody, set_root},
92 {(char *)-1, FILE_MODE, EFAULT, NULL, NULL},
93 {(char *)-2, FILE_MODE, EFAULT, NULL, NULL},
94 {long_path, FILE_MODE, ENAMETOOLONG, NULL, NULL},
95 {"", FILE_MODE, ENOENT, NULL, NULL},
96 {TEST_FILE3, FILE_MODE, ENOTDIR, NULL, NULL},
97 {MNT_POINT, FILE_MODE, EROFS, NULL, NULL},
98 {TEST_FILE4, FILE_MODE, ELOOP, NULL, NULL},
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +080099};
plars865695b2001-08-27 22:15:12 +0000100
Garrett Cooperc5f40232010-12-17 12:26:46 -0800101char *TCID = "chmod06";
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200102int TST_TOTAL = ARRAY_SIZE(tc);
plars865695b2001-08-27 22:15:12 +0000103
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200104static char *bad_addr = 0;
plars1ad84512002-07-23 13:11:18 +0000105
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200106static void setup(void);
107static void cleanup(void);
plars865695b2001-08-27 22:15:12 +0000108
subrata_modak56207ce2009-03-23 13:35:39 +0000109int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +0000110{
Garrett Cooperc5f40232010-12-17 12:26:46 -0800111 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200112 const char *msg;
Garrett Cooperc5f40232010-12-17 12:26:46 -0800113 int i;
plars865695b2001-08-27 22:15:12 +0000114
Cyril Hrubisb1118712014-06-19 16:50:57 +0200115 msg = parse_opts(ac, av, NULL, NULL);
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800116 if (msg != NULL)
plars865695b2001-08-27 22:15:12 +0000117 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800118
plars865695b2001-08-27 22:15:12 +0000119 setup();
120
plars865695b2001-08-27 22:15:12 +0000121 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800122 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000123
Garrett Cooperc5f40232010-12-17 12:26:46 -0800124 for (i = 0; i < TST_TOTAL; i++) {
plars865695b2001-08-27 22:15:12 +0000125
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200126 if (tc[i].setup)
127 tc[i].setup();
Garrett Cooperc5f40232010-12-17 12:26:46 -0800128
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200129 TEST(chmod(tc[i].pathname, tc[i].mode));
plars865695b2001-08-27 22:15:12 +0000130
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200131 if (tc[i].cleanup)
132 tc[i].cleanup();
subrata_modakbdbaec52009-02-26 12:14:51 +0000133
plars865695b2001-08-27 22:15:12 +0000134 if (TEST_RETURN != -1) {
Garrett Cooperc5f40232010-12-17 12:26:46 -0800135 tst_resm(TFAIL, "chmod succeeded unexpectedly");
plars865695b2001-08-27 22:15:12 +0000136 continue;
137 }
138
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200139 if (TEST_ERRNO == tc[i].exp_errno)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 tst_resm(TPASS | TTERRNO,
141 "chmod failed as expected");
Garrett Cooperc5f40232010-12-17 12:26:46 -0800142 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800143 tst_resm(TFAIL | TTERRNO,
144 "chmod failed unexpectedly; "
145 "expected %d - %s",
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200146 tc[i].exp_errno,
147 tst_strerrno(tc[i].exp_errno));
Garrett Cooper2c282152010-12-16 00:55:50 -0800148 }
plars865695b2001-08-27 22:15:12 +0000149
Garrett Cooper2c282152010-12-16 00:55:50 -0800150 }
plars865695b2001-08-27 22:15:12 +0000151
plars865695b2001-08-27 22:15:12 +0000152 cleanup();
Garrett Cooperc5f40232010-12-17 12:26:46 -0800153 tst_exit();
Garrett Cooperc5f40232010-12-17 12:26:46 -0800154}
plars865695b2001-08-27 22:15:12 +0000155
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200156void set_root(void)
157{
158 SAFE_SETEUID(cleanup, 0);
159}
160
161void set_nobody(void)
162{
163 SAFE_SETEUID(cleanup, nobody_uid);
164}
165
Mike Frysingerc57fba52014-04-09 18:56:30 -0400166void setup(void)
plars865695b2001-08-27 22:15:12 +0000167{
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200168 struct passwd *nobody;
Cyril Hrubisb1118712014-06-19 16:50:57 +0200169 const char *fs_type;
plars865695b2001-08-27 22:15:12 +0000170
plars865695b2001-08-27 22:15:12 +0000171 tst_sig(FORK, DEF_HANDLER, cleanup);
172
Garrett Cooperc5f40232010-12-17 12:26:46 -0800173 tst_require_root(NULL);
plars865695b2001-08-27 22:15:12 +0000174
plars865695b2001-08-27 22:15:12 +0000175 TEST_PAUSE;
176
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200177 nobody = SAFE_GETPWNAM(NULL, "nobody");
178 nobody_uid = nobody->pw_uid;
179
180 bad_addr = SAFE_MMAP(NULL, 0, 1, PROT_NONE,
181 MAP_PRIVATE_EXCEPT_UCLINUX | MAP_ANONYMOUS, 0, 0);
182 tc[3].pathname = bad_addr;
183
plars865695b2001-08-27 22:15:12 +0000184 tst_tmpdir();
185
Cyril Hrubisb1118712014-06-19 16:50:57 +0200186 fs_type = tst_dev_fs_type();
187 device = tst_acquire_device(cleanup);
188
189 if (!device)
190 tst_brkm(TCONF, cleanup, "Failed to obtain block device");
191
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200192 SAFE_TOUCH(cleanup, TEST_FILE1, 0666, NULL);
193 SAFE_MKDIR(cleanup, DIR_TEMP, MODE_RWX);
194 SAFE_TOUCH(cleanup, TEST_FILE2, 0666, NULL);
195 SAFE_CHMOD(cleanup, DIR_TEMP, FILE_MODE);
196 SAFE_TOUCH(cleanup, "t_file", MODE_RWX, NULL);
197
Cyril Hrubisb1118712014-06-19 16:50:57 +0200198 tst_mkfs(cleanup, device, fs_type, NULL);
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800199
200 SAFE_MKDIR(cleanup, MNT_POINT, DIR_MODE);
201
202 /*
203 * mount a read-only file system for test EROFS
204 */
Cyril Hrubisb1118712014-06-19 16:50:57 +0200205 if (mount(device, MNT_POINT, fs_type, MS_RDONLY, NULL) < 0) {
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800206 tst_brkm(TBROK | TERRNO, cleanup,
207 "mount device:%s failed", device);
208 }
209 mount_flag = 1;
210
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200211 memset(long_path, 'a', PATH_MAX+1);
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800212
213 /*
214 * create two symbolic links who point to each other for
215 * test ELOOP.
216 */
217 SAFE_SYMLINK(cleanup, "test_file4", "test_file5");
218 SAFE_SYMLINK(cleanup, "test_file5", "test_file4");
plars865695b2001-08-27 22:15:12 +0000219}
220
Cyril Hrubiscd3beec2014-06-19 15:20:12 +0200221static void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000222{
Garrett Cooperc5f40232010-12-17 12:26:46 -0800223 if (chmod(DIR_TEMP, MODE_RWX) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800224 tst_resm(TBROK | TERRNO, "chmod(%s) failed", DIR_TEMP);
plars865695b2001-08-27 22:15:12 +0000225
Cyril Hrubisc60a2302015-01-29 16:28:24 +0100226 if (mount_flag && tst_umount(MNT_POINT) < 0) {
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800227 tst_brkm(TBROK | TERRNO, NULL,
228 "umount device:%s failed", device);
229 }
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800230
Cyril Hrubisb1118712014-06-19 16:50:57 +0200231 if (device)
232 tst_release_device(NULL, device);
233
234 tst_rmdir();
Wang, Xiaoguang3aa27d92013-10-25 16:13:40 +0800235}