From 192536d62b085bb14f54ffc958e6303810cca624 Mon Sep 17 00:00:00 2001 From: Ken Hornstein Date: Wed, 20 Nov 2013 13:37:52 -0500 Subject: [PATCH] Support for changes to OS X Mavericks VNOP_SYMLINK() function. Add support for an extra argument to afs_symlink() to return the newly-created symlink vnode if requested (this is needed on OS X Mavericks). On OS X Mavericks return the newly-created symlink vnode in the symlink vnops functions, on all other platforms ignore it. It turns out that technically OS X has required the symlink to be created for a while, but code inside of symlink() would call namei() on the symlink name if the returned vnode point was NULL. The difference is that on Mavericks the Manditory Access Control Framework has been enabled, and that turns on some extra code which unconditionally calls vnode_mount() on the returned vnode pointer, which ends up causing a panic Reviewed-on: http://gerrit.openafs.org/10474 Reviewed-by: Derrick Brashear Tested-by: BuildBot (cherry picked from commit 3f4c1099b7b2d1467b1f5b701ea2f953fec20dc0) Change-Id: Ib8bac6fd4ed8fe5c2e9567431f7d03fdab50cd50 Reviewed-on: http://gerrit.openafs.org/10519 Tested-by: BuildBot Reviewed-by: Benjamin Kaduk Reviewed-by: Andrew Deason Reviewed-by: Jeffrey Altman Reviewed-by: Stephan Wiesand --- src/afs/AIX/osi_vnodeops.c | 2 +- src/afs/DARWIN/osi_vnodeops.c | 14 ++++++++++---- src/afs/FBSD/osi_vnodeops.c | 3 ++- src/afs/HPUX/osi_vnodeops.c | 2 +- src/afs/LINUX/osi_vnodeops.c | 3 ++- src/afs/LINUX24/osi_vnodeops.c | 3 ++- src/afs/NBSD/osi_vnodeops.c | 2 +- src/afs/OBSD/osi_vnodeops.c | 3 ++- src/afs/SOLARIS/osi_vnodeops.c | 2 +- src/afs/UKERNEL/afs_usrops.c | 3 ++- src/afs/UKERNEL/sysincludes.h | 2 +- src/afs/VNOPS/afs_vnop_symlink.c | 7 +++++-- src/afs/afs_prototypes.h | 2 +- 13 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/afs/AIX/osi_vnodeops.c b/src/afs/AIX/osi_vnodeops.c index 0e4000159..b86347e16 100644 --- a/src/afs/AIX/osi_vnodeops.c +++ b/src/afs/AIX/osi_vnodeops.c @@ -1420,7 +1420,7 @@ afs_gn_symlink(struct vnode *vp, AFS_STATCNT(afs_gn_symlink); VATTR_NULL(&va); va.va_mode = 0777; - error = afs_symlink(vp, link, &va, target, cred); + error = afs_symlink(vp, link, &va, target, NULL, cred); afs_Trace4(afs_iclSetp, CM_TRACE_GSYMLINK, ICL_TYPE_POINTER, vp, ICL_TYPE_STRING, link, ICL_TYPE_STRING, target, ICL_TYPE_LONG, error); diff --git a/src/afs/DARWIN/osi_vnodeops.c b/src/afs/DARWIN/osi_vnodeops.c index 1b2156ffe..54c07ad6c 100644 --- a/src/afs/DARWIN/osi_vnodeops.c +++ b/src/afs/DARWIN/osi_vnodeops.c @@ -1655,19 +1655,25 @@ afs_vop_symlink(ap) * } */ *ap; { struct vnode *dvp = ap->a_dvp; + struct vcache *vpp = NULL; int error = 0; - /* NFS ignores a_vpp; so do we. */ GETNAME(); AFS_GLOCK(); - error = - afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred); + error = afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, &vpp, + vop_cn_cred); AFS_GUNLOCK(); - DROPNAME(); #ifndef AFS_DARWIN80_ENV FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI); vput(dvp); #endif + *ap->a_vpp = NULL; + if (!error) { + error = afs_darwin_finalizevnode(vpp, dvp, ap->a_cnp, 0, 0); + if (! error) + *ap->a_vpp = AFSTOV(vpp); + } + DROPNAME(); return error; } diff --git a/src/afs/FBSD/osi_vnodeops.c b/src/afs/FBSD/osi_vnodeops.c index ac16df034..7a521524e 100644 --- a/src/afs/FBSD/osi_vnodeops.c +++ b/src/afs/FBSD/osi_vnodeops.c @@ -1365,7 +1365,8 @@ afs_vop_symlink(struct vop_symlink_args *ap) newvp = NULL; error = - afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred); + afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL, + cnp->cn_cred); if (error == 0) { error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred); if (error == 0) { diff --git a/src/afs/HPUX/osi_vnodeops.c b/src/afs/HPUX/osi_vnodeops.c index a9114ef98..dab15dbfe 100644 --- a/src/afs/HPUX/osi_vnodeops.c +++ b/src/afs/HPUX/osi_vnodeops.c @@ -502,7 +502,7 @@ mp_afs_symlink(struct vnode *adp, char *aname, struct vattr *attrs, int code; AFS_GLOCK(); - code = afs_symlink(adp, aname, attrs, atargetName, acred); + code = afs_symlink(adp, aname, attrs, atargetName, NULL, acred); AFS_GUNLOCK(); return (code); } diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index ada29624a..b3190baf0 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1568,7 +1568,8 @@ afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target) VATTR_NULL(&vattr); AFS_GLOCK(); - code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp); + code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, NULL, + credp); AFS_GUNLOCK(); crfree(credp); return afs_convert_code(code); diff --git a/src/afs/LINUX24/osi_vnodeops.c b/src/afs/LINUX24/osi_vnodeops.c index 5351a7e09..9ac0b1ca3 100644 --- a/src/afs/LINUX24/osi_vnodeops.c +++ b/src/afs/LINUX24/osi_vnodeops.c @@ -1429,7 +1429,8 @@ afs_linux_symlink(struct inode *dip, struct dentry *dp, const char *target) VATTR_NULL(&vattr); AFS_GLOCK(); - code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, credp); + code = afs_symlink(VTOAFS(dip), (char *)name, &vattr, (char *)target, NULL, + credp); AFS_GUNLOCK(); crfree(credp); return afs_convert_code(code); diff --git a/src/afs/NBSD/osi_vnodeops.c b/src/afs/NBSD/osi_vnodeops.c index 56c42a327..48e29f09f 100644 --- a/src/afs/NBSD/osi_vnodeops.c +++ b/src/afs/NBSD/osi_vnodeops.c @@ -852,7 +852,7 @@ afs_nbsd_symlink(void *v) GETNAME(); AFS_GLOCK(); code = - afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, + afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL, cnp->cn_cred); AFS_GUNLOCK(); DROPCNP(cnp); diff --git a/src/afs/OBSD/osi_vnodeops.c b/src/afs/OBSD/osi_vnodeops.c index 9bf045d4a..141c88172 100644 --- a/src/afs/OBSD/osi_vnodeops.c +++ b/src/afs/OBSD/osi_vnodeops.c @@ -847,7 +847,8 @@ afs_obsd_symlink(void *v) GETNAME(); AFS_GLOCK(); code = - afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred); + afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL, + cnp->cn_cred); AFS_GUNLOCK(); DROPCNP(cnp); DROPNAME(); diff --git a/src/afs/SOLARIS/osi_vnodeops.c b/src/afs/SOLARIS/osi_vnodeops.c index f810c6db9..ff1e124bc 100644 --- a/src/afs/SOLARIS/osi_vnodeops.c +++ b/src/afs/SOLARIS/osi_vnodeops.c @@ -1771,7 +1771,7 @@ gafs_symlink(struct vcache *adp, char *aname, struct vattr *attrs, int code; AFS_GLOCK(); - code = afs_symlink(adp, aname, attrs, atargetName, acred); + code = afs_symlink(adp, aname, attrs, atargetName, NULL, acred); AFS_GUNLOCK(); return (code); } diff --git a/src/afs/UKERNEL/afs_usrops.c b/src/afs/UKERNEL/afs_usrops.c index a4a0fdbae..a9825e8ea 100644 --- a/src/afs/UKERNEL/afs_usrops.c +++ b/src/afs/UKERNEL/afs_usrops.c @@ -3043,7 +3043,8 @@ uafs_symlink_r(char *target, char *source) attrs.va_mode = 0777; attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred); attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred); - code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred); + code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, NULL, + get_user_struct()->u_cred); VN_RELE(dirP); if (code != 0) { errno = code; diff --git a/src/afs/UKERNEL/sysincludes.h b/src/afs/UKERNEL/sysincludes.h index f5b2d9621..1b5b7f7f5 100644 --- a/src/afs/UKERNEL/sysincludes.h +++ b/src/afs/UKERNEL/sysincludes.h @@ -1246,7 +1246,7 @@ struct usr_vnodeops { int (*vn_rmdir) (struct vcache *adp, char *, afs_ucred_t *); int (*vn_readdir) (struct vcache *avc, struct uio *, afs_ucred_t *); int (*vn_symlink) (struct vcache *adp, char *, struct vattr *, char *, - afs_ucred_t *); + struct vcache **vpp, afs_ucred_t *); int (*vn_readlink) (struct vcache *avc, struct uio *, afs_ucred_t *); int (*vn_fsync) (struct vcache *avc, afs_ucred_t *); int (*vn_inactive) (struct vcache *avc, afs_ucred_t *acred); diff --git a/src/afs/VNOPS/afs_vnop_symlink.c b/src/afs/VNOPS/afs_vnop_symlink.c index faf103e13..95f69736d 100644 --- a/src/afs/VNOPS/afs_vnop_symlink.c +++ b/src/afs/VNOPS/afs_vnop_symlink.c @@ -66,7 +66,7 @@ afs_DisconCreateSymlink(struct vcache *avc, char *aname, /* don't set CDirty in here because RPC is called synchronously */ int afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, - char *atargetName, afs_ucred_t *acred) + char *atargetName, struct vcache **tvcp, afs_ucred_t *acred) { afs_uint32 now = 0; struct vrequest treq; @@ -284,7 +284,10 @@ afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, } ReleaseWriteLock(&tvc->lock); ReleaseWriteLock(&afs_xvcache); - afs_PutVCache(tvc); + if (tvcp) + *tvcp = tvc; + else + afs_PutVCache(tvc); code = 0; done: afs_PutFakeStat(&fakestate); diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h index 1d6d72f36..d8c4b8904 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -1291,7 +1291,7 @@ extern int afs_UFSHandleLink(struct vcache *avc, struct vrequest *areq); extern int afs_symlink(OSI_VC_DECL(adp), char *aname, struct vattr *attrs, char *atargetName, - afs_ucred_t *acred); + struct vcache **tvcp, afs_ucred_t *acred); extern int afs_readlink(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred); -- 2.39.5