Module Name: src Committed By: hannken Date: Thu Dec 6 10:00:40 UTC 2018
Modified Files: src/external/cddl/osnet/dist/uts/common/fs/zfs: zfs_vnops.c Log Message: We have component names as counted strings (cn_nameptr, cn_namelen) but ZFS expects a null-terminated name. Always create a copy with PNBUF_GET()/strlcpy()/PNBUF_PUT(). For LOOKUP use a small buffer on stack and allocate/free compomnent names longer than 30 chars. To generate a diff of this commit: cvs rdiff -u -r1.36 -r1.37 \ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c diff -u src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.36 src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.37 --- src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c:1.36 Fri Nov 30 09:53:40 2018 +++ src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c Thu Dec 6 10:00:40 2018 @@ -3847,8 +3847,13 @@ zfs_rename_relock(struct vnode *sdvp, st zfsvfs_t *zfsvfs; struct vnode *nvp, *svp, *tvp; znode_t *sdzp, *tdzp, *szp, *tzp; +#ifdef __FreeBSD__ const char *snm = scnp->cn_nameptr; const char *tnm = tcnp->cn_nameptr; +#endif +#ifdef __NetBSD__ + char *snm, *tnm; +#endif int error; #ifdef __FreeBSD__ @@ -3918,7 +3923,15 @@ relock: * Re-resolve svp to be certain it still exists and fetch the * correct vnode. */ +#ifdef __NetBSD__ + /* ZFS wants a null-terminated name. */ + snm = PNBUF_GET(); + strlcpy(snm, scnp->cn_nameptr, scnp->cn_namelen + 1); +#endif error = zfs_dirent_lookup(sdzp, snm, &szp, ZEXISTS); +#ifdef __NetBSD__ + PNBUF_PUT(snm); +#endif if (error != 0) { /* Source entry invalid or not there. */ ZFS_EXIT(zfsvfs); @@ -3937,7 +3950,15 @@ relock: /* * Re-resolve tvp, if it disappeared we just carry on. */ +#ifdef __NetBSD__ + /* ZFS wants a null-terminated name. */ + tnm = PNBUF_GET(); + strlcpy(tnm, tcnp->cn_nameptr, tcnp->cn_namelen + 1); +#endif error = zfs_dirent_lookup(tdzp, tnm, &tzp, 0); +#ifdef __NetBSD__ + PNBUF_PUT(tnm); +#endif if (error != 0) { ZFS_EXIT(zfsvfs); VOP_UNLOCK(sdvp, 0); @@ -4138,8 +4159,13 @@ zfs_rename(vnode_t *sdvp, vnode_t **svpp znode_t *sdzp, *tdzp, *szp, *tzp; zilog_t *zilog = NULL; dmu_tx_t *tx; +#ifdef __FreeBSD__ char *snm = __UNCONST(scnp->cn_nameptr); char *tnm = __UNCONST(tcnp->cn_nameptr); +#endif +#ifdef __NetBSD__ + char *snm, *tnm; +#endif int error = 0; /* Reject renames across filesystems. */ @@ -4167,6 +4193,13 @@ zfs_rename(vnode_t *sdvp, vnode_t **svpp sdzp = VTOZ(sdvp); zfsvfs = tdzp->z_zfsvfs; zilog = zfsvfs->z_log; +#ifdef __NetBSD__ + /* ZFS wants a null-terminated name. */ + snm = PNBUF_GET(); + strlcpy(snm, scnp->cn_nameptr, scnp->cn_namelen + 1); + tnm = PNBUF_GET(); + strlcpy(tnm, tcnp->cn_nameptr, tcnp->cn_namelen + 1); +#endif /* * After we re-enter ZFS_ENTER() we will have to revalidate all @@ -4388,6 +4421,10 @@ unlockout: /* all 4 vnodes are locked, VOP_UNLOCK(*svpp, 0); VOP_UNLOCK(sdvp, 0); +#ifdef __NetBSD__ + PNBUF_PUT(snm); + PNBUF_PUT(tnm); +#endif if (*tvpp != sdvp && *tvpp != *svpp) if (*tvpp != NULL) @@ -5060,12 +5097,11 @@ zfs_netbsd_lookup(void *v) struct vnode *dvp = ap->a_dvp; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; - char nm[NAME_MAX + 1]; + char *nm, short_nm[31]; int error; int iswhiteout; KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); - KASSERT(cnp->cn_namelen < sizeof nm); *vpp = NULL; @@ -5095,11 +5131,19 @@ zfs_netbsd_lookup(void *v) * zfs_lookup wants a null-terminated component name, but namei * gives us a pointer into the full pathname. */ + ASSERT(cnp->cn_namelen < PATH_MAX - 1); + if (cnp->cn_namelen + 1 > sizeof(short_nm)) + nm = PNBUF_GET(); + else + nm = short_nm; (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); error = zfs_lookup(dvp, nm, vpp, NULL, 0, NULL, cnp->cn_cred, NULL, NULL, NULL); + if (nm != short_nm) + PNBUF_PUT(nm); + /* * Translate errors to match our namei insanity. Also, if the * caller wants to create an entry here, it's apparently our @@ -5174,6 +5218,7 @@ zfs_netbsd_create(void *v) struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; struct vattr *vap = ap->a_vap; + char *nm; int mode; int error; @@ -5182,9 +5227,14 @@ zfs_netbsd_create(void *v) vattr_init_mask(vap); mode = vap->va_mode & ALLPERMS; + /* ZFS wants a null-terminated name. */ + nm = PNBUF_GET(); + (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); + /* XXX !EXCL is wrong here... */ - error = zfs_create(dvp, __UNCONST(cnp->cn_nameptr), vap, !EXCL, mode, - vpp, cnp->cn_cred, NULL); + error = zfs_create(dvp, nm, vap, !EXCL, mode, vpp, cnp->cn_cred, NULL); + + PNBUF_PUT(nm); KASSERT((error == 0) == (*vpp != NULL)); KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); @@ -5204,12 +5254,19 @@ zfs_netbsd_remove(void *v) struct vnode *dvp = ap->a_dvp; struct vnode *vp = ap->a_vp; struct componentname *cnp = ap->a_cnp; + char *nm; int error; KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); - error = zfs_remove(dvp, vp, __UNCONST(cnp->cn_nameptr), cnp->cn_cred); + /* ZFS wants a null-terminated name. */ + nm = PNBUF_GET(); + (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); + + error = zfs_remove(dvp, vp, nm, cnp->cn_cred); + + PNBUF_PUT(nm); vput(vp); KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); return (error); @@ -5228,14 +5285,20 @@ zfs_netbsd_mkdir(void *v) struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; struct vattr *vap = ap->a_vap; + char *nm; int error; KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); vattr_init_mask(vap); - error = zfs_mkdir(dvp, __UNCONST(cnp->cn_nameptr), vap, vpp, - cnp->cn_cred); + /* ZFS wants a null-terminated name. */ + nm = PNBUF_GET(); + (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); + + error = zfs_mkdir(dvp, nm, vap, vpp, cnp->cn_cred); + + PNBUF_PUT(nm); KASSERT((error == 0) == (*vpp != NULL)); KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); @@ -5255,12 +5318,19 @@ zfs_netbsd_rmdir(void *v) struct vnode *dvp = ap->a_dvp; struct vnode *vp = ap->a_vp; struct componentname *cnp = ap->a_cnp; + char *nm; int error; KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); - error = zfs_rmdir(dvp, vp, __UNCONST(cnp->cn_nameptr), cnp->cn_cred); + /* ZFS wants a null-terminated name. */ + nm = PNBUF_GET(); + (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); + + error = zfs_rmdir(dvp, vp, nm, cnp->cn_cred); + + PNBUF_PUT(nm); vput(vp); KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); return error; @@ -5494,6 +5564,7 @@ zfs_netbsd_symlink(void *v) struct componentname *cnp = ap->a_cnp; struct vattr *vap = ap->a_vap; char *target = ap->a_target; + char *nm; int error; KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); @@ -5501,8 +5572,13 @@ zfs_netbsd_symlink(void *v) vap->va_type = VLNK; /* Netbsd: Syscall only sets va_mode. */ vattr_init_mask(vap); - error = zfs_symlink(dvp, vpp, __UNCONST(cnp->cn_nameptr), vap, target, - cnp->cn_cred, 0); + /* ZFS wants a null-terminated name. */ + nm = PNBUF_GET(); + (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); + + error = zfs_symlink(dvp, vpp, nm, vap, target, cnp->cn_cred, 0); + + PNBUF_PUT(nm); KASSERT((error == 0) == (*vpp != NULL)); KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); @@ -5530,13 +5606,20 @@ zfs_netbsd_link(void *v) struct vnode *dvp = ap->a_dvp; struct vnode *vp = ap->a_vp; struct componentname *cnp = ap->a_cnp; + char *nm; int error; KASSERT(VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); + /* ZFS wants a null-terminated name. */ + nm = PNBUF_GET(); + (void)strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); + vn_lock(vp, LK_EXCLUSIVE); - error = zfs_link(dvp, vp, __UNCONST(cnp->cn_nameptr), cnp->cn_cred, + error = zfs_link(dvp, vp, nm, cnp->cn_cred, NULL, 0); + + PNBUF_PUT(nm); VOP_UNLOCK(vp, 0); return error; }