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