From 3f4c1099b7b2d1467b1f5b701ea2f953fec20dc0 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 Change-Id: I33b2f51cd10f76689eb9868eb05800ab493087c4 Reviewed-on: http://gerrit.openafs.org/10474 Reviewed-by: Derrick Brashear Tested-by: BuildBot --- 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 421215a29..d49c96db0 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 9797249f0..024e2d15b 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 f113596f5..dd644fe84 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 2a2962505..28841c8d2 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -1596,7 +1596,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 4e0055946..cfbcca392 100644 --- a/src/afs/LINUX24/osi_vnodeops.c +++ b/src/afs/LINUX24/osi_vnodeops.c @@ -1431,7 +1431,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 4c172aa87..b4899dcb8 100644 --- a/src/afs/NBSD/osi_vnodeops.c +++ b/src/afs/NBSD/osi_vnodeops.c @@ -1076,7 +1076,7 @@ afs_nbsd_symlink(void *v) name = cnstrdup(cnp); 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); if (code == 0) { code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred); diff --git a/src/afs/OBSD/osi_vnodeops.c b/src/afs/OBSD/osi_vnodeops.c index d3b85fd9b..022504e67 100644 --- a/src/afs/OBSD/osi_vnodeops.c +++ b/src/afs/OBSD/osi_vnodeops.c @@ -845,7 +845,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 9f9915775..55415fff4 100644 --- a/src/afs/SOLARIS/osi_vnodeops.c +++ b/src/afs/SOLARIS/osi_vnodeops.c @@ -1622,7 +1622,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 f6195b9eb..e0ad0bb51 100644 --- a/src/afs/UKERNEL/afs_usrops.c +++ b/src/afs/UKERNEL/afs_usrops.c @@ -3059,7 +3059,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 e4019561f..38904cc67 100644 --- a/src/afs/UKERNEL/sysincludes.h +++ b/src/afs/UKERNEL/sysincludes.h @@ -1252,7 +1252,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 13591ce90..dfb9e4c2c 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 f98aef2ae..ae8a3b122 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -1327,7 +1327,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