Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/sys/dsl_dataset.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ typedef struct dsl_dataset {

/* Protected by ds_lock; keep at end of struct for better locality */
char ds_snapname[ZFS_MAX_DATASET_NAME_LEN];

#ifdef __FreeBSD__
char *ds_jailname;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not familiar with zones, but wouldn't this functionality apply there too? Would some ds_zonename without the ifdef be more universal?

#endif
} dsl_dataset_t;

static inline dsl_dataset_phys_t *
Expand Down
1 change: 1 addition & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ typedef enum {
ZFS_PROP_DEFAULTUSEROBJQUOTA,
ZFS_PROP_DEFAULTGROUPOBJQUOTA,
ZFS_PROP_DEFAULTPROJECTOBJQUOTA,
ZFS_PROP_ZONE,
ZFS_NUM_PROPS
} zfs_prop_t;

Expand Down
3 changes: 2 additions & 1 deletion lib/libzfs/libzfs.abi
Original file line number Diff line number Diff line change
Expand Up @@ -2259,7 +2259,8 @@
<enumerator name='ZFS_PROP_DEFAULTUSEROBJQUOTA' value='103'/>
<enumerator name='ZFS_PROP_DEFAULTGROUPOBJQUOTA' value='104'/>
<enumerator name='ZFS_PROP_DEFAULTPROJECTOBJQUOTA' value='105'/>
<enumerator name='ZFS_NUM_PROPS' value='106'/>
<enumerator name='ZFS_PROP_ZONE' value='106'/>
<enumerator name='ZFS_NUM_PROPS' value='107'/>
</enum-decl>
<typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
<enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>
Expand Down
10 changes: 10 additions & 0 deletions man/man7/zfsprops.7
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,16 @@ for more information.
Jails are a
.Fx
feature and this property is not available on other platforms.
.It Sy jail
This read-only property reports name of the jail that mounted the jailed
dataset.
The "0" name is used for datasets that are not mounted or not jailed.
This differs from the normal ZFS convention to print dash ('-') for unset
values, since it can be a valid jail name.
If the jail is renamed, the property will still report its old name from
the time the dataset was mounted.
Comment on lines +2104 to +2105
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes me wonder if reporting jail ID would be more predictable.

The reported jail may no longer exist, while the dataset remains mounted.
The property is not revealed to jails themselves, the "0" is reported instead.
.It Sy zoned Ns = Ns Sy off Ns | Ns Sy on
Controls whether the dataset is managed from a non-global zone or namespace.
See
Expand Down
18 changes: 18 additions & 0 deletions module/os/freebsd/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,18 @@ zfs_domount(vfs_t *vfsp, char *osname)

if (!zfsvfs->z_issnap)
zfsctl_create(zfsvfs);

#ifdef __FreeBSD__
if (error == 0) {
/* zone dataset visiblity was checked before in zfs_mount() */
struct prison *pr = curthread->td_ucred->cr_prison;
if (pr != &prison0) {
zfsvfs->z_os->os_dsl_dataset->ds_jailname =
kmem_strdup(pr->pr_name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I am not closely familiar with the zone/jail code in ZFS, but I am not sure the delegation should necessarily be tied to a mounting. I suppose some dataset may not be mounted, but be controlled by the jail. Am I wrong?

}
}
#endif

out:
if (error) {
dmu_objset_disown(zfsvfs->z_os, B_TRUE, zfsvfs);
Expand Down Expand Up @@ -1783,6 +1795,12 @@ zfs_umount(vfs_t *vfsp, int fflag)
dmu_objset_set_user(os, NULL);
mutex_exit(&os->os_user_ptr_lock);

#ifdef __FreeBSD__
if (os->os_dsl_dataset->ds_jailname)
kmem_strfree(os->os_dsl_dataset->ds_jailname);
os->os_dsl_dataset->ds_jailname = NULL;
#endif

/*
* Finally release the objset
*/
Expand Down
4 changes: 4 additions & 0 deletions module/zcommon/zfs_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,9 +516,13 @@ zfs_prop_init(void)
zprop_register_index(ZFS_PROP_ZONED, "jailed", 0, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM, "on | off", "JAILED", boolean_table,
sfeatures);
zprop_register_string(ZFS_PROP_ZONE, "jail", NULL, PROP_READONLY,
ZFS_TYPE_FILESYSTEM, "<jailname> | 0", "JAIL", sfeatures);
#else
zprop_register_index(ZFS_PROP_ZONED, "zoned", 0, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM, "on | off", "ZONED", boolean_table, sfeatures);
zprop_register_string(ZFS_PROP_ZONE, "zone", NULL, PROP_READONLY,
ZFS_TYPE_FILESYSTEM, "<zonename>", "ZONE", sfeatures);
#endif
zprop_register_index(ZFS_PROP_VSCAN, "vscan", 0, PROP_INHERIT,
ZFS_TYPE_FILESYSTEM, "on | off", "VSCAN", boolean_table, sfeatures);
Expand Down
9 changes: 9 additions & 0 deletions module/zfs/dsl_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,15 @@ dsl_prop_get_all_ds(dsl_dataset_t *ds, nvlist_t **nvp,
goto out;
}

#ifdef __FreeBSD__
nvlist_t *propval = fnvlist_alloc();
fnvlist_add_string(propval, ZPROP_VALUE,
(ds->ds_jailname && INGLOBALZONE(curproc)) ?
ds->ds_jailname : "0");
fnvlist_add_nvlist(*nvp, "jail", propval);
nvlist_free(propval);
#endif

for (; dd != NULL; dd = dd->dd_parent) {
if (dd != ds->ds_dir || (flags & DSL_PROP_GET_SNAPSHOT)) {
if (flags & (DSL_PROP_GET_LOCAL |
Expand Down
2 changes: 1 addition & 1 deletion tests/runfiles/freebsd.run
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ failsafe = callbacks/zfs_failsafe
tags = ['functional']

[tests/functional/cli_root/zfs_jail:FreeBSD]
tests = ['zfs_jail_001_pos']
tests = ['zfs_jail_001_pos', 'zfs_jail_property']
tags = ['functional', 'cli_root', 'zfs_jail']

[tests/functional/pam:FreeBSD]
Expand Down
1 change: 1 addition & 0 deletions tests/zfs-tests/tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_jail/cleanup.ksh \
functional/cli_root/zfs_jail/setup.ksh \
functional/cli_root/zfs_jail/zfs_jail_001_pos.ksh \
functional/cli_root/zfs_jail/zfs_jail_property.ksh \
functional/cli_root/zfs_load-key/cleanup.ksh \
functional/cli_root/zfs_load-key/setup.ksh \
functional/cli_root/zfs_load-key/zfs_load-key_all.ksh \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
# 1. Create a jail.
# 2. Perform some basic ZFS operations on a dataset both in the host and
# in the jail to confirm the dataset is functional in the host
# and hidden in in the jail.
# and hidden in the jail.
# 3. Run `zfs jail` to expose the dataset in the jail.
# 4. Perform some basic ZFS operations on the dataset both in the host and
# in the jail to confirm the dataset is functional in the jail and host.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/bin/ksh -p
# SPDX-License-Identifier: CDDL-1.0
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or https://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright 2025 SkunkWerks, GmbH
#

. $STF_SUITE/include/libtest.shlib

#
# DESCRIPTION:
# Test basic use cases of "jail" zfs dataset property.
#
# STRATEGY:
# 1. Create a dataset. Verify.
# 2. Create a jail. Verify.
# 3. Jail the dataset. Verify.
# 4. Mount the dataset by the jail. Verify.
# 5. Unmount the dataset. Verify.
#

verify_runnable "global"

JAIL="testjail"
JAIL_CONF="$STF_SUITE/tests/functional/cli_root/zfs_jail/jail.conf"
DATASET="$TESTPOOL/dataset1"
DATASET_JAILED_MOUNTPOINT="/jailed"

function cleanup
{
if jls -j $JAIL name >/dev/null 2>&1; then
jail -r -f $JAIL_CONF $JAIL
fi
}

log_onexit cleanup

log_assert "Verify basic use cases of jail zfs property."

# Root dataset has default value
log_must test "0" = "$(zfs get -o value -H jail $TESTPOOL)"

# Create the dataset
log_must zfs create -o jailed=on -o mountpoint=$DATASET_JAILED_MOUNTPOINT $DATASET
log_must test "0" = "$(zfs get -o value -H jail $DATASET)"

# Create the jail
log_must jail -c -f $JAIL_CONF $JAIL
log_mustnot jexec $JAIL zfs list $DATASET
log_must test "0" = "$(zfs get -o value -H jail $DATASET)"

# Jail the dataset
log_must zfs jail $JAIL $DATASET
log_must jexec $JAIL zfs list $DATASET
log_must test "0" = "$(zfs get -o value -H jail $DATASET)"
log_must test "0" = "$(jexec $JAIL zfs get -o value -H jail $DATASET)"

# Mount the dataset by the jail
log_must jexec $JAIL zfs mount $DATASET
# Now we see who mounted it
log_must test "$JAIL" = "$(zfs get -o value -H jail $DATASET)"
# But it is hidden from the jail itself
log_must test "0" = "$(jexec $JAIL zfs get -o value -H jail $DATASET)"

# Unmount the dataset by the jail
log_must jexec $JAIL zfs unmount $DATASET
log_must test "0" = "$(zfs get -o value -H jail $DATASET)"
log_must test "0" = "$(jexec $JAIL zfs get -o value -H jail $DATASET)"

log_pass "Verify basic use cases of jail zfs property."
Loading