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