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 http://www.opensolaris.org/os/licensing.
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) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
24  */
25 #include "../../libzfs_impl.h"
26 #include <libzfs.h>
27 #include <libzutil.h>
28 #include <sys/sysctl.h>
29 #include <libintl.h>
30 #include <sys/linker.h>
31 #include <sys/module.h>
32 #include <sys/stat.h>
33 #include <sys/param.h>
34 
35 #ifdef IN_BASE
36 #define	ZFS_KMOD	"zfs"
37 #else
38 #define	ZFS_KMOD	"openzfs"
39 #endif
40 
41 
42 static int
43 execvPe(const char *name, const char *path, char * const *argv,
44     char * const *envp)
45 {
46 	const char **memp;
47 	size_t cnt, lp, ln;
48 	int eacces, save_errno;
49 	char buf[MAXPATHLEN];
50 	const char *bp, *np, *op, *p;
51 	struct stat sb;
52 
53 	eacces = 0;
54 
55 	/* If it's an absolute or relative path name, it's easy. */
56 	if (strchr(name, '/')) {
57 		bp = name;
58 		op = NULL;
59 		goto retry;
60 	}
61 	bp = buf;
62 
63 	/* If it's an empty path name, fail in the usual POSIX way. */
64 	if (*name == '\0') {
65 		errno = ENOENT;
66 		return (-1);
67 	}
68 
69 	op = path;
70 	ln = strlen(name);
71 	while (op != NULL) {
72 		np = strchrnul(op, ':');
73 
74 		/*
75 		 * It's a SHELL path -- double, leading and trailing colons
76 		 * mean the current directory.
77 		 */
78 		if (np == op) {
79 			/* Empty component. */
80 			p = ".";
81 			lp = 1;
82 		} else {
83 			/* Non-empty component. */
84 			p = op;
85 			lp = np - op;
86 		}
87 
88 		/* Advance to the next component or terminate after this. */
89 		if (*np == '\0')
90 			op = NULL;
91 		else
92 			op = np + 1;
93 
94 		/*
95 		 * If the path is too long complain.  This is a possible
96 		 * security issue; given a way to make the path too long
97 		 * the user may execute the wrong program.
98 		 */
99 		if (lp + ln + 2 > sizeof (buf)) {
100 			(void) write(STDERR_FILENO, "execvP: ", 8);
101 			(void) write(STDERR_FILENO, p, lp);
102 			(void) write(STDERR_FILENO, ": path too long\n",
103 			    16);
104 			continue;
105 		}
106 		bcopy(p, buf, lp);
107 		buf[lp] = '/';
108 		bcopy(name, buf + lp + 1, ln);
109 		buf[lp + ln + 1] = '\0';
110 
111 retry:		(void) execve(bp, argv, envp);
112 		switch (errno) {
113 		case E2BIG:
114 			goto done;
115 		case ELOOP:
116 		case ENAMETOOLONG:
117 		case ENOENT:
118 			break;
119 		case ENOEXEC:
120 			for (cnt = 0; argv[cnt]; ++cnt)
121 				;
122 
123 			/*
124 			 * cnt may be 0 above; always allocate at least
125 			 * 3 entries so that we can at least fit "sh", bp, and
126 			 * the NULL terminator.  We can rely on cnt to take into
127 			 * account the NULL terminator in all other scenarios,
128 			 * as we drop argv[0].
129 			 */
130 			memp = alloca(MAX(3, cnt + 2) * sizeof (char *));
131 			if (memp == NULL) {
132 				/* errno = ENOMEM; XXX override ENOEXEC? */
133 				goto done;
134 			}
135 			if (cnt > 0) {
136 				memp[0] = argv[0];
137 				memp[1] = bp;
138 				bcopy(argv + 1, memp + 2,
139 				    cnt * sizeof (char *));
140 			} else {
141 				memp[0] = "sh";
142 				memp[1] = bp;
143 				memp[2] = NULL;
144 			}
145 			(void) execve(_PATH_BSHELL,
146 			    __DECONST(char **, memp), envp);
147 			goto done;
148 		case ENOMEM:
149 			goto done;
150 		case ENOTDIR:
151 			break;
152 		case ETXTBSY:
153 			/*
154 			 * We used to retry here, but sh(1) doesn't.
155 			 */
156 			goto done;
157 		default:
158 			/*
159 			 * EACCES may be for an inaccessible directory or
160 			 * a non-executable file.  Call stat() to decide
161 			 * which.  This also handles ambiguities for EFAULT
162 			 * and EIO, and undocumented errors like ESTALE.
163 			 * We hope that the race for a stat() is unimportant.
164 			 */
165 			save_errno = errno;
166 			if (stat(bp, &sb) != 0)
167 				break;
168 			if (save_errno == EACCES) {
169 				eacces = 1;
170 				continue;
171 			}
172 			errno = save_errno;
173 			goto done;
174 		}
175 	}
176 	if (eacces)
177 		errno = EACCES;
178 	else
179 		errno = ENOENT;
180 done:
181 	return (-1);
182 }
183 
184 int
185 execvpe(const char *name, char * const argv[], char * const envp[])
186 {
187 	const char *path;
188 
189 	/* Get the path we're searching. */
190 	if ((path = getenv("PATH")) == NULL)
191 		path = _PATH_DEFPATH;
192 
193 	return (execvPe(name, path, argv, envp));
194 }
195 
196 #define	ERRBUFLEN 1024
197 
198 static __thread char errbuf[ERRBUFLEN];
199 
200 const char *
201 libzfs_error_init(int error)
202 {
203 	char *msg = errbuf;
204 	size_t msglen = sizeof (errbuf);
205 
206 	if (modfind("zfs") < 0) {
207 		size_t len = snprintf(msg, msglen, dgettext(TEXT_DOMAIN,
208 		    "Failed to load %s module: "), ZFS_KMOD);
209 		msg += len;
210 		msglen -= len;
211 	}
212 
213 	(void) snprintf(msg, msglen, "%s", strerror(error));
214 
215 	return (errbuf);
216 }
217 
218 int
219 zfs_ioctl(libzfs_handle_t *hdl, int request, zfs_cmd_t *zc)
220 {
221 	return (lzc_ioctl_fd(hdl->libzfs_fd, request, zc));
222 }
223 
224 /*
225  * Verify the required ZFS_DEV device is available and optionally attempt
226  * to load the ZFS modules.  Under normal circumstances the modules
227  * should already have been loaded by some external mechanism.
228  */
229 int
230 libzfs_load_module(void)
231 {
232 	/*
233 	 * XXX: kldfind(ZFS_KMOD) would be nice here, but we retain
234 	 * modfind("zfs") so out-of-base openzfs userland works with the
235 	 * in-base module.
236 	 */
237 	if (modfind("zfs") < 0) {
238 		/* Not present in kernel, try loading it. */
239 		if (kldload(ZFS_KMOD) < 0 && errno != EEXIST) {
240 			return (errno);
241 		}
242 	}
243 	return (0);
244 }
245 
246 int
247 zpool_relabel_disk(libzfs_handle_t *hdl, const char *path, const char *msg)
248 {
249 	(void) hdl, (void) path, (void) msg;
250 	return (0);
251 }
252 
253 int
254 zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
255 {
256 	(void) hdl, (void) zhp, (void) name;
257 	return (0);
258 }
259 
260 int
261 find_shares_object(differ_info_t *di)
262 {
263 	(void) di;
264 	return (0);
265 }
266 
267 int
268 zfs_destroy_snaps_nvl_os(libzfs_handle_t *hdl, nvlist_t *snaps)
269 {
270 	(void) hdl, (void) snaps;
271 	return (0);
272 }
273 
274 /*
275  * Attach/detach the given filesystem to/from the given jail.
276  */
277 int
278 zfs_jail(zfs_handle_t *zhp, int jailid, int attach)
279 {
280 	libzfs_handle_t *hdl = zhp->zfs_hdl;
281 	zfs_cmd_t zc = {"\0"};
282 	unsigned long cmd;
283 	int ret;
284 
285 	if (attach) {
286 		(void) snprintf(errbuf, sizeof (errbuf),
287 		    dgettext(TEXT_DOMAIN, "cannot jail '%s'"), zhp->zfs_name);
288 	} else {
289 		(void) snprintf(errbuf, sizeof (errbuf),
290 		    dgettext(TEXT_DOMAIN, "cannot unjail '%s'"), zhp->zfs_name);
291 	}
292 
293 	switch (zhp->zfs_type) {
294 	case ZFS_TYPE_VOLUME:
295 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
296 		    "volumes can not be jailed"));
297 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
298 	case ZFS_TYPE_SNAPSHOT:
299 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
300 		    "snapshots can not be jailed"));
301 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
302 	case ZFS_TYPE_BOOKMARK:
303 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
304 		    "bookmarks can not be jailed"));
305 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
306 	case ZFS_TYPE_VDEV:
307 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
308 		    "vdevs can not be jailed"));
309 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
310 	case ZFS_TYPE_INVALID:
311 		zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
312 		    "invalid zfs_type_t: ZFS_TYPE_INVALID"));
313 		return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
314 	case ZFS_TYPE_POOL:
315 	case ZFS_TYPE_FILESYSTEM:
316 		/* OK */
317 		;
318 	}
319 	assert(zhp->zfs_type == ZFS_TYPE_FILESYSTEM);
320 
321 	(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
322 	zc.zc_objset_type = DMU_OST_ZFS;
323 	zc.zc_zoneid = jailid;
324 
325 	cmd = attach ? ZFS_IOC_JAIL : ZFS_IOC_UNJAIL;
326 	if ((ret = zfs_ioctl(hdl, cmd, &zc)) != 0)
327 		zfs_standard_error(hdl, errno, errbuf);
328 
329 	return (ret);
330 }
331 
332 /*
333  * Set loader options for next boot.
334  */
335 int
336 zpool_nextboot(libzfs_handle_t *hdl, uint64_t pool_guid, uint64_t dev_guid,
337     const char *command)
338 {
339 	zfs_cmd_t zc = {"\0"};
340 	nvlist_t *args;
341 	int error;
342 
343 	args = fnvlist_alloc();
344 	fnvlist_add_uint64(args, ZPOOL_CONFIG_POOL_GUID, pool_guid);
345 	fnvlist_add_uint64(args, ZPOOL_CONFIG_GUID, dev_guid);
346 	fnvlist_add_string(args, "command", command);
347 	error = zcmd_write_src_nvlist(hdl, &zc, args);
348 	if (error == 0)
349 		error = zfs_ioctl(hdl, ZFS_IOC_NEXTBOOT, &zc);
350 	zcmd_free_nvlists(&zc);
351 	nvlist_free(args);
352 	return (error);
353 }
354 
355 /*
356  * Fill given version buffer with zfs kernel version.
357  * Returns 0 on success, and -1 on error (with errno set)
358  */
359 int
360 zfs_version_kernel(char *version, int len)
361 {
362 	size_t l = len;
363 
364 	return (sysctlbyname("vfs.zfs.version.module",
365 	    version, &l, NULL, 0));
366 }
367