1 /* 2 * Copyright (C) 2011 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 * In the user.* namespace, only regular files and directories can 27 * have extended attributes. Otherwise setxattr(2) will return -1 28 * and set errno to EPERM. 29 * 30 * There are 7 test cases: 31 * 1. Set attribute to a regular file, setxattr(2) should succeed 32 * 2. Set attribute to a directory, setxattr(2) should succeed 33 * 3. Set attribute to a symlink which points to the regular file, 34 * setxattr(2) should return -1 and set errno to EEXIST 35 * 4. Set attribute to a FIFO, setxattr(2) should return -1 and set 36 * errno to EPERM 37 * 5. Set attribute to a char special file, setxattr(2) should 38 * return -1 and set errno to EPERM 39 * 6. Set attribute to a block special file, setxattr(2) should 40 * return -1 and set errno to EPERM 41 * 7. Set attribute to a UNIX domain socket, setxattr(2) should 42 * return -1 and set errno to EPERM 43 */ 44 45 #include "config.h" 46 #include <sys/types.h> 47 #include <sys/stat.h> 48 #include <sys/wait.h> 49 #include <errno.h> 50 #include <fcntl.h> 51 #include <unistd.h> 52 #include <signal.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #ifdef HAVE_SYS_XATTR_H 57 # include <sys/xattr.h> 58 #endif 59 #include "test.h" 60 61 char *TCID = "setxattr02"; 62 63 #ifdef HAVE_SYS_XATTR_H 64 #define XATTR_TEST_KEY "user.testkey" 65 #define XATTR_TEST_VALUE "this is a test value" 66 #define XATTR_TEST_VALUE_SIZE 20 67 68 #define FILENAME "setxattr02testfile" 69 #define DIRNAME "setxattr02testdir" 70 #define SYMLINK "setxattr02symlink" 71 #define FIFO "setxattr02fifo" 72 #define CHR "setxattr02chr" 73 #define BLK "setxattr02blk" 74 #define SOCK "setxattr02sock" 75 76 static void setup(void); 77 static void cleanup(void); 78 79 struct test_case { 80 char *fname; 81 char *key; 82 char *value; 83 size_t size; 84 int flags; 85 int exp_err; 86 }; 87 static struct test_case tc[] = { 88 { /* case 00, set attr to reg */ 89 .fname = FILENAME, 90 .key = XATTR_TEST_KEY, 91 .value = XATTR_TEST_VALUE, 92 .size = XATTR_TEST_VALUE_SIZE, 93 .flags = XATTR_CREATE, 94 .exp_err = 0, 95 }, 96 { /* case 01, set attr to dir */ 97 .fname = DIRNAME, 98 .key = XATTR_TEST_KEY, 99 .value = XATTR_TEST_VALUE, 100 .size = XATTR_TEST_VALUE_SIZE, 101 .flags = XATTR_CREATE, 102 .exp_err = 0, 103 }, 104 { /* case 02, set attr to symlink */ 105 .fname = SYMLINK, 106 .key = XATTR_TEST_KEY, 107 .value = XATTR_TEST_VALUE, 108 .size = XATTR_TEST_VALUE_SIZE, 109 .flags = XATTR_CREATE, 110 .exp_err = EEXIST, 111 }, 112 { /* case 03, set attr to fifo */ 113 .fname = FIFO, 114 .key = XATTR_TEST_KEY, 115 .value = XATTR_TEST_VALUE, 116 .size = XATTR_TEST_VALUE_SIZE, 117 .flags = XATTR_CREATE, 118 .exp_err = EPERM, 119 }, 120 { /* case 04, set attr to character special */ 121 .fname = CHR, 122 .key = XATTR_TEST_KEY, 123 .value = XATTR_TEST_VALUE, 124 .size = XATTR_TEST_VALUE_SIZE, 125 .flags = XATTR_CREATE, 126 .exp_err = EPERM, 127 }, 128 { /* case 05, set attr to block special */ 129 .fname = BLK, 130 .key = XATTR_TEST_KEY, 131 .value = XATTR_TEST_VALUE, 132 .size = XATTR_TEST_VALUE_SIZE, 133 .flags = XATTR_CREATE, 134 .exp_err = EPERM, 135 }, 136 { /* case 06, set attr to socket */ 137 .fname = SOCK, 138 .key = XATTR_TEST_KEY, 139 .value = XATTR_TEST_VALUE, 140 .size = XATTR_TEST_VALUE_SIZE, 141 .flags = XATTR_CREATE, 142 .exp_err = EPERM, 143 }, 144 }; 145 146 int TST_TOTAL = sizeof(tc) / sizeof(tc[0]); 147 148 int main(int argc, char *argv[]) 149 { 150 int lc; 151 int i; 152 153 tst_parse_opts(argc, argv, NULL, NULL); 154 155 setup(); 156 157 for (lc = 0; TEST_LOOPING(lc); lc++) { 158 tst_count = 0; 159 160 for (i = 0; i < TST_TOTAL; i++) { 161 TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, 162 tc[i].size, tc[i].flags)); 163 164 if (TEST_ERRNO == tc[i].exp_err) { 165 tst_resm(TPASS | TTERRNO, "expected behavior"); 166 } else { 167 tst_resm(TFAIL | TTERRNO, "unexpected behavior " 168 "- expected errno %d - Got", 169 tc[i].exp_err); 170 } 171 } 172 } 173 174 cleanup(); 175 tst_exit(); 176 } 177 178 static void setup(void) 179 { 180 int fd; 181 dev_t dev; 182 183 tst_require_root(); 184 185 tst_tmpdir(); 186 187 /* Test for xattr support */ 188 fd = creat("testfile", 0644); 189 if (fd == -1) 190 tst_brkm(TBROK | TERRNO, cleanup, "Create testfile failed"); 191 close(fd); 192 if (setxattr("testfile", "user.test", "test", 4, XATTR_CREATE) == -1) 193 if (errno == ENOTSUP) 194 tst_brkm(TCONF, cleanup, "No xattr support in fs or " 195 "mount without user_xattr option"); 196 unlink("testfile"); 197 198 /* Create test files */ 199 fd = creat(FILENAME, 0644); 200 if (fd == -1) 201 tst_brkm(TBROK | TERRNO, cleanup, "Create test file(%s) failed", 202 FILENAME); 203 close(fd); 204 205 if (mkdir(DIRNAME, 0644) == -1) 206 tst_brkm(TBROK | TERRNO, cleanup, "Create test dir(%s) failed", 207 DIRNAME); 208 209 if (symlink(FILENAME, SYMLINK) == -1) 210 tst_brkm(TBROK | TERRNO, cleanup, "Create symlink(%s->%s)" 211 " failed", SYMLINK, FILENAME); 212 213 if (mknod(FIFO, S_IFIFO | 0777, 0) == -1) 214 tst_brkm(TBROK | TERRNO, cleanup, "Create FIFO(%s) failed", 215 FIFO); 216 217 dev = makedev(1, 3); 218 if (mknod(CHR, S_IFCHR | 0777, dev) == -1) 219 tst_brkm(TBROK | TERRNO, cleanup, "Create char special(%s)" 220 " failed", CHR); 221 222 if (mknod(BLK, S_IFBLK | 0777, 0) == -1) 223 tst_brkm(TBROK | TERRNO, cleanup, "Create block special(%s)" 224 " failed", BLK); 225 226 if (mknod(SOCK, S_IFSOCK | 0777, 0) == -1) 227 tst_brkm(TBROK | TERRNO, cleanup, "Create socket(%s) failed", 228 SOCK); 229 230 TEST_PAUSE; 231 } 232 233 static void cleanup(void) 234 { 235 tst_rmdir(); 236 } 237 #else /* HAVE_SYS_XATTR_H */ 238 int main(int argc, char *argv[]) 239 { 240 tst_brkm(TCONF, NULL, "<sys/xattr.h> does not exist."); 241 } 242 #endif 243