Mercurial > illumos > illumos-gate
changeset 9871:6f02df7ca581
6746299 assertion !vn_ismntpt(vp) fail in snv_98
6833224 TX NFS client file access returns EACCES randomly for non-ADMIN_LOW labeled resources
author | Jarrett Lu <Jarrett.Lu@Sun.COM> |
---|---|
date | Mon, 15 Jun 2009 15:18:04 -0700 |
parents | b2e907fa2ec2 |
children | bb47b7225612 |
files | usr/src/uts/common/fs/nfs/nfs3_srv.c usr/src/uts/common/fs/nfs/nfs4_srv.c usr/src/uts/common/fs/nfs/nfs_server.c usr/src/uts/common/fs/nfs/nfs_subr.c usr/src/uts/common/nfs/nfs.h usr/src/uts/common/os/tlabel.c usr/src/uts/common/sys/tsol/label.h |
diffstat | 7 files changed, 145 insertions(+), 128 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fs/nfs/nfs3_srv.c Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c Mon Jun 15 15:18:04 2009 -0700 @@ -187,7 +187,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -508,7 +509,7 @@ if (!blequal(&l_admin_low->tsl_label, clabel)) { if (!do_rfs_label_check(clabel, dvp, - DOMINANCE_CHECK)) { + DOMINANCE_CHECK, exi)) { if (publicfh_flag && exi != NULL) exi_rele(exi); VN_RELE(vp); @@ -674,9 +675,9 @@ if (!blequal(&l_admin_low->tsl_label, clabel)) { if ((equal_label = do_rfs_label_check(clabel, vp, - EQUALITY_CHECK)) == B_FALSE) { + EQUALITY_CHECK, exi)) == B_FALSE) { dominant_label = do_rfs_label_check(clabel, - vp, DOMINANCE_CHECK); + vp, DOMINANCE_CHECK, exi); } else dominant_label = B_TRUE; admin_low_client = B_FALSE; @@ -834,7 +835,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -980,7 +982,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -1282,7 +1285,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto err1; } @@ -1572,7 +1576,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -1957,7 +1962,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -2137,7 +2143,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto err1; } @@ -2344,7 +2351,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -2572,7 +2580,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto err1; } @@ -2731,7 +2740,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto err1; } @@ -2854,7 +2864,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto err1; } @@ -2927,7 +2938,8 @@ if (is_system_labeled()) { if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto err1; } @@ -3131,7 +3143,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -3180,7 +3193,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -3332,7 +3346,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -3619,7 +3634,8 @@ struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -3990,7 +4006,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -4060,7 +4077,6 @@ return (&args->fsroot); } -/* ARGSUSED */ void rfs3_fsinfo(FSINFO3args *args, FSINFO3res *resp, struct exportinfo *exi, struct svc_req *req, cred_t *cr) @@ -4095,7 +4111,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_STALE; vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes); @@ -4194,7 +4211,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; } @@ -4329,7 +4347,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, + exi)) { resp->status = NFS3ERR_ACCES; goto out1; }
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c Mon Jun 15 15:18:04 2009 -0700 @@ -1301,7 +1301,7 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if ((tslabel = nfs_getflabel(vp)) == NULL) { + if ((tslabel = nfs_getflabel(vp, cs->exi)) == NULL) { *cs->statusp = resp->status = puterrno4(EACCES); goto out; } @@ -2774,7 +2774,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + cs->exi)) { error = EACCES; goto err_out; } @@ -3353,23 +3354,6 @@ goto out; } - if (is_system_labeled()) { - bslabel_t *clabel; - - ASSERT(req->rq_label != NULL); - clabel = req->rq_label; - DTRACE_PROBE2(tx__rfs4__log__info__opputpubfh__clabel, char *, - "got client label from request(1)", - struct svc_req *, req); - if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK)) { - *cs->statusp = resp->status = - NFS4ERR_SERVERFAULT; - return; - } - } - } - error = makefh4(&cs->fh, vp, exi_public); if (error != 0) { *cs->statusp = resp->status = puterrno4(error); @@ -3399,6 +3383,24 @@ cs->exi = exi_public; } + if (is_system_labeled()) { + bslabel_t *clabel; + + ASSERT(req->rq_label != NULL); + clabel = req->rq_label; + DTRACE_PROBE2(tx__rfs4__log__info__opputpubfh__clabel, char *, + "got client label from request(1)", + struct svc_req *, req); + if (!blequal(&l_admin_low->tsl_label, clabel)) { + if (!do_rfs_label_check(clabel, vp, DOMINANCE_CHECK, + cs->exi)) { + *cs->statusp = resp->status = + NFS4ERR_SERVERFAULT; + goto out; + } + } + } + VN_HOLD(vp); cs->vp = vp; @@ -4109,7 +4111,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK, + cs->exi)) { *cs->statusp = resp->status = NFS4ERR_ACCESS; if (name != nm) kmem_free(name, MAXPATHLEN + 1); @@ -4416,7 +4419,7 @@ struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { if (!do_rfs_label_check(clabel, ndvp, - EQUALITY_CHECK)) { + EQUALITY_CHECK, cs->exi)) { *cs->statusp = resp->status = NFS4ERR_ACCESS; goto err_out; } @@ -5304,7 +5307,7 @@ struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { if (!do_rfs_label_check(clabel, cs->vp, - EQUALITY_CHECK)) { + EQUALITY_CHECK, cs->exi)) { *cs->statusp = resp->status = NFS4ERR_ACCESS; goto out; } @@ -6229,7 +6232,8 @@ "got client label from request(1)", struct svc_req *, req); if (!blequal(&l_admin_low->tsl_label, clabel)) { - if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) { + if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK, + cs->exi)) { return (NFS4ERR_ACCESS); } }
--- a/usr/src/uts/common/fs/nfs/nfs_server.c Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/fs/nfs/nfs_server.c Mon Jun 15 15:18:04 2009 -0700 @@ -87,6 +87,8 @@ #include <sys/cladm.h> #include <sys/clconf.h> +#include <sys/tsol/label.h> + #define MAXHOST 32 const char *kinet_ntop6(uchar_t *, char *, size_t); @@ -3118,3 +3120,73 @@ if (rfs4_dss_numnewpaths > 0) kmem_free(added_paths, rfs4_dss_numnewpaths * sizeof (char *)); } + +/* + * Used by NFSv3 and NFSv4 server to query label of + * a pathname component during lookup/access ops. + */ +ts_label_t * +nfs_getflabel(vnode_t *vp, struct exportinfo *exi) +{ + zone_t *zone; + ts_label_t *zone_label; + char *path; + + mutex_enter(&vp->v_lock); + if (vp->v_path != NULL) { + zone = zone_find_by_any_path(vp->v_path, B_FALSE); + mutex_exit(&vp->v_lock); + } else { + /* + * v_path not cached. Fall back on pathname of exported + * file system as we rely on pathname from which we can + * derive a label. The exported file system portion of + * path is sufficient to obtain a label. + */ + path = exi->exi_export.ex_path; + if (path == NULL) { + mutex_exit(&vp->v_lock); + return (NULL); + } + zone = zone_find_by_any_path(path, B_FALSE); + mutex_exit(&vp->v_lock); + } + /* + * Caller has verified that the file is either + * exported or visible. So if the path falls in + * global zone, admin_low is returned; otherwise + * the zone's label is returned. + */ + zone_label = zone->zone_slabel; + label_hold(zone_label); + zone_rele(zone); + return (zone_label); +} + +/* + * TX NFS routine used by NFSv3 and NFSv4 to do label check + * on client label and server's file object lable. + */ +boolean_t +do_rfs_label_check(bslabel_t *clabel, vnode_t *vp, int flag, + struct exportinfo *exi) +{ + bslabel_t *slabel; + ts_label_t *tslabel; + boolean_t result; + + if ((tslabel = nfs_getflabel(vp, exi)) == NULL) { + return (B_FALSE); + } + slabel = label2bslabel(tslabel); + DTRACE_PROBE4(tx__rfs__log__info__labelcheck, char *, + "comparing server's file label(1) with client label(2) (vp(3))", + bslabel_t *, slabel, bslabel_t *, clabel, vnode_t *, vp); + + if (flag == EQUALITY_CHECK) + result = blequal(clabel, slabel); + else + result = bldominates(clabel, slabel); + label_rele(tslabel); + return (result); +}
--- a/usr/src/uts/common/fs/nfs/nfs_subr.c Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/fs/nfs/nfs_subr.c Mon Jun 15 15:18:04 2009 -0700 @@ -5125,33 +5125,6 @@ } /* - * TX NFS routine used by NFSv3 and NFSv4 to do label check - * on client label and server's file object lable. - */ -boolean_t -do_rfs_label_check(bslabel_t *clabel, vnode_t *vp, int flag) -{ - bslabel_t *slabel; - ts_label_t *tslabel; - boolean_t result; - - if ((tslabel = nfs_getflabel(vp)) == NULL) { - return (B_FALSE); - } - slabel = label2bslabel(tslabel); - DTRACE_PROBE4(tx__rfs__log__info__labelcheck, char *, - "comparing server's file label(1) with client label(2) (vp(3))", - bslabel_t *, slabel, bslabel_t *, clabel, vnode_t *, vp); - - if (flag == EQUALITY_CHECK) - result = blequal(clabel, slabel); - else - result = bldominates(clabel, slabel); - label_rele(tslabel); - return (result); -} - -/* * See if xattr directory to see if it has any generic user attributes */ int
--- a/usr/src/uts/common/nfs/nfs.h Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/nfs/nfs.h Mon Jun 15 15:18:04 2009 -0700 @@ -2318,6 +2318,9 @@ extern int do_xattr_exists_check(vnode_t *, ulong_t *, cred_t *); +extern ts_label_t *nfs_getflabel(vnode_t *, struct exportinfo *); +extern boolean_t do_rfs_label_check(bslabel_t *, vnode_t *, int, + struct exportinfo *); #endif /* _KERNEL */ #ifdef __cplusplus
--- a/usr/src/uts/common/os/tlabel.c Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/os/tlabel.c Mon Jun 15 15:18:04 2009 -0700 @@ -44,7 +44,6 @@ #include <nfs/nfs.h> #include <nfs/nfs4.h> #include <nfs/nfs_clnt.h> -#include <sys/dnlc.h> int sys_labeling = 0; /* the default is "off" */ @@ -540,54 +539,3 @@ else return (0); } - -/* - * Used by NFSv3 and NFSv4 server to query label of - * a pathname component during lookup/access ops. - */ -ts_label_t * -nfs_getflabel(vnode_t *vp) -{ - zone_t *zone; - ts_label_t *zone_label; - char path[MAXNAMELEN]; - vnode_t *pvp, *tvp; - - mutex_enter(&vp->v_lock); - /* - * mount traverse has been done by caller - * before calling this routine. - */ - ASSERT(!vn_ismntpt(vp)); - if (vp->v_path != NULL) { - zone = zone_find_by_any_path(vp->v_path, B_FALSE); - mutex_exit(&vp->v_lock); - } else { - /* - * v_path not cached. Since we rely on path - * of an obj to get its label, we need to get - * path corresponding to the parent vnode. - */ - tvp = vp; - do { - mutex_exit(&tvp->v_lock); - if ((pvp = dnlc_reverse_lookup(tvp, path, - sizeof (path))) == NULL) - return (NULL); - mutex_enter(&pvp->v_lock); - tvp = pvp; - } while (pvp->v_path == NULL); - zone = zone_find_by_any_path(pvp->v_path, B_FALSE); - mutex_exit(&pvp->v_lock); - } - /* - * Caller has verified that the file is either - * exported or visible. So if the path falls in - * global zone, admin_low is returned; otherwise - * the zone's label is returned. - */ - zone_label = zone->zone_slabel; - label_hold(zone_label); - zone_rele(zone); - return (zone_label); -}
--- a/usr/src/uts/common/sys/tsol/label.h Mon Jun 15 13:26:03 2009 -0700 +++ b/usr/src/uts/common/sys/tsol/label.h Mon Jun 15 15:18:04 2009 -0700 @@ -130,8 +130,6 @@ extern int fgetlabel(int, m_label_t *); extern int _blinrange(const m_label_t *, const brange_t *); extern int blinlset(const m_label_t *, const blset_t); -extern ts_label_t *nfs_getflabel(vnode_t *); -extern boolean_t do_rfs_label_check(bslabel_t *, vnode_t *, int); /* * The use of '!!' here prevents users from referencing this function-like