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