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 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 * 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 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 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 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 * 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 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