1 /*
2 * Copyright (C) 2012 Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it
13 * is free of the rightful claim of any third person regarding
14 * infringement or the like. Any license provided herein, whether
15 * implied or otherwise, applies only to this software file. Patent
16 * licenses, if any, provided herein do not apply to combinations of
17 * this program with other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301, USA.
23 */
24
25 /*
26 * setxattr(2) to immutable and append-only files should get EPERM
27 *
28 * There are 2 test cases:
29 * 1. Set attribute to a immutable file, setxattr(2) should return -1
30 * and set errno to EPERM
31 * 2. Set attribute to a append-only file, setxattr(2) should return
32 * -1 and set errno to EPERM
33 */
34
35 #include "config.h"
36 #include <sys/ioctl.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <sys/wait.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <signal.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #ifdef HAVE_SYS_XATTR_H
48 # include <sys/xattr.h>
49 #endif
50 #include <linux/fs.h>
51
52 #include "test.h"
53 #include "safe_macros.h"
54
55 char *TCID = "setxattr03";
56
57 #if defined HAVE_SYS_XATTR_H && defined HAVE_FS_IOC_FLAGS
58 #define XATTR_TEST_KEY "user.testkey"
59 #define XATTR_TEST_VALUE "this is a test value"
60 #define XATTR_TEST_VALUE_SIZE (sizeof(XATTR_TEST_VALUE) - 1)
61
62 #define IMMU_FILE "setxattr03immutable"
63 #define APPEND_FILE "setxattr03appendonly"
64
65 #define set_immutable_on(fd) fsetflag(fd, 1, 1)
66 #define set_immutable_off(fd) fsetflag(fd, 0, 1)
67 #define set_append_on(fd) fsetflag(fd, 1, 0)
68 #define set_append_off(fd) fsetflag(fd, 0, 0)
69
70 struct test_case {
71 char *desc;
72 char *fname;
73 char *key;
74 char *value;
75 size_t size;
76 int flags;
77 int exp_err;
78 };
79 static struct test_case tc[] = {
80 { /* case 00, set attr to immutable file */
81 .desc = "Set attr to immutable file",
82 .fname = IMMU_FILE,
83 .key = XATTR_TEST_KEY,
84 .value = XATTR_TEST_VALUE,
85 .size = XATTR_TEST_VALUE_SIZE,
86 .flags = XATTR_CREATE,
87 .exp_err = EPERM,
88 },
89 { /* case 01, set attr to append-only file */
90 .desc = "Set attr to append-only file",
91 .fname = APPEND_FILE,
92 .key = XATTR_TEST_KEY,
93 .value = XATTR_TEST_VALUE,
94 .size = XATTR_TEST_VALUE_SIZE,
95 .flags = XATTR_CREATE,
96 .exp_err = EPERM,
97 },
98 };
99
100 static void setup(void);
101 static void cleanup(void);
102
103 static int immu_fd;
104 static int append_fd;
105
106 int TST_TOTAL = sizeof(tc) / sizeof(tc[0]);
107
main(int argc,char * argv[])108 int main(int argc, char *argv[])
109 {
110 int lc;
111 int i;
112
113 tst_parse_opts(argc, argv, NULL, NULL);
114
115 setup();
116
117 for (lc = 0; TEST_LOOPING(lc); lc++) {
118 tst_count = 0;
119
120 for (i = 0; i < TST_TOTAL; i++) {
121 TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value,
122 tc[i].size, tc[i].flags));
123
124 if (TEST_ERRNO == tc[i].exp_err) {
125 tst_resm(TPASS | TTERRNO, "%s", tc[i].desc);
126 } else {
127 tst_resm(TFAIL | TTERRNO, "%s - expected errno"
128 " %d - Got", tc[i].desc,
129 tc[i].exp_err);
130 }
131 }
132 }
133
134 cleanup();
135 tst_exit();
136 }
137
fsetflag(int fd,int on,int immutable)138 static int fsetflag(int fd, int on, int immutable)
139 {
140 int fsflags = 0;
141 int fsfl;
142
143 if (ioctl(fd, FS_IOC_GETFLAGS, &fsflags) < 0)
144 return 1;
145
146 if (immutable)
147 fsfl = FS_IMMUTABLE_FL;
148 else
149 fsfl = FS_APPEND_FL;
150
151 if (on)
152 fsflags |= fsfl;
153 else
154 fsflags &= ~fsfl;
155
156 if (ioctl(fd, FS_IOC_SETFLAGS, &fsflags) < 0)
157 return 1;
158
159 return 0;
160 }
161
setup(void)162 static void setup(void)
163 {
164 int fd;
165
166 tst_require_root();
167
168 tst_tmpdir();
169
170 /* Test for xattr support */
171 fd = SAFE_CREAT(cleanup, "testfile", 0644);
172 close(fd);
173 if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1)
174 if (errno == ENOTSUP)
175 tst_brkm(TCONF, cleanup, "No xattr support in fs or "
176 "fs mounted without user_xattr option");
177 unlink("testfile");
178
179 /* Create test files and set file immutable or append-only */
180 immu_fd = SAFE_CREAT(cleanup, IMMU_FILE, 0644);
181 if (set_immutable_on(immu_fd))
182 tst_brkm(TBROK | TERRNO, cleanup, "Set %s immutable failed",
183 IMMU_FILE);
184
185 append_fd = SAFE_CREAT(cleanup, APPEND_FILE, 0644);
186 if (set_append_on(append_fd))
187 tst_brkm(TBROK | TERRNO, cleanup, "Set %s append-only failed",
188 APPEND_FILE);
189
190 TEST_PAUSE;
191 }
192
cleanup(void)193 static void cleanup(void)
194 {
195 if ((immu_fd > 0) && set_immutable_off(immu_fd))
196 tst_resm(TWARN | TERRNO, "Unset %s immutable failed",
197 IMMU_FILE);
198 if ((append_fd > 0) && set_append_off(append_fd))
199 tst_resm(TWARN | TERRNO, "Unset %s append-only failed",
200 APPEND_FILE);
201 close(immu_fd);
202 close(append_fd);
203
204 tst_rmdir();
205 }
206 #else
main(void)207 int main(void)
208 {
209 tst_brkm(TCONF, NULL, "<sys/xattr.h> not present or FS_IOC_FLAGS "
210 "missing in <linux/fs.h>");
211 }
212 #endif /* defined HAVE_SYS_XATTR_H && defined HAVE_FS_IOC_FLAGS */
213