1fa9e4066Sahrens /*
2fa9e4066Sahrens * CDDL HEADER START
3fa9e4066Sahrens *
4fa9e4066Sahrens * The contents of this file are subject to the terms of the
5441d80aaSlling * Common Development and Distribution License (the "License").
6441d80aaSlling * You may not use this file except in compliance with the License.
7fa9e4066Sahrens *
8fa9e4066Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens * See the License for the specific language governing permissions
11fa9e4066Sahrens * and limitations under the License.
12fa9e4066Sahrens *
13fa9e4066Sahrens * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens *
19fa9e4066Sahrens * CDDL HEADER END
20fa9e4066Sahrens */
21ad135b5dSChristopher Siden
22fa9e4066Sahrens /*
233f9d6ad7SLin Ling * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
240dfe541eSEvan Layton */
250dfe541eSEvan Layton
260dfe541eSEvan Layton /*
270d8fa8f8SMartin Matuska * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
281df56adaSMartin Matuska * Portions Copyright 2011 Martin Matuska
295878fad7SDan McDonald * Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.
300dfe541eSEvan Layton * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
3128df1ae0SJason King * Copyright 2019 Joyent, Inc.
322840dce1SChris Williamson * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
33a6f561b4SSašo Kiselkov * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
34a7a845e4SSteven Hartland * Copyright (c) 2013 Steven Hartland. All rights reserved.
35c3d26abcSMatthew Ahrens * Copyright (c) 2014 Integros [integros.com]
36c8811bd3SToomas Soome * Copyright 2016 Toomas Soome <tsoome@me.com>
376ccda740Sloli * Copyright (c) 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
38a4b8c9aaSAndrew Stormont * Copyright 2017 RackTop Systems.
39eb633035STom Caputi * Copyright (c) 2017, Datto, Inc. All rights reserved.
40*d8f839f9SJason King * Copyright 2021 The University of Queensland
414445fffbSMatthew Ahrens */
424445fffbSMatthew Ahrens
434445fffbSMatthew Ahrens /*
444445fffbSMatthew Ahrens * ZFS ioctls.
454445fffbSMatthew Ahrens *
464445fffbSMatthew Ahrens * This file handles the ioctls to /dev/zfs, used for configuring ZFS storage
474445fffbSMatthew Ahrens * pools and filesystems, e.g. with /sbin/zfs and /sbin/zpool.
484445fffbSMatthew Ahrens *
494445fffbSMatthew Ahrens * There are two ways that we handle ioctls: the legacy way where almost
504445fffbSMatthew Ahrens * all of the logic is in the ioctl callback, and the new way where most
514445fffbSMatthew Ahrens * of the marshalling is handled in the common entry point, zfsdev_ioctl().
524445fffbSMatthew Ahrens *
534445fffbSMatthew Ahrens * Non-legacy ioctls should be registered by calling
544445fffbSMatthew Ahrens * zfs_ioctl_register() from zfs_ioctl_init(). The ioctl is invoked
554445fffbSMatthew Ahrens * from userland by lzc_ioctl().
564445fffbSMatthew Ahrens *
574445fffbSMatthew Ahrens * The registration arguments are as follows:
584445fffbSMatthew Ahrens *
594445fffbSMatthew Ahrens * const char *name
604445fffbSMatthew Ahrens * The name of the ioctl. This is used for history logging. If the
614445fffbSMatthew Ahrens * ioctl returns successfully (the callback returns 0), and allow_log
624445fffbSMatthew Ahrens * is true, then a history log entry will be recorded with the input &
634445fffbSMatthew Ahrens * output nvlists. The log entry can be printed with "zpool history -i".
644445fffbSMatthew Ahrens *
654445fffbSMatthew Ahrens * zfs_ioc_t ioc
664445fffbSMatthew Ahrens * The ioctl request number, which userland will pass to ioctl(2).
677ac89354SDon Brady * We want newer versions of libzfs and libzfs_core to run against
687ac89354SDon Brady * existing zfs kernel modules (i.e. a deferred reboot after an update).
697ac89354SDon Brady * Therefore the ioctl numbers cannot change from release to release.
704445fffbSMatthew Ahrens *
714445fffbSMatthew Ahrens * zfs_secpolicy_func_t *secpolicy
724445fffbSMatthew Ahrens * This function will be called before the zfs_ioc_func_t, to
734445fffbSMatthew Ahrens * determine if this operation is permitted. It should return EPERM
744445fffbSMatthew Ahrens * on failure, and 0 on success. Checks include determining if the
754445fffbSMatthew Ahrens * dataset is visible in this zone, and if the user has either all
764445fffbSMatthew Ahrens * zfs privileges in the zone (SYS_MOUNT), or has been granted permission
774445fffbSMatthew Ahrens * to do this operation on this dataset with "zfs allow".
784445fffbSMatthew Ahrens *
794445fffbSMatthew Ahrens * zfs_ioc_namecheck_t namecheck
804445fffbSMatthew Ahrens * This specifies what to expect in the zfs_cmd_t:zc_name -- a pool
814445fffbSMatthew Ahrens * name, a dataset name, or nothing. If the name is not well-formed,
824445fffbSMatthew Ahrens * the ioctl will fail and the callback will not be called.
834445fffbSMatthew Ahrens * Therefore, the callback can assume that the name is well-formed
844445fffbSMatthew Ahrens * (e.g. is null-terminated, doesn't have more than one '@' character,
854445fffbSMatthew Ahrens * doesn't have invalid characters).
864445fffbSMatthew Ahrens *
874445fffbSMatthew Ahrens * zfs_ioc_poolcheck_t pool_check
884445fffbSMatthew Ahrens * This specifies requirements on the pool state. If the pool does
894445fffbSMatthew Ahrens * not meet them (is suspended or is readonly), the ioctl will fail
904445fffbSMatthew Ahrens * and the callback will not be called. If any checks are specified
914445fffbSMatthew Ahrens * (i.e. it is not POOL_CHECK_NONE), namecheck must not be NO_NAME.
924445fffbSMatthew Ahrens * Multiple checks can be or-ed together (e.g. POOL_CHECK_SUSPENDED |
934445fffbSMatthew Ahrens * POOL_CHECK_READONLY).
944445fffbSMatthew Ahrens *
957ac89354SDon Brady * zfs_ioc_key_t *nvl_keys
967ac89354SDon Brady * The list of expected/allowable innvl input keys. This list is used
977ac89354SDon Brady * to validate the nvlist input to the ioctl.
987ac89354SDon Brady *
994445fffbSMatthew Ahrens * boolean_t smush_outnvlist
1004445fffbSMatthew Ahrens * If smush_outnvlist is true, then the output is presumed to be a
1014445fffbSMatthew Ahrens * list of errors, and it will be "smushed" down to fit into the
1024445fffbSMatthew Ahrens * caller's buffer, by removing some entries and replacing them with a
1034445fffbSMatthew Ahrens * single "N_MORE_ERRORS" entry indicating how many were removed. See
1044445fffbSMatthew Ahrens * nvlist_smush() for details. If smush_outnvlist is false, and the
1054445fffbSMatthew Ahrens * outnvlist does not fit into the userland-provided buffer, then the
1064445fffbSMatthew Ahrens * ioctl will fail with ENOMEM.
1074445fffbSMatthew Ahrens *
1084445fffbSMatthew Ahrens * zfs_ioc_func_t *func
1094445fffbSMatthew Ahrens * The callback function that will perform the operation.
1104445fffbSMatthew Ahrens *
1114445fffbSMatthew Ahrens * The callback should return 0 on success, or an error number on
1124445fffbSMatthew Ahrens * failure. If the function fails, the userland ioctl will return -1,
1134445fffbSMatthew Ahrens * and errno will be set to the callback's return value. The callback
1144445fffbSMatthew Ahrens * will be called with the following arguments:
1154445fffbSMatthew Ahrens *
1164445fffbSMatthew Ahrens * const char *name
1174445fffbSMatthew Ahrens * The name of the pool or dataset to operate on, from
1184445fffbSMatthew Ahrens * zfs_cmd_t:zc_name. The 'namecheck' argument specifies the
1194445fffbSMatthew Ahrens * expected type (pool, dataset, or none).
1204445fffbSMatthew Ahrens *
1214445fffbSMatthew Ahrens * nvlist_t *innvl
1224445fffbSMatthew Ahrens * The input nvlist, deserialized from zfs_cmd_t:zc_nvlist_src. Or
1234445fffbSMatthew Ahrens * NULL if no input nvlist was provided. Changes to this nvlist are
1244445fffbSMatthew Ahrens * ignored. If the input nvlist could not be deserialized, the
1254445fffbSMatthew Ahrens * ioctl will fail and the callback will not be called.
1264445fffbSMatthew Ahrens *
1274445fffbSMatthew Ahrens * nvlist_t *outnvl
1284445fffbSMatthew Ahrens * The output nvlist, initially empty. The callback can fill it in,
1294445fffbSMatthew Ahrens * and it will be returned to userland by serializing it into
1304445fffbSMatthew Ahrens * zfs_cmd_t:zc_nvlist_dst. If it is non-empty, and serialization
1314445fffbSMatthew Ahrens * fails (e.g. because the caller didn't supply a large enough
1324445fffbSMatthew Ahrens * buffer), then the overall ioctl will fail. See the
1334445fffbSMatthew Ahrens * 'smush_nvlist' argument above for additional behaviors.
1344445fffbSMatthew Ahrens *
1354445fffbSMatthew Ahrens * There are two typical uses of the output nvlist:
1364445fffbSMatthew Ahrens * - To return state, e.g. property values. In this case,
1374445fffbSMatthew Ahrens * smush_outnvlist should be false. If the buffer was not large
1384445fffbSMatthew Ahrens * enough, the caller will reallocate a larger buffer and try
1394445fffbSMatthew Ahrens * the ioctl again.
1404445fffbSMatthew Ahrens *
1414445fffbSMatthew Ahrens * - To return multiple errors from an ioctl which makes on-disk
1424445fffbSMatthew Ahrens * changes. In this case, smush_outnvlist should be true.
1434445fffbSMatthew Ahrens * Ioctls which make on-disk modifications should generally not
1444445fffbSMatthew Ahrens * use the outnvl if they succeed, because the caller can not
1454445fffbSMatthew Ahrens * distinguish between the operation failing, and
1464445fffbSMatthew Ahrens * deserialization failing.
1477ac89354SDon Brady *
1487ac89354SDon Brady * IOCTL Interface Errors
1497ac89354SDon Brady *
1507ac89354SDon Brady * The following ioctl input errors can be returned:
1517ac89354SDon Brady * ZFS_ERR_IOC_CMD_UNAVAIL the ioctl number is not supported by kernel
1527ac89354SDon Brady * ZFS_ERR_IOC_ARG_UNAVAIL an input argument is not supported by kernel
1537ac89354SDon Brady * ZFS_ERR_IOC_ARG_REQUIRED a required input argument is missing
1547ac89354SDon Brady * ZFS_ERR_IOC_ARG_BADTYPE an input argument has an invalid type
155e9103aaeSGarrett D'Amore */
156fa9e4066Sahrens
157fa9e4066Sahrens #include <sys/types.h>
158fa9e4066Sahrens #include <sys/param.h>
159fa9e4066Sahrens #include <sys/errno.h>
160fa9e4066Sahrens #include <sys/uio.h>
161fa9e4066Sahrens #include <sys/buf.h>
162fa9e4066Sahrens #include <sys/modctl.h>
163fa9e4066Sahrens #include <sys/open.h>
164fa9e4066Sahrens #include <sys/file.h>
165fa9e4066Sahrens #include <sys/kmem.h>
166fa9e4066Sahrens #include <sys/conf.h>
167fa9e4066Sahrens #include <sys/cmn_err.h>
168fa9e4066Sahrens #include <sys/stat.h>
169fa9e4066Sahrens #include <sys/zfs_ioctl.h>
1704201a95eSRic Aleshire #include <sys/zfs_vfsops.h>
171da6c28aaSamw #include <sys/zfs_znode.h>
172fa9e4066Sahrens #include <sys/zap.h>
173fa9e4066Sahrens #include <sys/spa.h>
174b1b8ab34Slling #include <sys/spa_impl.h>
175fa9e4066Sahrens #include <sys/vdev.h>
1764201a95eSRic Aleshire #include <sys/priv_impl.h>
177fa9e4066Sahrens #include <sys/dmu.h>
178fa9e4066Sahrens #include <sys/dsl_dir.h>
179fa9e4066Sahrens #include <sys/dsl_dataset.h>
180fa9e4066Sahrens #include <sys/dsl_prop.h>
181ecd6cf80Smarks #include <sys/dsl_deleg.h>
182ecd6cf80Smarks #include <sys/dmu_objset.h>
1834e3c9f44SBill Pijewski #include <sys/dmu_impl.h>
1843b2aab18SMatthew Ahrens #include <sys/dmu_tx.h>
185fa9e4066Sahrens #include <sys/ddi.h>
186fa9e4066Sahrens #include <sys/sunddi.h>
187fa9e4066Sahrens #include <sys/sunldi.h>
188fa9e4066Sahrens #include <sys/policy.h>
189fa9e4066Sahrens #include <sys/zone.h>
190fa9e4066Sahrens #include <sys/nvpair.h>
191fa9e4066Sahrens #include <sys/pathname.h>
192fa9e4066Sahrens #include <sys/mount.h>
193fa9e4066Sahrens #include <sys/sdt.h>
194fa9e4066Sahrens #include <sys/fs/zfs.h>
195fa9e4066Sahrens #include <sys/zfs_ctldir.h>
196da6c28aaSamw #include <sys/zfs_dir.h>
197c99e4bdcSChris Kirby #include <sys/zfs_onexit.h>
198a2eea2e1Sahrens #include <sys/zvol.h>
1993f9d6ad7SLin Ling #include <sys/dsl_scan.h>
200ecd6cf80Smarks #include <sharefs/share.h>
201f18faf3fSek #include <sys/dmu_objset.h>
2020fa1b3ccSPaul Dagnelie #include <sys/dmu_recv.h>
2033b2aab18SMatthew Ahrens #include <sys/dmu_send.h>
2043b2aab18SMatthew Ahrens #include <sys/dsl_destroy.h>
20578f17100SMatthew Ahrens #include <sys/dsl_bookmark.h>
2063b2aab18SMatthew Ahrens #include <sys/dsl_userhold.h>
207a6f561b4SSašo Kiselkov #include <sys/zfeature.h>
208dfc11533SChris Williamson #include <sys/zcp.h>
20945818ee1SMatthew Ahrens #include <sys/zio_checksum.h>
2105cabbc6bSPrashanth Sreenivasa #include <sys/vdev_removal.h>
211094e47e9SGeorge Wilson #include <sys/vdev_impl.h>
212094e47e9SGeorge Wilson #include <sys/vdev_initialize.h>
213084fd14fSBrian Behlendorf #include <sys/vdev_trim.h>
214eb633035STom Caputi #include <sys/dsl_crypt.h>
215fa9e4066Sahrens
216fa9e4066Sahrens #include "zfs_namecheck.h"
217e9dbad6fSeschrock #include "zfs_prop.h"
218ecd6cf80Smarks #include "zfs_deleg.h"
2190a586ceaSMark Shellenbaum #include "zfs_comutil.h"
220fa9e4066Sahrens
221dfc11533SChris Williamson #include "lua.h"
222dfc11533SChris Williamson #include "lauxlib.h"
223dfc11533SChris Williamson
224fa9e4066Sahrens extern struct modlfs zfs_modlfs;
225fa9e4066Sahrens
226fa9e4066Sahrens extern void zfs_init(void);
227fa9e4066Sahrens extern void zfs_fini(void);
228fa9e4066Sahrens
229fa9e4066Sahrens ldi_ident_t zfs_li = NULL;
230fa9e4066Sahrens dev_info_t *zfs_dip;
231fa9e4066Sahrens
2324445fffbSMatthew Ahrens uint_t zfs_fsyncer_key;
2334445fffbSMatthew Ahrens extern uint_t rrw_tsd_key;
2344445fffbSMatthew Ahrens static uint_t zfs_allow_log_key;
2354445fffbSMatthew Ahrens
2364445fffbSMatthew Ahrens typedef int zfs_ioc_legacy_func_t(zfs_cmd_t *);
2374445fffbSMatthew Ahrens typedef int zfs_ioc_func_t(const char *, nvlist_t *, nvlist_t *);
2384445fffbSMatthew Ahrens typedef int zfs_secpolicy_func_t(zfs_cmd_t *, nvlist_t *, cred_t *);
239fa9e4066Sahrens
2407ac89354SDon Brady /*
2417ac89354SDon Brady * IOC Keys are used to document and validate user->kernel interface inputs.
2427ac89354SDon Brady * See zfs_keys_recv_new for an example declaration. Any key name that is not
2437ac89354SDon Brady * listed will be rejected as input.
2447ac89354SDon Brady *
2457ac89354SDon Brady * The keyname 'optional' is always allowed, and must be an nvlist if present.
2467ac89354SDon Brady * Arguments which older kernels can safely ignore can be placed under the
2477ac89354SDon Brady * "optional" key.
2487ac89354SDon Brady *
2497ac89354SDon Brady * When adding new keys to an existing ioc for new functionality, consider:
2507ac89354SDon Brady * - adding an entry into zfs_sysfs.c zfs_features[] list
2517ac89354SDon Brady * - updating the libzfs_input_check.c test utility
2527ac89354SDon Brady *
2537ac89354SDon Brady * Note: in the ZK_WILDCARDLIST case, the name serves as documentation
2547ac89354SDon Brady * for the expected name (bookmark, snapshot, property, etc) but there
2557ac89354SDon Brady * is no validation in the preflight zfs_check_input_nvpairs() check.
2567ac89354SDon Brady */
2577ac89354SDon Brady typedef enum {
2587ac89354SDon Brady ZK_OPTIONAL = 1 << 0, /* pair is optional */
2597ac89354SDon Brady ZK_WILDCARDLIST = 1 << 1, /* one or more unspecified key names */
2607ac89354SDon Brady } ioc_key_flag_t;
2617ac89354SDon Brady
2627ac89354SDon Brady /* DATA_TYPE_ANY is used when zkey_type can vary. */
2637ac89354SDon Brady #define DATA_TYPE_ANY DATA_TYPE_UNKNOWN
2647ac89354SDon Brady
2657ac89354SDon Brady typedef struct zfs_ioc_key {
2667ac89354SDon Brady const char *zkey_name;
2677ac89354SDon Brady data_type_t zkey_type;
2687ac89354SDon Brady ioc_key_flag_t zkey_flags;
2697ac89354SDon Brady } zfs_ioc_key_t;
2707ac89354SDon Brady
27154d692b7SGeorge Wilson typedef enum {
27254d692b7SGeorge Wilson NO_NAME,
27354d692b7SGeorge Wilson POOL_NAME,
27454d692b7SGeorge Wilson DATASET_NAME
27554d692b7SGeorge Wilson } zfs_ioc_namecheck_t;
27654d692b7SGeorge Wilson
277f9af39baSGeorge Wilson typedef enum {
278f9af39baSGeorge Wilson POOL_CHECK_NONE = 1 << 0,
279f9af39baSGeorge Wilson POOL_CHECK_SUSPENDED = 1 << 1,
2804445fffbSMatthew Ahrens POOL_CHECK_READONLY = 1 << 2,
281f9af39baSGeorge Wilson } zfs_ioc_poolcheck_t;
282f9af39baSGeorge Wilson
283fa9e4066Sahrens typedef struct zfs_ioc_vec {
2844445fffbSMatthew Ahrens zfs_ioc_legacy_func_t *zvec_legacy_func;
285fa9e4066Sahrens zfs_ioc_func_t *zvec_func;
286fa9e4066Sahrens zfs_secpolicy_func_t *zvec_secpolicy;
28754d692b7SGeorge Wilson zfs_ioc_namecheck_t zvec_namecheck;
2884445fffbSMatthew Ahrens boolean_t zvec_allow_log;
289f9af39baSGeorge Wilson zfs_ioc_poolcheck_t zvec_pool_check;
2904445fffbSMatthew Ahrens boolean_t zvec_smush_outnvlist;
2914445fffbSMatthew Ahrens const char *zvec_name;
2927ac89354SDon Brady const zfs_ioc_key_t *zvec_nvl_keys;
2937ac89354SDon Brady size_t zvec_nvl_key_count;
294fa9e4066Sahrens } zfs_ioc_vec_t;
295fa9e4066Sahrens
29614843421SMatthew Ahrens /* This array is indexed by zfs_userquota_prop_t */
29714843421SMatthew Ahrens static const char *userquota_perms[] = {
29814843421SMatthew Ahrens ZFS_DELEG_PERM_USERUSED,
29914843421SMatthew Ahrens ZFS_DELEG_PERM_USERQUOTA,
30014843421SMatthew Ahrens ZFS_DELEG_PERM_GROUPUSED,
30114843421SMatthew Ahrens ZFS_DELEG_PERM_GROUPQUOTA,
302f67950b2SNasf-Fan ZFS_DELEG_PERM_USEROBJUSED,
303f67950b2SNasf-Fan ZFS_DELEG_PERM_USEROBJQUOTA,
304f67950b2SNasf-Fan ZFS_DELEG_PERM_GROUPOBJUSED,
305f67950b2SNasf-Fan ZFS_DELEG_PERM_GROUPOBJQUOTA,
306f67950b2SNasf-Fan ZFS_DELEG_PERM_PROJECTUSED,
307f67950b2SNasf-Fan ZFS_DELEG_PERM_PROJECTQUOTA,
308f67950b2SNasf-Fan ZFS_DELEG_PERM_PROJECTOBJUSED,
309f67950b2SNasf-Fan ZFS_DELEG_PERM_PROJECTOBJQUOTA,
31014843421SMatthew Ahrens };
31114843421SMatthew Ahrens
31214843421SMatthew Ahrens static int zfs_ioc_userspace_upgrade(zfs_cmd_t *zc);
313f67950b2SNasf-Fan static int zfs_ioc_id_quota_upgrade(zfs_cmd_t *zc);
31492241e0bSTom Erickson static int zfs_check_settable(const char *name, nvpair_t *property,
31592241e0bSTom Erickson cred_t *cr);
31692241e0bSTom Erickson static int zfs_check_clearable(char *dataset, nvlist_t *props,
31792241e0bSTom Erickson nvlist_t **errors);
3180a48a24eStimh static int zfs_fill_zplprops_root(uint64_t, nvlist_t *, nvlist_t *,
3190a48a24eStimh boolean_t *);
3204445fffbSMatthew Ahrens int zfs_set_prop_nvlist(const char *, zprop_source_t, nvlist_t *, nvlist_t *);
3214445fffbSMatthew Ahrens static int get_nvlist(uint64_t nvl, uint64_t size, int iflag, nvlist_t **nvp);
3220a48a24eStimh
3232acef22dSMatthew Ahrens static int zfs_prop_activate_feature(spa_t *spa, spa_feature_t feature);
324a6f561b4SSašo Kiselkov
325fa9e4066Sahrens /* _NOTE(PRINTFLIKE(4)) - this is printf-like, but lint is too whiney */
326fa9e4066Sahrens void
__dprintf(const char * file,const char * func,int line,const char * fmt,...)327fa9e4066Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
328fa9e4066Sahrens {
329fa9e4066Sahrens const char *newfile;
3303f9d6ad7SLin Ling char buf[512];
331fa9e4066Sahrens va_list adx;
332fa9e4066Sahrens
333fa9e4066Sahrens /*
334fa9e4066Sahrens * Get rid of annoying "../common/" prefix to filename.
335fa9e4066Sahrens */
336fa9e4066Sahrens newfile = strrchr(file, '/');
337fa9e4066Sahrens if (newfile != NULL) {
338fa9e4066Sahrens newfile = newfile + 1; /* Get rid of leading / */
339fa9e4066Sahrens } else {
340fa9e4066Sahrens newfile = file;
341fa9e4066Sahrens }
342fa9e4066Sahrens
343fa9e4066Sahrens va_start(adx, fmt);
344fa9e4066Sahrens (void) vsnprintf(buf, sizeof (buf), fmt, adx);
345fa9e4066Sahrens va_end(adx);
346fa9e4066Sahrens
347fa9e4066Sahrens /*
348fa9e4066Sahrens * To get this data, use the zfs-dprintf probe as so:
349fa9e4066Sahrens * dtrace -q -n 'zfs-dprintf \
350fa9e4066Sahrens * /stringof(arg0) == "dbuf.c"/ \
351fa9e4066Sahrens * {printf("%s: %s", stringof(arg1), stringof(arg3))}'
352fa9e4066Sahrens * arg0 = file name
353fa9e4066Sahrens * arg1 = function name
354fa9e4066Sahrens * arg2 = line number
355fa9e4066Sahrens * arg3 = message
356fa9e4066Sahrens */
357fa9e4066Sahrens DTRACE_PROBE4(zfs__dprintf,
358fa9e4066Sahrens char *, newfile, char *, func, int, line, char *, buf);
359fa9e4066Sahrens }
360fa9e4066Sahrens
361ecd6cf80Smarks static void
history_str_free(char * buf)362228975ccSek history_str_free(char *buf)
363228975ccSek {
364228975ccSek kmem_free(buf, HIS_MAX_RECORD_LEN);
365228975ccSek }
366228975ccSek
367228975ccSek static char *
history_str_get(zfs_cmd_t * zc)368228975ccSek history_str_get(zfs_cmd_t *zc)
369ecd6cf80Smarks {
37040feaa91Sahrens char *buf;
371ecd6cf80Smarks
372dd328bf6SToomas Soome if (zc->zc_history == 0)
373228975ccSek return (NULL);
374e7437265Sahrens
375ecd6cf80Smarks buf = kmem_alloc(HIS_MAX_RECORD_LEN, KM_SLEEP);
376ecd6cf80Smarks if (copyinstr((void *)(uintptr_t)zc->zc_history,
377ecd6cf80Smarks buf, HIS_MAX_RECORD_LEN, NULL) != 0) {
378228975ccSek history_str_free(buf);
379228975ccSek return (NULL);
380ecd6cf80Smarks }
381ecd6cf80Smarks
382ecd6cf80Smarks buf[HIS_MAX_RECORD_LEN -1] = '\0';
383ecd6cf80Smarks
384228975ccSek return (buf);
385228975ccSek }
386ecd6cf80Smarks
38715e6edf1Sgw /*
38815e6edf1Sgw * Check to see if the named dataset is currently defined as bootable
38915e6edf1Sgw */
39015e6edf1Sgw static boolean_t
zfs_is_bootfs(const char * name)39115e6edf1Sgw zfs_is_bootfs(const char *name)
39215e6edf1Sgw {
393503ad85cSMatthew Ahrens objset_t *os;
39415e6edf1Sgw
395503ad85cSMatthew Ahrens if (dmu_objset_hold(name, FTAG, &os) == 0) {
396503ad85cSMatthew Ahrens boolean_t ret;
397b24ab676SJeff Bonwick ret = (dmu_objset_id(os) == spa_bootfs(dmu_objset_spa(os)));
398503ad85cSMatthew Ahrens dmu_objset_rele(os, FTAG);
399503ad85cSMatthew Ahrens return (ret);
40015e6edf1Sgw }
401503ad85cSMatthew Ahrens return (B_FALSE);
40215e6edf1Sgw }
40315e6edf1Sgw
404c2a93d44Stimh /*
405f7170741SWill Andrews * Return non-zero if the spa version is less than requested version.
406c2a93d44Stimh */
407da6c28aaSamw static int
zfs_earlier_version(const char * name,int version)4080a48a24eStimh zfs_earlier_version(const char *name, int version)
409da6c28aaSamw {
410da6c28aaSamw spa_t *spa;
411da6c28aaSamw
412da6c28aaSamw if (spa_open(name, &spa, FTAG) == 0) {
413da6c28aaSamw if (spa_version(spa) < version) {
414da6c28aaSamw spa_close(spa, FTAG);
415da6c28aaSamw return (1);
416da6c28aaSamw }
417da6c28aaSamw spa_close(spa, FTAG);
418da6c28aaSamw }
419da6c28aaSamw return (0);
420da6c28aaSamw }
421da6c28aaSamw
4229e6eda55Smarks /*
423745cd3c5Smaybee * Return TRUE if the ZPL version is less than requested version.
4249e6eda55Smarks */
425745cd3c5Smaybee static boolean_t
zpl_earlier_version(const char * name,int version)426745cd3c5Smaybee zpl_earlier_version(const char *name, int version)
4279e6eda55Smarks {
4289e6eda55Smarks objset_t *os;
429745cd3c5Smaybee boolean_t rc = B_TRUE;
4309e6eda55Smarks
431503ad85cSMatthew Ahrens if (dmu_objset_hold(name, FTAG, &os) == 0) {
432745cd3c5Smaybee uint64_t zplversion;
4339e6eda55Smarks
434503ad85cSMatthew Ahrens if (dmu_objset_type(os) != DMU_OST_ZFS) {
435503ad85cSMatthew Ahrens dmu_objset_rele(os, FTAG);
436503ad85cSMatthew Ahrens return (B_TRUE);
437503ad85cSMatthew Ahrens }
438503ad85cSMatthew Ahrens /* XXX reading from non-owned objset */
439745cd3c5Smaybee if (zfs_get_zplprop(os, ZFS_PROP_VERSION, &zplversion) == 0)
440745cd3c5Smaybee rc = zplversion < version;
441503ad85cSMatthew Ahrens dmu_objset_rele(os, FTAG);
4429e6eda55Smarks }
4439e6eda55Smarks return (rc);
4449e6eda55Smarks }
4459e6eda55Smarks
446228975ccSek static void
zfs_log_history(zfs_cmd_t * zc)447228975ccSek zfs_log_history(zfs_cmd_t *zc)
448228975ccSek {
449228975ccSek spa_t *spa;
450228975ccSek char *buf;
451ecd6cf80Smarks
452228975ccSek if ((buf = history_str_get(zc)) == NULL)
453228975ccSek return;
454228975ccSek
455228975ccSek if (spa_open(zc->zc_name, &spa, FTAG) == 0) {
456228975ccSek if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
4574445fffbSMatthew Ahrens (void) spa_history_log(spa, buf);
458228975ccSek spa_close(spa, FTAG);
459228975ccSek }
460228975ccSek history_str_free(buf);
461ecd6cf80Smarks }
462ecd6cf80Smarks
463fa9e4066Sahrens /*
464fa9e4066Sahrens * Policy for top-level read operations (list pools). Requires no privileges,
465fa9e4066Sahrens * and can be used in the local zone, as there is no associated dataset.
466fa9e4066Sahrens */
467fa9e4066Sahrens /* ARGSUSED */
468fa9e4066Sahrens static int
zfs_secpolicy_none(zfs_cmd_t * zc,nvlist_t * innvl,cred_t * cr)4694445fffbSMatthew Ahrens zfs_secpolicy_none(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
470fa9e4066Sahrens {
471fa9e4066Sahrens return (0);
472fa9e4066Sahrens }
473fa9e4066Sahrens
474fa9e4066Sahrens /*
475fa9e4066Sahrens * Policy for dataset read operations (list children, get statistics). Requires
476fa9e4066Sahrens * no privileges, but must be visible in the local zone.
477fa9e4066Sahrens */
478fa9e4066Sahrens /* ARGSUSED */
479fa9e4066Sahrens static int
zfs_secpolicy_read(zfs_cmd_t * zc,nvlist_t * innvl,cred_t * cr)4804445fffbSMatthew Ahrens zfs_secpolicy_read(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
481fa9e4066Sahrens {
482fa9e4066Sahrens if (INGLOBALZONE(curproc) ||
483ecd6cf80Smarks zone_dataset_visible(zc->zc_name, NULL))
484fa9e4066Sahrens return (0);
485fa9e4066Sahrens
486be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT));
487fa9e4066Sahrens }
488fa9e4066Sahrens
489fa9e4066Sahrens static int
zfs_dozonecheck_impl(const char * dataset,uint64_t zoned,cred_t * cr)490a7f53a56SChris Kirby zfs_dozonecheck_impl(const char *dataset, uint64_t zoned, cred_t *cr)
491fa9e4066Sahrens {
492fa9e4066Sahrens int writable = 1;
493fa9e4066Sahrens
494fa9e4066Sahrens /*
495fa9e4066Sahrens * The dataset must be visible by this zone -- check this first
496fa9e4066Sahrens * so they don't see EPERM on something they shouldn't know about.
497fa9e4066Sahrens */
498fa9e4066Sahrens if (!INGLOBALZONE(curproc) &&
499fa9e4066Sahrens !zone_dataset_visible(dataset, &writable))
500be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT));
501fa9e4066Sahrens
502fa9e4066Sahrens if (INGLOBALZONE(curproc)) {
503fa9e4066Sahrens /*
504fa9e4066Sahrens * If the fs is zoned, only root can access it from the
505fa9e4066Sahrens * global zone.
506fa9e4066Sahrens */
507fa9e4066Sahrens if (secpolicy_zfs(cr) && zoned)
508be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
509fa9e4066Sahrens } else {
510fa9e4066Sahrens /*
511fa9e4066Sahrens * If we are in a local zone, the 'zoned' property must be set.
512fa9e4066Sahrens */
513fa9e4066Sahrens if (!zoned)
514be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
515fa9e4066Sahrens
516fa9e4066Sahrens /* must be writable by this zone */
517fa9e4066Sahrens if (!writable)
518be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
519fa9e4066Sahrens }
520fa9e4066Sahrens return (0);
521fa9e4066Sahrens }
522fa9e4066Sahrens
523a7f53a56SChris Kirby static int
zfs_dozonecheck(const char * dataset,cred_t * cr)524a7f53a56SChris Kirby zfs_dozonecheck(const char *dataset, cred_t *cr)
525a7f53a56SChris Kirby {
526a7f53a56SChris Kirby uint64_t zoned;
527a7f53a56SChris Kirby
528a7f53a56SChris Kirby if (dsl_prop_get_integer(dataset, "zoned", &zoned, NULL))
529be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT));
530a7f53a56SChris Kirby
531a7f53a56SChris Kirby return (zfs_dozonecheck_impl(dataset, zoned, cr));
532a7f53a56SChris Kirby }
533a7f53a56SChris Kirby
534a7f53a56SChris Kirby static int
zfs_dozonecheck_ds(const char * dataset,dsl_dataset_t * ds,cred_t * cr)535a7f53a56SChris Kirby zfs_dozonecheck_ds(const char *dataset, dsl_dataset_t *ds, cred_t *cr)
536a7f53a56SChris Kirby {
537a7f53a56SChris Kirby uint64_t zoned;
538a7f53a56SChris Kirby
5393b2aab18SMatthew Ahrens if (dsl_prop_get_int_ds(ds, "zoned", &zoned))
540be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT));
541a7f53a56SChris Kirby
542a7f53a56SChris Kirby return (zfs_dozonecheck_impl(dataset, zoned, cr));
543a7f53a56SChris Kirby }
544a7f53a56SChris Kirby
5454445fffbSMatthew Ahrens static int
zfs_secpolicy_write_perms_ds(const char * name,dsl_dataset_t * ds,const char * perm,cred_t * cr)5463b2aab18SMatthew Ahrens zfs_secpolicy_write_perms_ds(const char *name, dsl_dataset_t *ds,
5473b2aab18SMatthew Ahrens const char *perm, cred_t *cr)
548fa9e4066Sahrens {
549fa9e4066Sahrens int error;
550fa9e4066Sahrens
55119b94df9SMatthew Ahrens error = zfs_dozonecheck_ds(name, ds, cr);
552ecd6cf80Smarks if (error == 0) {
553ecd6cf80Smarks error = secpolicy_zfs(cr);
5543b2aab18SMatthew Ahrens if (error != 0)
5554445fffbSMatthew Ahrens error = dsl_deleg_access_impl(ds, perm, cr);
556ecd6cf80Smarks }
557ecd6cf80Smarks return (error);
558ecd6cf80Smarks }
559ecd6cf80Smarks
5604445fffbSMatthew Ahrens static int
zfs_secpolicy_write_perms(const char * name,const char * perm,cred_t * cr)5613b2aab18SMatthew Ahrens zfs_secpolicy_write_perms(const char *name, const char *perm, cred_t *cr)
562a7f53a56SChris Kirby {
563a7f53a56SChris Kirby int error;
5643b2aab18SMatthew Ahrens dsl_dataset_t *ds;
5653b2aab18SMatthew Ahrens dsl_pool_t *dp;
566a7f53a56SChris Kirby
56725f7d993SMatthew Ahrens /*
56825f7d993SMatthew Ahrens * First do a quick check for root in the global zone, which
56925f7d993SMatthew Ahrens * is allowed to do all write_perms. This ensures that zfs_ioc_*
57025f7d993SMatthew Ahrens * will get to handle nonexistent datasets.
57125f7d993SMatthew Ahrens */
57225f7d993SMatthew Ahrens if (INGLOBALZONE(curproc) && secpolicy_zfs(cr) == 0)
57325f7d993SMatthew Ahrens return (0);
57425f7d993SMatthew Ahrens
5753b2aab18SMatthew Ahrens error = dsl_pool_hold(name, FTAG, &dp);
5763b2aab18SMatthew Ahrens if (error != 0)
5773b2aab18SMatthew Ahrens return (error);
5783b2aab18SMatthew Ahrens
5793b2aab18SMatthew Ahrens error = dsl_dataset_hold(dp, name, FTAG, &ds);
5803b2aab18SMatthew Ahrens if (error != 0) {
5813b2aab18SMatthew Ahrens dsl_pool_rele(dp, FTAG);
5823b2aab18SMatthew Ahrens return (error);
583a7f53a56SChris Kirby }
5843b2aab18SMatthew Ahrens
5853b2aab18SMatthew Ahrens error = zfs_secpolicy_write_perms_ds(name, ds, perm, cr);
5863b2aab18SMatthew Ahrens
5873b2aab18SMatthew Ahrens dsl_dataset_rele(ds, FTAG);
5883b2aab18SMatthew Ahrens dsl_pool_rele(dp, FTAG);
589a7f53a56SChris Kirby return (error);
590a7f53a56SChris Kirby }
591a7f53a56SChris Kirby
5924201a95eSRic Aleshire /*
5934201a95eSRic Aleshire * Policy for setting the security label property.
5944201a95eSRic Aleshire *
5954201a95eSRic Aleshire * Returns 0 for success, non-zero for access and other errors.
5964201a95eSRic Aleshire */
5974201a95eSRic Aleshire static int
zfs_set_slabel_policy(const char * name,char * strval,cred_t * cr)59892241e0bSTom Erickson zfs_set_slabel_policy(const char *name, char *strval, cred_t *cr)
5994201a95eSRic Aleshire {
6004201a95eSRic Aleshire char ds_hexsl[MAXNAMELEN];
6014201a95eSRic Aleshire bslabel_t ds_sl, new_sl;
6024201a95eSRic Aleshire boolean_t new_default = FALSE;
6034201a95eSRic Aleshire uint64_t zoned;
6044201a95eSRic Aleshire int needed_priv = -1;
6054201a95eSRic Aleshire int error;
6064201a95eSRic Aleshire
6074201a95eSRic Aleshire /* First get the existing dataset label. */
6084201a95eSRic Aleshire error = dsl_prop_get(name, zfs_prop_to_name(ZFS_PROP_MLSLABEL),
6094201a95eSRic Aleshire 1, sizeof (ds_hexsl), &ds_hexsl, NULL);
6103b2aab18SMatthew Ahrens if (error != 0)
611be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
6124201a95eSRic Aleshire
6134201a95eSRic Aleshire if (strcasecmp(strval, ZFS_MLSLABEL_DEFAULT) == 0)
6144201a95eSRic Aleshire new_default = TRUE;
6154201a95eSRic Aleshire
6164201a95eSRic Aleshire /* The label must be translatable */
6174201a95eSRic Aleshire if (!new_default && (hexstr_to_label(strval, &new_sl) != 0))
618be6fd75aSMatthew Ahrens return (SET_ERROR(EINVAL));
6194201a95eSRic Aleshire
6204201a95eSRic Aleshire /*
6214201a95eSRic Aleshire * In a non-global zone, disallow attempts to set a label that
6224201a95eSRic Aleshire * doesn't match that of the zone; otherwise no other checks
6234201a95eSRic Aleshire * are needed.
6244201a95eSRic Aleshire */
6254201a95eSRic Aleshire if (!INGLOBALZONE(curproc)) {
6264201a95eSRic Aleshire if (new_default || !blequal(&new_sl, CR_SL(CRED())))
627be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
6284201a95eSRic Aleshire return (0);
6294201a95eSRic Aleshire }
6304201a95eSRic Aleshire
6314201a95eSRic Aleshire /*
6324201a95eSRic Aleshire * For global-zone datasets (i.e., those whose zoned property is
6334201a95eSRic Aleshire * "off", verify that the specified new label is valid for the
6344201a95eSRic Aleshire * global zone.
6354201a95eSRic Aleshire */
6364201a95eSRic Aleshire if (dsl_prop_get_integer(name,
6374201a95eSRic Aleshire zfs_prop_to_name(ZFS_PROP_ZONED), &zoned, NULL))
638be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
6394201a95eSRic Aleshire if (!zoned) {
6404201a95eSRic Aleshire if (zfs_check_global_label(name, strval) != 0)
641be6fd75aSMatthew Ahrens return (SET_ERROR(EPERM));
6424201a95eSRic Aleshire }
6434201a95eSRic Aleshire
644