xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/unlink/unlink09.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2024 FUJITSU LIMITED. All Rights Reserved.
4  * Author: Yang Xu <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Verify that unlink(2) fails with
11  *
12  * - EPERM when target file is marked as immutable or append-only
13  * - EROFS when target file is on a read-only filesystem.
14  */
15 
16 #include <sys/ioctl.h>
17 #include "tst_test.h"
18 #include "lapi/fs.h"
19 
20 #define TEST_EPERM_IMMUTABLE "test_eperm_immutable"
21 #define TEST_EPERM_APPEND_ONLY "test_eperm_append_only"
22 #define DIR_EROFS "erofs"
23 #define TEST_EROFS "erofs/test_erofs"
24 
25 static int fd_immutable;
26 static int fd_append_only;
27 
28 static struct test_case_t {
29 	char *filename;
30 	int *fd;
31 	int flag;
32 	int expected_errno;
33 	char *desc;
34 } tcases[] = {
35 	{TEST_EPERM_IMMUTABLE, &fd_immutable, FS_IMMUTABLE_FL, EPERM,
36 		"target file is immutable"},
37 	{TEST_EPERM_APPEND_ONLY, &fd_append_only, FS_APPEND_FL, EPERM,
38 		"target file is append-only"},
39 	{TEST_EROFS, NULL, 0, EROFS, "target file in read-only filesystem"},
40 };
41 
setup(void)42 static void setup(void)
43 {
44 	int attr;
45 
46 	fd_immutable = SAFE_OPEN(TEST_EPERM_IMMUTABLE, O_CREAT, 0600);
47 	SAFE_IOCTL(fd_immutable, FS_IOC_GETFLAGS, &attr);
48 	attr |= FS_IMMUTABLE_FL;
49 	SAFE_IOCTL(fd_immutable, FS_IOC_SETFLAGS, &attr);
50 
51 	fd_append_only = SAFE_OPEN(TEST_EPERM_APPEND_ONLY, O_CREAT, 0600);
52 	SAFE_IOCTL(fd_append_only, FS_IOC_GETFLAGS, &attr);
53 	attr |= FS_APPEND_FL;
54 	SAFE_IOCTL(fd_append_only, FS_IOC_SETFLAGS, &attr);
55 }
56 
cleanup(void)57 static void cleanup(void)
58 {
59 	int attr;
60 
61 	SAFE_IOCTL(fd_immutable, FS_IOC_GETFLAGS, &attr);
62 	attr &= ~FS_IMMUTABLE_FL;
63 	SAFE_IOCTL(fd_immutable, FS_IOC_SETFLAGS, &attr);
64 	SAFE_CLOSE(fd_immutable);
65 
66 	SAFE_IOCTL(fd_append_only, FS_IOC_GETFLAGS, &attr);
67 	attr &= ~FS_APPEND_FL;
68 	SAFE_IOCTL(fd_append_only, FS_IOC_SETFLAGS, &attr);
69 	SAFE_CLOSE(fd_append_only);
70 }
71 
verify_unlink(unsigned int i)72 static void verify_unlink(unsigned int i)
73 {
74 	struct test_case_t *tc = &tcases[i];
75 	int attr;
76 
77 	TST_EXP_FAIL(unlink(tc->filename), tc->expected_errno, "%s", tc->desc);
78 
79 	/* If unlink() succeeded unexpectedly, test file should be restored. */
80 	if (!TST_RET) {
81 		if (tc->fd) {
82 			*(tc->fd) = SAFE_OPEN(tc->filename, O_CREAT, 0600);
83 			if (tc->flag) {
84 				SAFE_IOCTL(*(tc->fd), FS_IOC_GETFLAGS, &attr);
85 				attr |= tc->flag;
86 				SAFE_IOCTL(*(tc->fd), FS_IOC_SETFLAGS, &attr);
87 			}
88 		} else {
89 			SAFE_TOUCH(tc->filename, 0600, 0);
90 		}
91 	}
92 }
93 
94 static struct tst_test test = {
95 	.setup = setup,
96 	.tcnt = ARRAY_SIZE(tcases),
97 	.cleanup = cleanup,
98 	.test = verify_unlink,
99 	.needs_rofs = 1,
100 	.mntpoint = DIR_EROFS,
101 	.needs_root = 1,
102 };
103