1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

Fix kernel panic when moving a file to .zfs/shares

Fix possible loss of correct error return code in ZFS mount

OpenSolaris revisions and Bug IDs:

11824:53128e5db7cf
6863610	ZFS mount can lose correct error return

12079:13822b941977
6939941	problem with moving files in zfs (142901-12)

Approved by:	delphij (mentor)
Obtained from:	OpenSolaris (Bug ID 6863610, 6939941)
MFC after:	3 days
This commit is contained in:
Martin Matuska 2010-09-15 19:55:26 +00:00
parent 0e2b59be50
commit d1ee63f836
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=212694
5 changed files with 41 additions and 23 deletions

View File

@ -76,6 +76,7 @@ vn_is_readonly(vnode_t *vp)
#define vn_invalid(vp) do { } while (0)
#define vn_renamepath(tdvp, svp, tnm, lentnm) do { } while (0)
#define vn_free(vp) do { } while (0)
#define vn_matchops(vp, vops) ((vp)->v_op == &(vops))
#define VN_HOLD(v) vref(v)
#define VN_RELE(v) vrele(v)

View File

@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _ZFS_CTLDIR_H
@ -48,6 +47,7 @@ void zfsctl_destroy(zfsvfs_t *);
vnode_t *zfsctl_root(znode_t *);
void zfsctl_init(void);
void zfsctl_fini(void);
boolean_t zfsctl_is_node(vnode_t *);
int zfsctl_rename_snapshot(const char *from, const char *to);
int zfsctl_destroy_snapshot(const char *snapname, int force);

View File

@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@ -152,6 +151,17 @@ zfsctl_fini(void)
{
}
boolean_t
zfsctl_is_node(vnode_t *vp)
{
return (vn_matchops(vp, zfsctl_ops_root) ||
vn_matchops(vp, zfsctl_ops_snapdir) ||
vn_matchops(vp, zfsctl_ops_snapshot) ||
vn_matchops(vp, zfsctl_ops_shares) ||
vn_matchops(vp, zfsctl_ops_shares_dir));
}
/*
* Return the inode number associated with the 'snapshot' or
* 'shares' directory.

View File

@ -1163,8 +1163,7 @@ zfs_mount(vfs_t *vfsp)
*/
error = secpolicy_fs_mount(cr, mvp, vfsp);
if (error) {
error = dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr);
if (error != 0)
if (dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr) != 0)
goto out;
if (!(vfsp->vfs_flag & MS_REMOUNT)) {
@ -1178,7 +1177,7 @@ zfs_mount(vfs_t *vfsp)
vattr.va_mask = AT_UID;
vn_lock(mvp, LK_SHARED | LK_RETRY);
if (error = VOP_GETATTR(mvp, &vattr, cr)) {
if (VOP_GETATTR(mvp, &vattr, cr)) {
VOP_UNLOCK(mvp, 0);
goto out;
}
@ -1433,9 +1432,8 @@ zfs_umount(vfs_t *vfsp, int fflag)
ret = secpolicy_fs_unmount(cr, vfsp);
if (ret) {
ret = dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource),
ZFS_DELEG_PERM_MOUNT, cr);
if (ret)
if (dsl_deleg_access((char *)refstr_value(vfsp->vfs_resource),
ZFS_DELEG_PERM_MOUNT, cr))
return (ret);
}
/*

View File

@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Portions Copyright 2007 Jeremy Teo */
@ -3357,7 +3356,7 @@ zfs_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr,
if (VOP_REALVP(tdvp, &realvp, ct) == 0)
tdvp = realvp;
if (tdvp->v_vfsp != sdvp->v_vfsp) {
if (tdvp->v_vfsp != sdvp->v_vfsp || zfsctl_is_node(tdvp)) {
ZFS_EXIT(zfsvfs);
return (EXDEV);
}
@ -3875,6 +3874,7 @@ zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
vnode_t *realvp;
int error;
int zf = ZNEW;
uint64_t parent;
uid_t owner;
ASSERT(tdvp->v_type == VDIR);
@ -3886,13 +3886,30 @@ zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
if (VOP_REALVP(svp, &realvp, ct) == 0)
svp = realvp;
if (svp->v_vfsp != tdvp->v_vfsp) {
/*
* POSIX dictates that we return EPERM here.
* Better choices include ENOTSUP or EISDIR.
*/
if (svp->v_type == VDIR) {
ZFS_EXIT(zfsvfs);
return (EPERM);
}
if (svp->v_vfsp != tdvp->v_vfsp || zfsctl_is_node(svp)) {
ZFS_EXIT(zfsvfs);
return (EXDEV);
}
szp = VTOZ(svp);
ZFS_VERIFY_ZP(szp);
/* Prevent links to .zfs/shares files */
if (szp->z_phys->zp_parent == zfsvfs->z_shares_dir) {
ZFS_EXIT(zfsvfs);
return (EPERM);
}
if (zfsvfs->z_utf8 && u8_validate(name,
strlen(name), NULL, U8_VALIDATE_ENTIRE, &error) < 0) {
ZFS_EXIT(zfsvfs);
@ -3901,7 +3918,6 @@ zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
if (flags & FIGNORECASE)
zf |= ZCILOOK;
top:
/*
* We do not support links between attributes and non-attributes
* because of the potential security risk of creating links
@ -3914,14 +3930,6 @@ zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
return (EINVAL);
}
/*
* POSIX dictates that we return EPERM here.
* Better choices include ENOTSUP or EISDIR.
*/
if (svp->v_type == VDIR) {
ZFS_EXIT(zfsvfs);
return (EPERM);
}
owner = zfs_fuid_map_id(zfsvfs, szp->z_phys->zp_uid, cr, ZFS_OWNER);
if (owner != crgetuid(cr) &&
@ -3935,6 +3943,7 @@ zfs_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr,
return (error);
}
top:
/*
* Attempt to lock directory; fail if entry already exists.
*/