xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/open_by_handle_at/open_by_handle_at02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2020 Viresh Kumar <[email protected]>
4  */
5 
6 /*\
7  * [Description]
8  *
9  * Failure tests for open_by_handle_at().
10  */
11 #define _GNU_SOURCE
12 #include <linux/capability.h>
13 #include "tst_capability.h"
14 #include "lapi/name_to_handle_at.h"
15 
16 #define TEST_FILE "test_file"
17 #define FOO_SYMLINK "foo_symlink"
18 
19 static struct file_handle high_fh = {.handle_bytes = MAX_HANDLE_SZ + 1}, *high_fhp = &high_fh;
20 static struct file_handle zero_fh, *zero_fhp = &zero_fh;
21 static struct file_handle *valid_fhp, *invalid_fhp, *link_fhp;
22 
23 static struct tst_cap cap_req = TST_CAP(TST_CAP_REQ, CAP_DAC_READ_SEARCH);
24 static struct tst_cap cap_drop = TST_CAP(TST_CAP_DROP, CAP_DAC_READ_SEARCH);
25 
26 static struct tcase {
27 	const char *name;
28 	int dfd;
29 	struct file_handle **fhp;
30 	int flags;
31 	int cap;
32 	int exp_errno;
33 } tcases[] = {
34 	{"invalid-dfd", -1, &valid_fhp, O_RDWR, 0, EBADF},
35 	{"stale-dfd", 0, &valid_fhp, O_RDWR, 0, ESTALE},
36 	{"invalid-file-handle", AT_FDCWD, &invalid_fhp, O_RDWR, 0, EFAULT},
37 	{"high-file-handle-size", AT_FDCWD, &high_fhp, O_RDWR, 0, EINVAL},
38 	{"zero-file-handle-size", AT_FDCWD, &zero_fhp, O_RDWR, 0, EINVAL},
39 	{"no-capability", AT_FDCWD, &valid_fhp, O_RDWR, 1, EPERM},
40 	{"symlink", AT_FDCWD, &link_fhp, O_RDWR, 0, ELOOP},
41 };
42 
setup(void)43 static void setup(void)
44 {
45 	void *faulty_address;
46 	int mount_id;
47 
48 	SAFE_TOUCH(TEST_FILE, 0600, NULL);
49 	SAFE_SYMLINK(TEST_FILE, FOO_SYMLINK);
50 	faulty_address = tst_get_bad_addr(NULL);
51 	invalid_fhp = faulty_address;
52 
53 	valid_fhp = allocate_file_handle(AT_FDCWD, TEST_FILE);
54 	if (!valid_fhp)
55 		return;
56 
57 	TEST(name_to_handle_at(AT_FDCWD, TEST_FILE, valid_fhp, &mount_id, 0));
58 	if (TST_RET)
59 		tst_res(TFAIL | TTERRNO, "name_to_handle_at() failed");
60 
61 	/* Symlink's file handle */
62 	link_fhp = tst_alloc(sizeof(*link_fhp) + valid_fhp->handle_bytes);
63 	link_fhp->handle_type = valid_fhp->handle_type;
64 	link_fhp->handle_bytes = valid_fhp->handle_bytes;
65 
66 	TEST(name_to_handle_at(AT_FDCWD, FOO_SYMLINK, link_fhp, &mount_id, 0));
67 	if (TST_RET)
68 		tst_res(TFAIL | TTERRNO, "name_to_handle_at() failed");
69 }
70 
run(unsigned int n)71 static void run(unsigned int n)
72 {
73 	struct tcase *tc = &tcases[n];
74 	int fd;
75 
76 	if (tc->cap)
77 		tst_cap_action(&cap_drop);
78 
79 	TEST(fd = open_by_handle_at(tc->dfd, *tc->fhp, tc->flags));
80 
81 	if (tc->cap)
82 		tst_cap_action(&cap_req);
83 
84 	if (TST_RET != -1) {
85 		SAFE_CLOSE(fd);
86 		tst_res(TFAIL, "%s: open_by_handle_at() passed unexpectedly",
87 			tc->name);
88 		return;
89 	}
90 
91 	if (tc->exp_errno != TST_ERR) {
92 		tst_res(TFAIL | TTERRNO,
93 			"%s: open_by_handle_at() should fail with %s", tc->name,
94 			tst_strerrno(tc->exp_errno));
95 		return;
96 	}
97 
98 	tst_res(TPASS | TTERRNO, "%s: open_by_handle_at() failed as expected",
99 		tc->name);
100 }
101 
102 static struct tst_test test = {
103 	.tcnt = ARRAY_SIZE(tcases),
104 	.test = run,
105 	.setup = setup,
106 	.needs_tmpdir = 1,
107 	.needs_root = 1,
108 };
109