1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2011 Red Hat, Inc. 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/* 7f08c3bdfSopenharmony_ci * Basic tests for setxattr(2) and make sure setxattr(2) handles error 8f08c3bdfSopenharmony_ci * conditions correctly. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * There are 7 test cases: 11f08c3bdfSopenharmony_ci * 1. Any other flags being set except XATTR_CREATE and XATTR_REPLACE, 12f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to EINVAL 13f08c3bdfSopenharmony_ci * 2. With XATTR_REPLACE flag set but the attribute does not exist, 14f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to ENODATA 15f08c3bdfSopenharmony_ci * 3. Create new attr with name length greater than XATTR_NAME_MAX(255) 16f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to ERANGE 17f08c3bdfSopenharmony_ci * 4. Create new attr whose value length is greater than XATTR_SIZE_MAX(65536) 18f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to E2BIG 19f08c3bdfSopenharmony_ci * 5. Create new attr whose value length is zero, 20f08c3bdfSopenharmony_ci * setxattr(2) should succeed 21f08c3bdfSopenharmony_ci * 6. Replace the attr value without XATTR_REPLACE flag being set, 22f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to EEXIST 23f08c3bdfSopenharmony_ci * 7. Replace attr value with XATTR_REPLACE flag being set, 24f08c3bdfSopenharmony_ci * setxattr(2) should succeed 25f08c3bdfSopenharmony_ci * 8. Create new attr whose key length is zero, 26f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to ERANGE 27f08c3bdfSopenharmony_ci * 9. Create new attr whose key is NULL, 28f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to EFAULT 29f08c3bdfSopenharmony_ci */ 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#include "config.h" 32f08c3bdfSopenharmony_ci#include <sys/types.h> 33f08c3bdfSopenharmony_ci#include <sys/stat.h> 34f08c3bdfSopenharmony_ci#include <sys/wait.h> 35f08c3bdfSopenharmony_ci#include <errno.h> 36f08c3bdfSopenharmony_ci#include <fcntl.h> 37f08c3bdfSopenharmony_ci#include <unistd.h> 38f08c3bdfSopenharmony_ci#include <signal.h> 39f08c3bdfSopenharmony_ci#include <stdio.h> 40f08c3bdfSopenharmony_ci#include <stdlib.h> 41f08c3bdfSopenharmony_ci#include <string.h> 42f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_XATTR_H 43f08c3bdfSopenharmony_ci# include <sys/xattr.h> 44f08c3bdfSopenharmony_ci#endif 45f08c3bdfSopenharmony_ci#include "tst_test.h" 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_XATTR_H 48f08c3bdfSopenharmony_ci#define XATTR_NAME_MAX 255 49f08c3bdfSopenharmony_ci#define XATTR_NAME_LEN (XATTR_NAME_MAX + 2) 50f08c3bdfSopenharmony_ci#define XATTR_SIZE_MAX 65536 51f08c3bdfSopenharmony_ci#define XATTR_TEST_KEY "user.testkey" 52f08c3bdfSopenharmony_ci#define XATTR_TEST_VALUE "this is a test value" 53f08c3bdfSopenharmony_ci#define XATTR_TEST_VALUE_SIZE 20 54f08c3bdfSopenharmony_ci#define MNTPOINT "mntpoint" 55f08c3bdfSopenharmony_ci#define FNAME MNTPOINT"/setxattr01testfile" 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic char long_key[XATTR_NAME_LEN]; 58f08c3bdfSopenharmony_cistatic char *long_value; 59f08c3bdfSopenharmony_cistatic char *xattr_value = XATTR_TEST_VALUE; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_cistruct test_case { 62f08c3bdfSopenharmony_ci char *key; 63f08c3bdfSopenharmony_ci char **value; 64f08c3bdfSopenharmony_ci size_t size; 65f08c3bdfSopenharmony_ci int flags; 66f08c3bdfSopenharmony_ci int exp_err; 67f08c3bdfSopenharmony_ci int keyneeded; 68f08c3bdfSopenharmony_ci}; 69f08c3bdfSopenharmony_cistruct test_case tc[] = { 70f08c3bdfSopenharmony_ci { /* case 00, invalid flags */ 71f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 72f08c3bdfSopenharmony_ci .value = &xattr_value, 73f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 74f08c3bdfSopenharmony_ci .flags = ~0, 75f08c3bdfSopenharmony_ci .exp_err = EINVAL, 76f08c3bdfSopenharmony_ci }, 77f08c3bdfSopenharmony_ci { /* case 01, replace non-existing attribute */ 78f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 79f08c3bdfSopenharmony_ci .value = &xattr_value, 80f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 81f08c3bdfSopenharmony_ci .flags = XATTR_REPLACE, 82f08c3bdfSopenharmony_ci .exp_err = ENODATA, 83f08c3bdfSopenharmony_ci }, 84f08c3bdfSopenharmony_ci { /* case 02, long key name */ 85f08c3bdfSopenharmony_ci .key = long_key, 86f08c3bdfSopenharmony_ci .value = &xattr_value, 87f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 88f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 89f08c3bdfSopenharmony_ci .exp_err = ERANGE, 90f08c3bdfSopenharmony_ci }, 91f08c3bdfSopenharmony_ci { /* case 03, long value */ 92f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 93f08c3bdfSopenharmony_ci .value = &long_value, 94f08c3bdfSopenharmony_ci .size = XATTR_SIZE_MAX + 1, 95f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 96f08c3bdfSopenharmony_ci .exp_err = E2BIG, 97f08c3bdfSopenharmony_ci }, 98f08c3bdfSopenharmony_ci { /* case 04, zero length value */ 99f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 100f08c3bdfSopenharmony_ci .value = &xattr_value, 101f08c3bdfSopenharmony_ci .size = 0, 102f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 103f08c3bdfSopenharmony_ci .exp_err = 0, 104f08c3bdfSopenharmony_ci }, 105f08c3bdfSopenharmony_ci { /* case 05, create existing attribute */ 106f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 107f08c3bdfSopenharmony_ci .value = &xattr_value, 108f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 109f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 110f08c3bdfSopenharmony_ci .exp_err = EEXIST, 111f08c3bdfSopenharmony_ci .keyneeded = 1, 112f08c3bdfSopenharmony_ci }, 113f08c3bdfSopenharmony_ci { /* case 06, replace existing attribute */ 114f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 115f08c3bdfSopenharmony_ci .value = &xattr_value, 116f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 117f08c3bdfSopenharmony_ci .flags = XATTR_REPLACE, 118f08c3bdfSopenharmony_ci .exp_err = 0, 119f08c3bdfSopenharmony_ci .keyneeded = 1, 120f08c3bdfSopenharmony_ci }, 121f08c3bdfSopenharmony_ci { /* case 07, zero length key */ 122f08c3bdfSopenharmony_ci .key = "", 123f08c3bdfSopenharmony_ci .value = &xattr_value, 124f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 125f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 126f08c3bdfSopenharmony_ci .exp_err = ERANGE, 127f08c3bdfSopenharmony_ci }, 128f08c3bdfSopenharmony_ci { /* case 08, NULL key */ 129f08c3bdfSopenharmony_ci .value = &xattr_value, 130f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 131f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 132f08c3bdfSopenharmony_ci .exp_err = EFAULT, 133f08c3bdfSopenharmony_ci }, 134f08c3bdfSopenharmony_ci}; 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_cistatic void verify_setxattr(unsigned int i) 137f08c3bdfSopenharmony_ci{ 138f08c3bdfSopenharmony_ci /* some tests might require existing keys for each iteration */ 139f08c3bdfSopenharmony_ci if (tc[i].keyneeded) { 140f08c3bdfSopenharmony_ci SAFE_SETXATTR(FNAME, tc[i].key, tc[i].value, tc[i].size, 141f08c3bdfSopenharmony_ci XATTR_CREATE); 142f08c3bdfSopenharmony_ci } 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_ci TEST(setxattr(FNAME, tc[i].key, *tc[i].value, tc[i].size, tc[i].flags)); 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) 147f08c3bdfSopenharmony_ci tst_brk(TCONF, "setxattr(2) not supported"); 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci /* success */ 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci if (!tc[i].exp_err) { 152f08c3bdfSopenharmony_ci if (TST_RET) { 153f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 154f08c3bdfSopenharmony_ci "setxattr(2) failed with %li", TST_RET); 155f08c3bdfSopenharmony_ci return; 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci /* this is needed for subsequent iterations */ 159f08c3bdfSopenharmony_ci SAFE_REMOVEXATTR(FNAME, tc[i].key); 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci tst_res(TPASS, "setxattr(2) passed"); 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci return; 164f08c3bdfSopenharmony_ci } 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci if (TST_RET == 0) { 167f08c3bdfSopenharmony_ci tst_res(TFAIL, "setxattr(2) passed unexpectedly"); 168f08c3bdfSopenharmony_ci return; 169f08c3bdfSopenharmony_ci } 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci /* error */ 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_ci if (tc[i].exp_err != TST_ERR) { 174f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "setxattr(2) should fail with %s", 175f08c3bdfSopenharmony_ci tst_strerrno(tc[i].exp_err)); 176f08c3bdfSopenharmony_ci return; 177f08c3bdfSopenharmony_ci } 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci /* key might have been added AND test might have failed, remove it */ 180f08c3bdfSopenharmony_ci if (tc[i].keyneeded) 181f08c3bdfSopenharmony_ci SAFE_REMOVEXATTR(FNAME, tc[i].key); 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "setxattr(2) failed"); 184f08c3bdfSopenharmony_ci} 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_cistatic void setup(void) 187f08c3bdfSopenharmony_ci{ 188f08c3bdfSopenharmony_ci size_t i = 0; 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci snprintf(long_key, 6, "%s", "user."); 191f08c3bdfSopenharmony_ci memset(long_key + 5, 'k', XATTR_NAME_LEN - 5); 192f08c3bdfSopenharmony_ci long_key[XATTR_NAME_LEN - 1] = '\0'; 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci long_value = SAFE_MALLOC(XATTR_SIZE_MAX + 2); 195f08c3bdfSopenharmony_ci memset(long_value, 'v', XATTR_SIZE_MAX + 2); 196f08c3bdfSopenharmony_ci long_value[XATTR_SIZE_MAX + 1] = '\0'; 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci SAFE_TOUCH(FNAME, 0644, NULL); 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(tc); i++) { 201f08c3bdfSopenharmony_ci if (!tc[i].key) 202f08c3bdfSopenharmony_ci tc[i].key = tst_get_bad_addr(NULL); 203f08c3bdfSopenharmony_ci } 204f08c3bdfSopenharmony_ci} 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_cistatic struct tst_test test = { 207f08c3bdfSopenharmony_ci .setup = setup, 208f08c3bdfSopenharmony_ci .test = verify_setxattr, 209f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tc), 210f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 211f08c3bdfSopenharmony_ci .mount_device = 1, 212f08c3bdfSopenharmony_ci .all_filesystems = 1, 213f08c3bdfSopenharmony_ci .needs_root = 1, 214f08c3bdfSopenharmony_ci}; 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci#else /* HAVE_SYS_XATTR_H */ 217f08c3bdfSopenharmony_ciTST_TEST_TCONF("<sys/xattr.h> does not exist"); 218f08c3bdfSopenharmony_ci#endif 219