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 * Basic tests for setxattr(2) and make sure setxattr(2) handles error 27 * conditions correctly. 28 * 29 * There are 7 test cases: 30 * 1. Any other flags being set except XATTR_CREATE and XATTR_REPLACE, 31 * setxattr(2) should return -1 and set errno to EINVAL 32 * 2. With XATTR_REPLACE flag set but the attribute does not exist, 33 * setxattr(2) should return -1 and set errno to ENODATA 34 * 3. Create new attr with name length greater than XATTR_NAME_MAX(255) 35 * setxattr(2) should return -1 and set errno to ERANGE 36 * 4. Create new attr whose value length is greater than XATTR_SIZE_MAX(65536) 37 * setxattr(2) should return -1 and set errno to E2BIG 38 * 5. Create new attr whose value length is zero, 39 * setxattr(2) should succeed 40 * 6. Replace the attr value without XATTR_REPLACE flag being set, 41 * setxattr(2) should return -1 and set errno to EEXIST 42 * 7. Replace attr value with XATTR_REPLACE flag being set, 43 * setxattr(2) should succeed 44 */ 45 46 #include "config.h" 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include <sys/wait.h> 50 #include <errno.h> 51 #include <fcntl.h> 52 #include <unistd.h> 53 #include <signal.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 #ifdef HAVE_SYS_XATTR_H 58 # include <sys/xattr.h> 59 #endif 60 #include "tst_test.h" 61 62 #ifdef HAVE_SYS_XATTR_H 63 #define XATTR_NAME_MAX 255 64 #define XATTR_NAME_LEN (XATTR_NAME_MAX + 2) 65 #define XATTR_SIZE_MAX 65536 66 #define XATTR_TEST_KEY "user.testkey" 67 #define XATTR_TEST_VALUE "this is a test value" 68 #define XATTR_TEST_VALUE_SIZE 20 69 #define MNTPOINT "mntpoint" 70 #define FNAME MNTPOINT"/setxattr01testfile" 71 72 static char long_key[XATTR_NAME_LEN]; 73 static char *long_value; 74 static char *xattr_value = XATTR_TEST_VALUE; 75 76 struct test_case { 77 char *key; 78 char **value; 79 size_t size; 80 int flags; 81 int exp_err; 82 }; 83 struct test_case tc[] = { 84 { /* case 00, invalid flags */ 85 .key = long_key, 86 .value = &xattr_value, 87 .size = XATTR_TEST_VALUE_SIZE, 88 .flags = ~0, 89 .exp_err = EINVAL, 90 }, 91 { /* case 01, replace non-existing attribute */ 92 .key = XATTR_TEST_KEY, 93 .value = &xattr_value, 94 .size = XATTR_TEST_VALUE_SIZE, 95 .flags = XATTR_REPLACE, 96 .exp_err = ENODATA, 97 }, 98 { /* case 02, long key name */ 99 .key = long_key, 100 .value = &xattr_value, 101 .size = XATTR_TEST_VALUE_SIZE, 102 .flags = XATTR_CREATE, 103 .exp_err = ERANGE, 104 }, 105 { /* case 03, long value */ 106 .key = XATTR_TEST_KEY, 107 .value = &long_value, 108 .size = XATTR_SIZE_MAX + 1, 109 .flags = XATTR_CREATE, 110 .exp_err = E2BIG, 111 }, 112 { /* case 04, zero length value */ 113 .key = XATTR_TEST_KEY, 114 .value = &xattr_value, 115 .size = 0, 116 .flags = XATTR_CREATE, 117 .exp_err = 0, 118 }, 119 { /* case 05, create existing attribute */ 120 .key = XATTR_TEST_KEY, 121 .value = &xattr_value, 122 .size = XATTR_TEST_VALUE_SIZE, 123 .flags = XATTR_CREATE, 124 .exp_err = EEXIST, 125 }, 126 { /* case 06, replace existing attribute */ 127 .key = XATTR_TEST_KEY, 128 .value = &xattr_value, 129 .size = XATTR_TEST_VALUE_SIZE, 130 .flags = XATTR_REPLACE, 131 .exp_err = 0, 132 }, 133 }; 134 135 static void verify_setxattr(unsigned int i) 136 { 137 TEST(setxattr(FNAME, tc[i].key, *tc[i].value, tc[i].size, tc[i].flags)); 138 139 if (TEST_RETURN == -1 && TEST_ERRNO == EOPNOTSUPP) 140 tst_brk(TCONF, "setxattr() not supported"); 141 142 if (!tc[i].exp_err) { 143 if (TEST_RETURN) { 144 tst_res(TFAIL | TTERRNO, 145 "setxattr() failed with %li", TEST_RETURN); 146 return; 147 } 148 149 tst_res(TPASS, "setxattr() passed"); 150 return; 151 } 152 153 if (TEST_RETURN == 0) { 154 tst_res(TFAIL, "setxattr() passed unexpectedly"); 155 return; 156 } 157 158 if (TEST_ERRNO != tc[i].exp_err) { 159 tst_res(TFAIL | TTERRNO, "setxattr() should fail with %s", 160 tst_strerrno(tc[i].exp_err)); 161 return; 162 } 163 164 tst_res(TPASS | TTERRNO, "setxattr() failed"); 165 } 166 167 static void setup(void) 168 { 169 snprintf(long_key, 6, "%s", "user."); 170 memset(long_key + 5, 'k', XATTR_NAME_LEN - 5); 171 long_key[XATTR_NAME_LEN - 1] = '\0'; 172 173 long_value = SAFE_MALLOC(XATTR_SIZE_MAX + 2); 174 memset(long_value, 'v', XATTR_SIZE_MAX + 2); 175 long_value[XATTR_SIZE_MAX + 1] = '\0'; 176 177 SAFE_TOUCH(FNAME, 0644, NULL); 178 } 179 180 static struct tst_test test = { 181 .setup = setup, 182 .test = verify_setxattr, 183 .tcnt = ARRAY_SIZE(tc), 184 .mntpoint = MNTPOINT, 185 .mount_device = 1, 186 .all_filesystems = 1, 187 .needs_tmpdir = 1, 188 .needs_root = 1, 189 }; 190 191 #else /* HAVE_SYS_XATTR_H */ 192 TST_TEST_TCONF("<sys/xattr.h> does not exist"); 193 #endif 194