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 * In the user.* namespace, only regular files and directories can 8f08c3bdfSopenharmony_ci * have extended attributes. Otherwise setxattr(2) will return -1 9f08c3bdfSopenharmony_ci * and set errno to EPERM. 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * There are 7 test cases: 12f08c3bdfSopenharmony_ci * 1. Set attribute to a regular file, setxattr(2) should succeed 13f08c3bdfSopenharmony_ci * 2. Set attribute to a directory, setxattr(2) should succeed 14f08c3bdfSopenharmony_ci * 3. Set attribute to a symlink which points to the regular file, 15f08c3bdfSopenharmony_ci * setxattr(2) should return -1 and set errno to EEXIST 16f08c3bdfSopenharmony_ci * 4. Set attribute to a FIFO, setxattr(2) should return -1 and set 17f08c3bdfSopenharmony_ci * errno to EPERM 18f08c3bdfSopenharmony_ci * 5. Set attribute to a char special file, setxattr(2) should 19f08c3bdfSopenharmony_ci * return -1 and set errno to EPERM 20f08c3bdfSopenharmony_ci * 6. Set attribute to a block special file, setxattr(2) should 21f08c3bdfSopenharmony_ci * return -1 and set errno to EPERM 22f08c3bdfSopenharmony_ci * 7. Set attribute to a UNIX domain socket, setxattr(2) should 23f08c3bdfSopenharmony_ci * return -1 and set errno to EPERM 24f08c3bdfSopenharmony_ci */ 25f08c3bdfSopenharmony_ci 26f08c3bdfSopenharmony_ci#include "config.h" 27f08c3bdfSopenharmony_ci#include <sys/types.h> 28f08c3bdfSopenharmony_ci#include <sys/stat.h> 29f08c3bdfSopenharmony_ci#include <sys/sysmacros.h> 30f08c3bdfSopenharmony_ci#include <sys/wait.h> 31f08c3bdfSopenharmony_ci#include <errno.h> 32f08c3bdfSopenharmony_ci#include <fcntl.h> 33f08c3bdfSopenharmony_ci#include <unistd.h> 34f08c3bdfSopenharmony_ci#include <signal.h> 35f08c3bdfSopenharmony_ci#include <stdio.h> 36f08c3bdfSopenharmony_ci#include <stdlib.h> 37f08c3bdfSopenharmony_ci#include <string.h> 38f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_XATTR_H 39f08c3bdfSopenharmony_ci# include <sys/xattr.h> 40f08c3bdfSopenharmony_ci#endif 41f08c3bdfSopenharmony_ci#include "tst_test.h" 42f08c3bdfSopenharmony_ci 43f08c3bdfSopenharmony_ci#ifdef HAVE_SYS_XATTR_H 44f08c3bdfSopenharmony_ci#define XATTR_TEST_KEY "user.testkey" 45f08c3bdfSopenharmony_ci#define XATTR_TEST_VALUE "this is a test value" 46f08c3bdfSopenharmony_ci#define XATTR_TEST_VALUE_SIZE 20 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci#define OFFSET 10 49f08c3bdfSopenharmony_ci#define FILENAME "setxattr02testfile" 50f08c3bdfSopenharmony_ci#define DIRNAME "setxattr02testdir" 51f08c3bdfSopenharmony_ci#define SYMLINK "setxattr02symlink" 52f08c3bdfSopenharmony_ci#define FIFO "setxattr02fifo" 53f08c3bdfSopenharmony_ci#define CHR "setxattr02chr" 54f08c3bdfSopenharmony_ci#define BLK "setxattr02blk" 55f08c3bdfSopenharmony_ci#define SOCK "setxattr02sock" 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistruct test_case { 58f08c3bdfSopenharmony_ci char *fname; 59f08c3bdfSopenharmony_ci char *key; 60f08c3bdfSopenharmony_ci char *value; 61f08c3bdfSopenharmony_ci size_t size; 62f08c3bdfSopenharmony_ci int flags; 63f08c3bdfSopenharmony_ci int exp_err; 64f08c3bdfSopenharmony_ci int needskeyset; 65f08c3bdfSopenharmony_ci}; 66f08c3bdfSopenharmony_cistatic struct test_case tc[] = { 67f08c3bdfSopenharmony_ci { /* case 00, set attr to reg */ 68f08c3bdfSopenharmony_ci .fname = FILENAME, 69f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 70f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 71f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 72f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 73f08c3bdfSopenharmony_ci .exp_err = 0, 74f08c3bdfSopenharmony_ci }, 75f08c3bdfSopenharmony_ci { /* case 01, set attr to dir */ 76f08c3bdfSopenharmony_ci .fname = DIRNAME, 77f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 78f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 79f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 80f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 81f08c3bdfSopenharmony_ci .exp_err = 0, 82f08c3bdfSopenharmony_ci }, 83f08c3bdfSopenharmony_ci { /* case 02, set attr to symlink */ 84f08c3bdfSopenharmony_ci .fname = SYMLINK, 85f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 86f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 87f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 88f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 89f08c3bdfSopenharmony_ci .exp_err = EEXIST, 90f08c3bdfSopenharmony_ci .needskeyset = 1, 91f08c3bdfSopenharmony_ci }, 92f08c3bdfSopenharmony_ci { /* case 03, set attr to fifo */ 93f08c3bdfSopenharmony_ci .fname = FIFO, 94f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 95f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 96f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 97f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 98f08c3bdfSopenharmony_ci .exp_err = EPERM, 99f08c3bdfSopenharmony_ci }, 100f08c3bdfSopenharmony_ci { /* case 04, set attr to character special */ 101f08c3bdfSopenharmony_ci .fname = CHR, 102f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 103f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 104f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 105f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 106f08c3bdfSopenharmony_ci .exp_err = EPERM, 107f08c3bdfSopenharmony_ci }, 108f08c3bdfSopenharmony_ci { /* case 05, set attr to block special */ 109f08c3bdfSopenharmony_ci .fname = BLK, 110f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 111f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 112f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 113f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 114f08c3bdfSopenharmony_ci .exp_err = EPERM, 115f08c3bdfSopenharmony_ci }, 116f08c3bdfSopenharmony_ci { /* case 06, set attr to socket */ 117f08c3bdfSopenharmony_ci .fname = SOCK, 118f08c3bdfSopenharmony_ci .key = XATTR_TEST_KEY, 119f08c3bdfSopenharmony_ci .value = XATTR_TEST_VALUE, 120f08c3bdfSopenharmony_ci .size = XATTR_TEST_VALUE_SIZE, 121f08c3bdfSopenharmony_ci .flags = XATTR_CREATE, 122f08c3bdfSopenharmony_ci .exp_err = EPERM, 123f08c3bdfSopenharmony_ci }, 124f08c3bdfSopenharmony_ci}; 125f08c3bdfSopenharmony_ci 126f08c3bdfSopenharmony_cistatic void verify_setxattr(unsigned int i) 127f08c3bdfSopenharmony_ci{ 128f08c3bdfSopenharmony_ci /* some tests might require existing keys for each iteration */ 129f08c3bdfSopenharmony_ci if (tc[i].needskeyset) { 130f08c3bdfSopenharmony_ci SAFE_SETXATTR(tc[i].fname, tc[i].key, tc[i].value, tc[i].size, 131f08c3bdfSopenharmony_ci XATTR_CREATE); 132f08c3bdfSopenharmony_ci } 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci TEST(setxattr(tc[i].fname, tc[i].key, tc[i].value, tc[i].size, 135f08c3bdfSopenharmony_ci tc[i].flags)); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci if (TST_RET == -1 && TST_ERR == EOPNOTSUPP) 138f08c3bdfSopenharmony_ci tst_brk(TCONF, "setxattr(2) not supported"); 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci /* success */ 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ci if (!tc[i].exp_err) { 143f08c3bdfSopenharmony_ci if (TST_RET) { 144f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 145f08c3bdfSopenharmony_ci "setxattr(2) on %s failed with %li", 146f08c3bdfSopenharmony_ci tc[i].fname + OFFSET, TST_RET); 147f08c3bdfSopenharmony_ci return; 148f08c3bdfSopenharmony_ci } 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci /* this is needed for subsequent iterations */ 151f08c3bdfSopenharmony_ci SAFE_REMOVEXATTR(tc[i].fname, tc[i].key); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci tst_res(TPASS, "setxattr(2) on %s passed", 154f08c3bdfSopenharmony_ci tc[i].fname + OFFSET); 155f08c3bdfSopenharmony_ci return; 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci if (TST_RET == 0) { 159f08c3bdfSopenharmony_ci tst_res(TFAIL, "setxattr(2) on %s passed unexpectedly", 160f08c3bdfSopenharmony_ci tc[i].fname + OFFSET); 161f08c3bdfSopenharmony_ci return; 162f08c3bdfSopenharmony_ci } 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci /* fail */ 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci if (tc[i].exp_err != TST_ERR) { 167f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 168f08c3bdfSopenharmony_ci "setxattr(2) on %s should have failed with %s", 169f08c3bdfSopenharmony_ci tc[i].fname + OFFSET, 170f08c3bdfSopenharmony_ci tst_strerrno(tc[i].exp_err)); 171f08c3bdfSopenharmony_ci return; 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ci /* key might have been added AND test might have failed, remove it */ 175f08c3bdfSopenharmony_ci if (tc[i].needskeyset) 176f08c3bdfSopenharmony_ci SAFE_REMOVEXATTR(tc[i].fname, tc[i].key); 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, "setxattr(2) on %s failed", 179f08c3bdfSopenharmony_ci tc[i].fname + OFFSET); 180f08c3bdfSopenharmony_ci} 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_cistatic void setup(void) 183f08c3bdfSopenharmony_ci{ 184f08c3bdfSopenharmony_ci dev_t dev = makedev(1, 3); 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci SAFE_TOUCH(FILENAME, 0644, NULL); 187f08c3bdfSopenharmony_ci SAFE_MKDIR(DIRNAME, 0644); 188f08c3bdfSopenharmony_ci SAFE_SYMLINK(FILENAME, SYMLINK); 189f08c3bdfSopenharmony_ci SAFE_MKNOD(FIFO, S_IFIFO | 0777, 0); 190f08c3bdfSopenharmony_ci SAFE_MKNOD(CHR, S_IFCHR | 0777, dev); 191f08c3bdfSopenharmony_ci SAFE_MKNOD(BLK, S_IFBLK | 0777, 0); 192f08c3bdfSopenharmony_ci SAFE_MKNOD(SOCK, S_IFSOCK | 0777, 0); 193f08c3bdfSopenharmony_ci} 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_cistatic struct tst_test test = { 196f08c3bdfSopenharmony_ci .setup = setup, 197f08c3bdfSopenharmony_ci .test = verify_setxattr, 198f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tc), 199f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 200f08c3bdfSopenharmony_ci .needs_root = 1, 201f08c3bdfSopenharmony_ci}; 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci#else /* HAVE_SYS_XATTR_H */ 204f08c3bdfSopenharmony_ciTST_TEST_TCONF("<sys/xattr.h> does not exist"); 205f08c3bdfSopenharmony_ci#endif 206