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