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