1*8012ca3fSmsaitoh /* $NetBSD: t_rwtoro.c,v 1.2 2020/05/14 08:34:18 msaitoh Exp $ */
2a9f23b81Shannken
3a9f23b81Shannken /*-
4a9f23b81Shannken * Copyright (c) 2017 The NetBSD Foundation, Inc.
5a9f23b81Shannken * All rights reserved.
6a9f23b81Shannken *
7a9f23b81Shannken * Redistribution and use in source and binary forms, with or without
8a9f23b81Shannken * modification, are permitted provided that the following conditions
9a9f23b81Shannken * are met:
10a9f23b81Shannken * 1. Redistributions of source code must retain the above copyright
11a9f23b81Shannken * notice, this list of conditions and the following disclaimer.
12a9f23b81Shannken * 2. Redistributions in binary form must reproduce the above copyright
13a9f23b81Shannken * notice, this list of conditions and the following disclaimer in the
14a9f23b81Shannken * documentation and/or other materials provided with the distribution.
15a9f23b81Shannken *
16a9f23b81Shannken * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17a9f23b81Shannken * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18a9f23b81Shannken * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19a9f23b81Shannken * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20a9f23b81Shannken * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21a9f23b81Shannken * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22a9f23b81Shannken * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23a9f23b81Shannken * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24a9f23b81Shannken * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25a9f23b81Shannken * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26a9f23b81Shannken * POSSIBILITY OF SUCH DAMAGE.
27a9f23b81Shannken */
28a9f23b81Shannken
29a9f23b81Shannken #include <sys/types.h>
30a9f23b81Shannken #include <sys/mount.h>
31a9f23b81Shannken #include <sys/stat.h>
32a9f23b81Shannken #include <sys/statvfs.h>
33a9f23b81Shannken
34a9f23b81Shannken #include <atf-c.h>
35a9f23b81Shannken #include <fcntl.h>
36a9f23b81Shannken #include <libgen.h>
37a9f23b81Shannken #include <stdlib.h>
38a9f23b81Shannken #include <unistd.h>
39a9f23b81Shannken
40a9f23b81Shannken #include <rump/rump_syscalls.h>
41a9f23b81Shannken #include <rump/rump.h>
42a9f23b81Shannken
43a9f23b81Shannken #include <miscfs/nullfs/null.h>
44a9f23b81Shannken #include <fs/tmpfs/tmpfs_args.h>
45a9f23b81Shannken
46a9f23b81Shannken #include "../common/h_fsmacros.h"
47a9f23b81Shannken #include "../../h_macros.h"
48a9f23b81Shannken
49a9f23b81Shannken static const char *unsupported = "fs does not support r/o remount";
50a9f23b81Shannken static char file_path[MAXPATHLEN];
51a9f23b81Shannken static int file_fd;
52a9f23b81Shannken
53a9f23b81Shannken /*
54a9f23b81Shannken * Remount the filesystem read-only and test errno.
55a9f23b81Shannken * Skip filesystems that don't implement read-write -> read-only.
56a9f23b81Shannken */
57a9f23b81Shannken static void
remount_ro(const atf_tc_t * tc,const char * mp,int expected_errno)58a9f23b81Shannken remount_ro(const atf_tc_t *tc, const char *mp, int expected_errno)
59a9f23b81Shannken {
60a9f23b81Shannken int error;
61a9f23b81Shannken union {
62a9f23b81Shannken struct tmpfs_args tmpfs;
63a9f23b81Shannken char data[4095];
64a9f23b81Shannken } mount_args;
65a9f23b81Shannken int mount_args_length;
66a9f23b81Shannken struct statvfs sbuf;
67a9f23b81Shannken
68a9f23b81Shannken if (FSTYPE_ZFS(tc))
69a9f23b81Shannken atf_tc_skip("%s", unsupported);
70a9f23b81Shannken
71a9f23b81Shannken /* Prepare mount arguments. */
72a9f23b81Shannken RL(rump_sys_statvfs1(mp, &sbuf, ST_WAIT));
73a9f23b81Shannken mount_args_length = sizeof(mount_args);
74a9f23b81Shannken memset(&mount_args, 0, mount_args_length);
75a9f23b81Shannken if (FSTYPE_TMPFS(tc))
76a9f23b81Shannken mount_args.tmpfs.ta_version = TMPFS_ARGS_VERSION;
77a9f23b81Shannken mount_args_length = rump_sys_mount(sbuf.f_fstypename, mp, MNT_GETARGS,
78a9f23b81Shannken &mount_args, mount_args_length);
79a9f23b81Shannken ATF_CHECK(mount_args_length >= 0);
80a9f23b81Shannken
81a9f23b81Shannken /* Remount and test result. */
82a9f23b81Shannken error = rump_sys_mount(sbuf.f_fstypename, mp, MNT_UPDATE | MNT_RDONLY,
83a9f23b81Shannken &mount_args, mount_args_length);
84a9f23b81Shannken if (errno == EOPNOTSUPP)
85a9f23b81Shannken atf_tc_skip("%s", unsupported);
86a9f23b81Shannken if (expected_errno == 0)
87a9f23b81Shannken ATF_CHECK(error == 0);
88a9f23b81Shannken else
89a9f23b81Shannken ATF_CHECK_ERRNO(expected_errno, error == -1);
90a9f23b81Shannken }
91a9f23b81Shannken
92a9f23b81Shannken static void
open_file_ro(const char * prefix)93a9f23b81Shannken open_file_ro(const char *prefix)
94a9f23b81Shannken {
95a9f23b81Shannken
96a9f23b81Shannken snprintf(file_path, sizeof(file_path), "%s/file", prefix);
97a9f23b81Shannken RL(file_fd = rump_sys_open(file_path, O_CREAT | O_RDWR, 0777));
98a9f23b81Shannken RL(rump_sys_close(file_fd));
99a9f23b81Shannken RL(file_fd = rump_sys_open(file_path, O_RDONLY));
100a9f23b81Shannken }
101a9f23b81Shannken
102a9f23b81Shannken static void
open_file_ro_unlink(const char * prefix)103a9f23b81Shannken open_file_ro_unlink(const char *prefix)
104a9f23b81Shannken {
105a9f23b81Shannken
106a9f23b81Shannken snprintf(file_path, sizeof(file_path), "%s/file", prefix);
107a9f23b81Shannken RL(file_fd = rump_sys_open(file_path, O_CREAT | O_RDWR, 0777));
108a9f23b81Shannken RL(rump_sys_close(file_fd));
109a9f23b81Shannken RL(file_fd = rump_sys_open(file_path, O_RDONLY));
110a9f23b81Shannken RL(rump_sys_unlink(file_path));
111a9f23b81Shannken }
112a9f23b81Shannken
113a9f23b81Shannken static void
open_file_rw(const char * prefix)114a9f23b81Shannken open_file_rw(const char *prefix)
115a9f23b81Shannken {
116a9f23b81Shannken
117a9f23b81Shannken snprintf(file_path, sizeof(file_path), "%s/file", prefix);
118a9f23b81Shannken RL(file_fd = rump_sys_open(file_path, O_CREAT | O_RDWR, 0777));
119a9f23b81Shannken }
120a9f23b81Shannken
121a9f23b81Shannken static void
close_file(const char * unused)122a9f23b81Shannken close_file(const char *unused)
123a9f23b81Shannken {
124a9f23b81Shannken
125a9f23b81Shannken RL(rump_sys_close(file_fd));
126a9f23b81Shannken }
127a9f23b81Shannken
128a9f23b81Shannken static void
basic_test(const atf_tc_t * tc,const char * mp,int expected_errno,bool use_layer,void (* pre)(const char *),void (* post)(const char *))129a9f23b81Shannken basic_test(const atf_tc_t *tc, const char *mp, int expected_errno,
130a9f23b81Shannken bool use_layer, void (*pre)(const char *), void (*post)(const char *))
131a9f23b81Shannken {
132a9f23b81Shannken const char *null_mount = "/nullm";
133a9f23b81Shannken struct null_args nargs;
134a9f23b81Shannken
135a9f23b81Shannken if (use_layer) {
136a9f23b81Shannken RL(rump_sys_mkdir(null_mount, 0777));
137a9f23b81Shannken memset(&nargs, 0, sizeof(nargs));
138*8012ca3fSmsaitoh nargs.nulla_target = __UNCONST(mp);
139a9f23b81Shannken RL(rump_sys_mount(MOUNT_NULL, null_mount, 0,
140a9f23b81Shannken &nargs, sizeof(nargs)));
141a9f23b81Shannken }
142a9f23b81Shannken if (pre)
143a9f23b81Shannken (*pre)(use_layer ? null_mount : mp);
144a9f23b81Shannken remount_ro(tc, mp, expected_errno);
145a9f23b81Shannken if (post)
146a9f23b81Shannken (*post)(use_layer ? null_mount : mp);
147a9f23b81Shannken if (use_layer)
148a9f23b81Shannken RL(rump_sys_unmount(null_mount, 0));
149a9f23b81Shannken }
150a9f23b81Shannken
151a9f23b81Shannken static void
noneopen(const atf_tc_t * tc,const char * mp)152a9f23b81Shannken noneopen(const atf_tc_t *tc, const char *mp)
153a9f23b81Shannken {
154a9f23b81Shannken
155a9f23b81Shannken basic_test(tc, mp, 0, false, NULL, NULL);
156a9f23b81Shannken }
157a9f23b81Shannken
158a9f23b81Shannken static void
readopen(const atf_tc_t * tc,const char * mp)159a9f23b81Shannken readopen(const atf_tc_t *tc, const char *mp)
160a9f23b81Shannken {
161a9f23b81Shannken
162a9f23b81Shannken basic_test(tc, mp, 0, false, open_file_ro, close_file);
163a9f23b81Shannken }
164a9f23b81Shannken
165a9f23b81Shannken static void
writeopen(const atf_tc_t * tc,const char * mp)166a9f23b81Shannken writeopen(const atf_tc_t *tc, const char *mp)
167a9f23b81Shannken {
168a9f23b81Shannken
169a9f23b81Shannken basic_test(tc, mp, EBUSY, false, open_file_rw, close_file);
170a9f23b81Shannken }
171a9f23b81Shannken
172a9f23b81Shannken static void
read_unlinked(const atf_tc_t * tc,const char * mp)173a9f23b81Shannken read_unlinked(const atf_tc_t *tc, const char *mp)
174a9f23b81Shannken {
175a9f23b81Shannken
176a9f23b81Shannken basic_test(tc, mp, EBUSY, false, open_file_ro_unlink, close_file);
177a9f23b81Shannken }
178a9f23b81Shannken
179a9f23b81Shannken static void
layer_noneopen(const atf_tc_t * tc,const char * mp)180a9f23b81Shannken layer_noneopen(const atf_tc_t *tc, const char *mp)
181a9f23b81Shannken {
182a9f23b81Shannken
183a9f23b81Shannken basic_test(tc, mp, 0, true, NULL, NULL);
184a9f23b81Shannken }
185a9f23b81Shannken
186a9f23b81Shannken static void
layer_readopen(const atf_tc_t * tc,const char * mp)187a9f23b81Shannken layer_readopen(const atf_tc_t *tc, const char *mp)
188a9f23b81Shannken {
189a9f23b81Shannken
190a9f23b81Shannken basic_test(tc, mp, 0, true, open_file_ro, close_file);
191a9f23b81Shannken }
192a9f23b81Shannken
193a9f23b81Shannken static void
layer_writeopen(const atf_tc_t * tc,const char * mp)194a9f23b81Shannken layer_writeopen(const atf_tc_t *tc, const char *mp)
195a9f23b81Shannken {
196a9f23b81Shannken
197a9f23b81Shannken basic_test(tc, mp, EBUSY, true, open_file_rw, close_file);
198a9f23b81Shannken }
199a9f23b81Shannken
200a9f23b81Shannken static void
layer_read_unlinked(const atf_tc_t * tc,const char * mp)201a9f23b81Shannken layer_read_unlinked(const atf_tc_t *tc, const char *mp)
202a9f23b81Shannken {
203a9f23b81Shannken
204a9f23b81Shannken basic_test(tc, mp, EBUSY, true, open_file_ro_unlink, close_file);
205a9f23b81Shannken }
206a9f23b81Shannken
207a9f23b81Shannken ATF_TC_FSAPPLY(noneopen, "remount r/o with no file open");
208a9f23b81Shannken ATF_TC_FSAPPLY(readopen, "remount r/o with file open for reading");
209a9f23b81Shannken ATF_TC_FSAPPLY(writeopen, "remount r/o with file open for writing");
210a9f23b81Shannken ATF_TC_FSAPPLY(read_unlinked,
211a9f23b81Shannken "remount r/o with unlinked file open for reading");
212a9f23b81Shannken ATF_TC_FSAPPLY(layer_noneopen, "remount r/o with no file open on layer");
213a9f23b81Shannken ATF_TC_FSAPPLY(layer_readopen,
214a9f23b81Shannken "remount r/o with file open for reading on layer");
215a9f23b81Shannken ATF_TC_FSAPPLY(layer_writeopen,
216a9f23b81Shannken "remount r/o with file open for writing on layer");
217a9f23b81Shannken ATF_TC_FSAPPLY(layer_read_unlinked,
218a9f23b81Shannken "remount r/o with unlinked file open for reading on layer");
219a9f23b81Shannken
ATF_TP_ADD_TCS(tp)220a9f23b81Shannken ATF_TP_ADD_TCS(tp)
221a9f23b81Shannken {
222a9f23b81Shannken
223a9f23b81Shannken ATF_TP_FSAPPLY(noneopen);
224a9f23b81Shannken ATF_TP_FSAPPLY(readopen);
225a9f23b81Shannken ATF_TP_FSAPPLY(writeopen);
226a9f23b81Shannken ATF_TP_FSAPPLY(read_unlinked);
227a9f23b81Shannken ATF_TP_FSAPPLY(layer_noneopen);
228a9f23b81Shannken ATF_TP_FSAPPLY(layer_readopen);
229a9f23b81Shannken ATF_TP_FSAPPLY(layer_writeopen);
230a9f23b81Shannken ATF_TP_FSAPPLY(layer_read_unlinked);
231a9f23b81Shannken
232a9f23b81Shannken return atf_no_error();
233a9f23b81Shannken }
234