1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2011 Red Hat, Inc.
4 * Copyright (c) Linux Test Project, 2012-2022
5 * Copyright (c) 2023 Marius Kittler <[email protected]>
6 */
7
8 /*\
9 * [Description]
10 *
11 * In the user.* namespace, only regular files and directories can
12 * have extended attributes. Otherwise getxattr(2) will return -1
13 * and set errno to ENODATA.
14 *
15 * There are 4 test cases:
16 *
17 * - Get attribute from a FIFO, setxattr(2) should return -1 and
18 * set errno to ENODATA
19 * - Get attribute from a char special file, setxattr(2) should
20 * return -1 and set errno to ENODATA
21 * - Get attribute from a block special file, setxattr(2) should
22 * return -1 and set errno to ENODATA
23 * - Get attribute from a UNIX domain socket, setxattr(2) should
24 * return -1 and set errno to ENODATA
25 */
26
27 #include <sys/types.h>
28 #include <sys/sysmacros.h>
29 #include <sys/xattr.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include "tst_res_flags.h"
34 #include "tst_test.h"
35 #include "tst_test_macros.h"
36
37 #define MNTPOINT "mntpoint"
38 #define FNAME MNTPOINT"/getxattr02"
39 #define XATTR_TEST_KEY "user.testkey"
40
41 #define FIFO "getxattr02fifo"
42 #define CHR "getxattr02chr"
43 #define BLK "getxattr02blk"
44 #define SOCK "getxattr02sock"
45
46 static struct test_case {
47 const char *desc;
48 char *fname;
49 int mode;
50 } tcases[] = {
51 {
52 .desc = "get attr from fifo",
53 .fname = FNAME FIFO,
54 .mode = S_IFIFO,
55 },
56 {
57 .desc = "get attr from char special",
58 .fname = FNAME CHR,
59 .mode = S_IFCHR,
60 },
61 {
62 .desc = "get attr from block special",
63 .fname = FNAME BLK,
64 .mode = S_IFBLK,
65 },
66 {
67 .desc = "get attr from UNIX domain socket",
68 .fname = FNAME SOCK,
69 .mode = S_IFSOCK,
70 },
71 };
72
run(unsigned int i)73 static void run(unsigned int i)
74 {
75 char buf[BUFSIZ];
76 struct test_case *tc = &tcases[i];
77 dev_t dev = tc->mode == S_IFCHR ? makedev(1, 3) : 0u;
78
79 if (mknod(tc->fname, tc->mode | 0777, dev) < 0)
80 tst_brk(TBROK | TERRNO, "create %s (mode %i) failed (%s)",
81 tc->fname, tc->mode, tc->desc);
82
83 TEST(getxattr(tc->fname, XATTR_TEST_KEY, buf, BUFSIZ));
84 if (TST_RET == -1 && TST_ERR == ENODATA)
85 tst_res(TPASS | TTERRNO, "%s: expected return value",
86 tc->desc);
87 else
88 tst_res(TFAIL | TTERRNO,
89 "%s: unexpected return value - expected errno %d - got",
90 tc->desc, ENODATA);
91
92 unlink(tc->fname);
93 }
94
setup(void)95 static void setup(void)
96 {
97 /* assert xattr support in the current filesystem */
98 SAFE_TOUCH(FNAME, 0644, NULL);
99 TEST(setxattr(FNAME, "user.test", "test", 4, XATTR_CREATE));
100 if (TST_ERR == ENOTSUP)
101 tst_brk(TCONF,
102 "No xattr support in fs or mount without user_xattr option");
103 else if (TST_RET != 0)
104 tst_brk(TBROK | TTERRNO, "setxattr failed");
105 }
106
107 static struct tst_test test = {
108 .all_filesystems = 1,
109 .needs_root = 1,
110 .mntpoint = MNTPOINT,
111 .mount_device = 1,
112 .skip_filesystems = (const char *const []) {
113 "ramfs",
114 "nfs",
115 NULL
116 },
117 .setup = setup,
118 .test = run,
119 .tcnt = ARRAY_SIZE(tcases)
120 };
121