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