1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2018 Linaro Limited. All rights reserved.
4 * Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
5 */
6
7 /*
8 * Test Name: lremovexattr01
9 *
10 * Description:
11 * lremovexattr(2) removes the extended attribute identified by a name and
12 * associated with a given path in the filesystem. Unlike removexattr(2),
13 * lremovexattr(2) removes the attribute from the symbolic link only, and not
14 * the file. This test verifies that a simple call to lremovexattr(2) removes,
15 * indeed, a previously set attribute key/value from a symbolic link, and the
16 * symbolic link _only_.
17 *
18 * Note:
19 * According to attr(5), extended attributes are interpreted differently from
20 * regular files, directories and symbolic links. User attributes are only
21 * allowed for regular files and directories, thus the need of using trusted.*
22 * attributes for this test.
23 */
24
25 #include "config.h"
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31
32 #ifdef HAVE_SYS_XATTR_H
33 # include <sys/xattr.h>
34 #endif
35
36 #include "tst_test.h"
37
38 #ifdef HAVE_SYS_XATTR_H
39
40 #define ENOATTR ENODATA
41
42 #define XATTR_KEY "trusted.key1"
43 #define XATTR_VALUE "file and link"
44 #define XATTR_VALUE_SIZE 13
45
46 #define MNTPOINT "mntpoint"
47 #define FILENAME MNTPOINT"/lremovexattr01testfile"
48 #define SYMLINK MNTPOINT"/lremovexattr01symlink"
49
50 static char got_value[XATTR_VALUE_SIZE];
51
verify_lremovexattr(void)52 static void verify_lremovexattr(void)
53 {
54 /* set attribute on both: file and symlink */
55
56 SAFE_SETXATTR(FILENAME, XATTR_KEY, XATTR_VALUE, XATTR_VALUE_SIZE,
57 XATTR_CREATE);
58
59 SAFE_LSETXATTR(SYMLINK, XATTR_KEY, XATTR_VALUE, XATTR_VALUE_SIZE,
60 XATTR_CREATE);
61
62 /* remove attribute from symlink only */
63
64 TEST(lremovexattr(SYMLINK, XATTR_KEY));
65
66 if (TST_RET != 0) {
67 tst_res(TFAIL | TTERRNO, "lremovexattr(2) failed");
68 return;
69 }
70
71 /* make sure attribute is gone from symlink */
72
73 memset(&got_value, 0, XATTR_VALUE_SIZE);
74
75 TEST(lgetxattr(SYMLINK, XATTR_KEY, &got_value, XATTR_VALUE_SIZE));
76
77 if (TST_RET >= 0) {
78 tst_res(TFAIL, "lremovexattr(2) did not work");
79 return;
80 }
81
82 if (TST_ERR != ENOATTR) {
83 tst_brk(TBROK | TTERRNO, "lgetxattr(2) failed unexpectedly");
84 return;
85 }
86
87 /* check if file is unchanged, like it should be */
88
89 memset(&got_value, 0, XATTR_VALUE_SIZE);
90
91 TEST(getxattr(FILENAME, XATTR_KEY, &got_value, XATTR_VALUE_SIZE));
92
93 if (TST_RET <= 0) {
94 tst_res(TFAIL, "lremovexattr(2) deleted file attribute");
95 return;
96 }
97
98 if (strncmp(got_value, XATTR_VALUE, XATTR_VALUE_SIZE)) {
99 tst_res(TFAIL, "lremovexattr(2) changed file attribute");
100 return;
101 }
102
103 /* cleanup file attribute for iteration */
104
105 SAFE_REMOVEXATTR(FILENAME, XATTR_KEY);
106
107 tst_res(TPASS, "lremovexattr(2) removed attribute as expected");
108 }
109
setup(void)110 static void setup(void)
111 {
112 SAFE_TOUCH(FILENAME, 0644, NULL);
113
114 if (symlink(FILENAME, SYMLINK) < 0)
115 tst_brk(TCONF, "symlink() not supported");
116 }
117
118 static struct tst_test test = {
119 .setup = setup,
120 .test_all = verify_lremovexattr,
121 .mntpoint = MNTPOINT,
122 .mount_device = 1,
123 .all_filesystems = 1,
124 .needs_root = 1,
125 };
126
127 #else /* HAVE_SYS_XATTR_H */
128 TST_TEST_TCONF("<sys/xattr.h> does not exist");
129 #endif
130