xref: /freebsd/sys/contrib/openzfs/lib/libzfs/os/linux/libzfs_util_os.c (revision 8ac904ce090b1c2e355da8aa122ca2252183f4e1)
1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or https://opensource.org/licenses/CDDL-1.0.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright (c) 2021 Klara, Inc.
25  */
26 
27 #include <alloca.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <libintl.h>
31 #include <math.h>
32 #include <poll.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <strings.h>
37 #include <sys/inotify.h>
38 #include <sys/mntent.h>
39 #include <sys/mnttab.h>
40 #include <sys/stat.h>
41 #include <sys/timerfd.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <unistd.h>
45 
46 #include <libzfs.h>
47 #include <libzfs_core.h>
48 
49 #include "../../libzfs_impl.h"
50 #include "zfs_prop.h"
51 #include <libzutil.h>
52 #include <sys/zfs_sysfs.h>
53 
54 #define	ZDIFF_SHARESDIR		"/.zfs/shares/"
55 
56 const char *
libzfs_error_init(int error)57 libzfs_error_init(int error)
58 {
59 	switch (error) {
60 	case ENXIO:
61 		return (dgettext(TEXT_DOMAIN, "The ZFS modules are not "
62 		    "loaded.\nTry running 'modprobe zfs' as root "
63 		    "to load them."));
64 	case ENOENT:
65 		return (dgettext(TEXT_DOMAIN, "/dev/zfs and /proc/self/mounts "
66 		    "are required.\nTry running 'udevadm trigger' and 'mount "
67 		    "-t proc proc /proc' as root."));
68 	case ENOEXEC:
69 		return (dgettext(TEXT_DOMAIN, "The ZFS modules cannot be "
70 		    "auto-loaded.\nTry running 'modprobe zfs' as "
71 		    "root to manually load them."));
72 	case EACCES:
73 		return (dgettext(TEXT_DOMAIN, "Permission denied the "
74 		    "ZFS utilities must be run as root."));
75 	default:
76 		return (dgettext(TEXT_DOMAIN, "Failed to initialize the "
77 		    "libzfs library."));
78 	}
79 }
80 
81 static int
in_container(void)82 in_container(void)
83 {
84 	char buffer[4096];
85 	ssize_t count;
86 	int fd;
87 
88 	if (access("/run/systemd/container", R_OK) == 0)
89 		return (1);
90 
91 	fd = open("/proc/1/cgroup", O_RDONLY);
92 	if (fd == -1)
93 		return (0);
94 
95 	count = read(fd, buffer, sizeof (buffer) - 1);
96 	close(fd);
97 
98 	if (count <= 0)
99 		return (0);
100 
101 	buffer[count] = '\0';
102 
103 	if (strstr(buffer, "docker") ||
104 	    strstr(buffer, "containerd") ||
105 	    strstr(buffer, "kubepods") ||
106 	    strstr(buffer, "lxc")) {
107 		return (1);
108 	}
109 
110 	return (0);
111 }
112 
113 /*
114  * zfs(4) is loaded by udev if there's a fstype=zfs device present,
115  * but if there isn't, load them automatically;
116  * always wait for ZFS_DEV to appear via udev.
117  *
118  * Environment variables:
119  * - ZFS_MODULE_TIMEOUT="<seconds>" - Seconds to wait for ZFS_DEV,
120  *                                    defaults to 10, max. 10 min.
121  */
122 int
libzfs_load_module(void)123 libzfs_load_module(void)
124 {
125 	if (access(ZFS_DEV, F_OK) == 0)
126 		return (0);
127 
128 	if (access(ZFS_SYSFS_DIR, F_OK) != 0) {
129 		char *argv[] = {(char *)"modprobe", (char *)"zfs", NULL};
130 		if (libzfs_run_process("modprobe", argv, 0))
131 			return (ENOEXEC);
132 
133 		if (access(ZFS_SYSFS_DIR, F_OK) != 0)
134 			return (ENXIO);
135 	}
136 
137 	const char *timeout_str = getenv("ZFS_MODULE_TIMEOUT");
138 	int seconds = 10;
139 
140 	/* Set timeout to zero if inside of a container */
141 	if (in_container())
142 		seconds = 0;
143 
144 	if (timeout_str)
145 		seconds = MIN(strtol(timeout_str, NULL, 0), 600);
146 	struct itimerspec timeout = {.it_value.tv_sec = MAX(seconds, 0)};
147 
148 	int ino = inotify_init1(IN_CLOEXEC);
149 	if (ino == -1)
150 		return (ENOENT);
151 	inotify_add_watch(ino, ZFS_DEVDIR, IN_CREATE);
152 
153 	if (access(ZFS_DEV, F_OK) == 0) {
154 		close(ino);
155 		return (0);
156 	} else if (seconds == 0) {
157 		close(ino);
158 		return (ENOENT);
159 	}
160 
161 	size_t evsz = sizeof (struct inotify_event) + NAME_MAX + 1;
162 	struct inotify_event *ev = alloca(evsz);
163 
164 	int tout = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
165 	if (tout == -1) {
166 		close(ino);
167 		return (ENOENT);
168 	}
169 	timerfd_settime(tout, 0, &timeout, NULL);
170 
171 	int ret = ENOENT;
172 	struct pollfd pfds[] = {
173 		{.fd = ino, .events = POLLIN},
174 		{.fd = tout, .events = POLLIN},
175 	};
176 	while (poll(pfds, ARRAY_SIZE(pfds), -1) != -1) {
177 		if (pfds[0].revents & POLLIN) {
178 			verify(read(ino, ev, evsz) >
179 			    sizeof (struct inotify_event));
180 			if (strncmp(ev->name, &ZFS_DEV[sizeof (ZFS_DEVDIR)],
181 			    ev->len) == 0) {
182 				ret = 0;
183 				break;
184 			}
185 		}
186 		if (pfds[1].revents & POLLIN)
187 			break;
188 	}
189 	close(tout);
190 	close(ino);
191 	return (ret);
192 }
193 
194 int
find_shares_object(differ_info_t * di)195 find_shares_object(differ_info_t *di)
196 {
197 	char fullpath[MAXPATHLEN];
198 	struct stat64 sb = { 0 };
199 
200 	(void) strlcpy(fullpath, di->dsmnt, MAXPATHLEN);
201 	(void) strlcat(fullpath, ZDIFF_SHARESDIR, MAXPATHLEN);
202 
203 	if (stat64(fullpath, &sb) != 0) {
204 		(void) snprintf(di->errbuf, sizeof (di->errbuf),
205 		    dgettext(TEXT_DOMAIN, "Cannot stat %s"), fullpath);
206 		return (zfs_error(di->zhp->zfs_hdl, EZFS_DIFF, di->errbuf));
207 	}
208 
209 	di->shares = (uint64_t)sb.st_ino;
210 	return (0);
211 }
212 
213 int
zfs_destroy_snaps_nvl_os(libzfs_handle_t * hdl,nvlist_t * snaps)214 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps)
215 {
216 	(void) hdl, (void) snaps;
217 	return (0);
218 }
219 
220 /*
221  * Return allocated loaded module version, or NULL on error (with errno set)
222  */
223 char *
zfs_version_kernel(void)224 zfs_version_kernel(void)
225 {
226 	FILE *f = fopen(ZFS_SYSFS_DIR "/version", "re");
227 	if (f == NULL)
228 		return (NULL);
229 
230 	char *ret = NULL;
231 	size_t l;
232 	ssize_t read;
233 	if ((read = getline(&ret, &l, f)) == -1) {
234 		int err = errno;
235 		fclose(f);
236 		errno = err;
237 		return (NULL);
238 	}
239 
240 	fclose(f);
241 	if (ret[read - 1] == '\n')
242 		ret[read - 1] = '\0';
243 	return (ret);
244 }
245 
246 /*
247  * Add or delete the given filesystem to/from the given user namespace.
248  */
249 int
zfs_userns(zfs_handle_t * zhp,const char * nspath,int attach)250 zfs_userns(zfs_handle_t *zhp, const char *nspath, int attach)
251 {
252 	libzfs_handle_t *hdl = zhp->zfs_hdl;
253 	zfs_cmd_t zc = {"\0"};
254 	char errbuf[1024];
255 	unsigned long cmd;
256 	int ret;
257 
258 	if (attach) {
259 		(void) snprintf(errbuf, sizeof (errbuf),
260 		    dgettext(TEXT_DOMAIN, "cannot add '%s' to namespace"),
261 		    zhp->zfs_name);
262 	} else {
263 		(void) snprintf(errbuf, sizeof (errbuf),
264 		    dgettext(TEXT_DOMAIN, "cannot remove '%s' from namespace"),
265 		    zhp->zfs_name);
266 	}
267 
268 	switch (zhp->zfs_type) {
269 	case ZFS_TYPE_VOLUME:
270 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
271 		    "volumes can not be namespaced"));
272 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
273 	case ZFS_TYPE_SNAPSHOT:
274 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
275 		    "snapshots can not be namespaced"));
276 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
277 	case ZFS_TYPE_BOOKMARK:
278 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
279 		    "bookmarks can not be namespaced"));
280 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
281 	case ZFS_TYPE_VDEV:
282 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
283 		    "vdevs can not be namespaced"));
284 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
285 	case ZFS_TYPE_INVALID:
286 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
287 		    "invalid zfs_type_t: ZFS_TYPE_INVALID"));
288 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
289 	case ZFS_TYPE_POOL:
290 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
291 		    "pools can not be namespaced"));
292 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
293 	case ZFS_TYPE_FILESYSTEM:
294 		break;
295 	}
296 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
297 
298 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
299 	zc.zc_objset_type = DMU_OST_ZFS;
300 	zc.zc_cleanup_fd = open(nspath, O_RDONLY);
301 	if (zc.zc_cleanup_fd < 0) {
302 		return (zfs_error(hdl, EZFS_NOT_USER_NAMESPACE, errbuf));
303 	}
304 
305 	cmd = attach ? ZFS_IOC_USERNS_ATTACH : ZFS_IOC_USERNS_DETACH;
306 	if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0)
307 		zfs_standard_error(hdl, errno, errbuf);
308 
309 	(void) close(zc.zc_cleanup_fd);
310 
311 	return (ret);
312 }
313