# HG changeset patch # User Marcel Telka # Date 1363298284 14400 # Node ID ad441dd344785d961b97a791d2432d6732f8fa96 # Parent dc0c7baefe32bc9e5c3bc8cbf82361e265b36a16 Back out hg changeset 829c00a55a37, bug 2986 -- introduces vulnerability Reviewed by: Richard Lowe Reviewed by: Christopher Siden Approved by: Dan McDonald diff -r dc0c7baefe32 -r ad441dd34478 usr/src/uts/common/fs/nfs/nfs3_srv.c --- a/usr/src/uts/common/fs/nfs/nfs3_srv.c Tue Mar 12 19:31:47 2013 -0400 +++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c Thu Mar 14 17:58:04 2013 -0400 @@ -433,25 +433,16 @@ goto out1; } - exi_hold(exi); - /* * If the public filehandle is used then allow * a multi-component lookup */ if (PUBLIC_FH3(&args->what.dir)) { - struct exportinfo *new; - publicfh_flag = TRUE; - error = rfs_publicfh_mclookup(name, dvp, cr, &vp, - &new, &sec); - - if (error == 0) { - exi_rele(exi); - exi = new; - } - + &exi, &sec); + if (error && exi != NULL) + exi_rele(exi); /* See comment below Re: publicfh_flag */ /* * Since WebNFS may bypass MOUNT, we need to ensure this * request didn't come from an unlabeled admin_low client. @@ -473,6 +464,8 @@ if (tp == NULL || tp->tpc_tp.tp_doi != l_admin_low->tsl_doi || tp->tpc_tp.host_type != SUN_CIPSO) { + if (exi != NULL) + exi_rele(exi); VN_RELE(vp); resp->status = NFS3ERR_ACCES; error = 1; @@ -498,6 +491,8 @@ if (!blequal(&l_admin_low->tsl_label, clabel)) { if (!do_rfs_label_check(clabel, dvp, DOMINANCE_CHECK, exi)) { + if (publicfh_flag && exi != NULL) + exi_rele(exi); VN_RELE(vp); resp->status = NFS3ERR_ACCES; error = 1; @@ -524,10 +519,18 @@ goto out; } + /* + * If publicfh_flag is true then we have called rfs_publicfh_mclookup + * and have obtained a new exportinfo in exi which needs to be + * released. Note the the original exportinfo pointed to by exi + * will be released by the caller, common_dispatch. + */ + if (publicfh_flag) + exi_rele(exi); + va.va_mask = AT_ALL; vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va; - exi_rele(exi); VN_RELE(vp); resp->status = NFS3_OK; @@ -549,12 +552,6 @@ return; out: - /* - * The passed argument exportinfo is released by the - * caller, common_dispatch - */ - exi_rele(exi); - if (curthread->t_flag & T_WOULDBLOCK) { curthread->t_flag &= ~T_WOULDBLOCK; resp->status = NFS3ERR_JUKEBOX; diff -r dc0c7baefe32 -r ad441dd34478 usr/src/uts/common/fs/nfs/nfs_server.c --- a/usr/src/uts/common/fs/nfs/nfs_server.c Tue Mar 12 19:31:47 2013 -0400 +++ b/usr/src/uts/common/fs/nfs/nfs_server.c Thu Mar 14 17:58:04 2013 -0400 @@ -21,7 +21,6 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Bayard G. Bell. All rights reserved. - * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -2801,8 +2800,8 @@ */ /* Release the reference on the old exi value */ + ASSERT(*exi != NULL); exi_rele(*exi); - *exi = NULL; if (error = nfs_check_vpexi(mc_dvp, *vpp, kcred, exi)) { VN_RELE(*vpp); @@ -2815,9 +2814,6 @@ if (mc_dvp) VN_RELE(mc_dvp); - if (error && *exi != NULL) - exi_rele(*exi); - return (error); } @@ -2963,19 +2959,16 @@ /* * Get the export information for the lookup vnode, and verify its * useable. - * - * Set @exip only in success */ int nfs_check_vpexi(vnode_t *mc_dvp, vnode_t *vp, cred_t *cr, - struct exportinfo **exip) + struct exportinfo **exi) { int walk; int error = 0; - struct exportinfo *exi; - - exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE); - if (exi == NULL) + + *exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE); + if (*exi == NULL) error = EACCES; else { /* @@ -2984,13 +2977,10 @@ * must not terminate below the * exported directory. */ - if (exi->exi_export.ex_flags & EX_NOSUB && walk > 0) { + if ((*exi)->exi_export.ex_flags & EX_NOSUB && walk > 0) error = EACCES; - exi_rele(exi); - } } - if (error == 0) - *exip = exi; + return (error); } diff -r dc0c7baefe32 -r ad441dd34478 usr/src/uts/common/fs/nfs/nfs_srv.c --- a/usr/src/uts/common/fs/nfs/nfs_srv.c Tue Mar 12 19:31:47 2013 -0400 +++ b/usr/src/uts/common/fs/nfs/nfs_srv.c Thu Mar 14 17:58:04 2013 -0400 @@ -20,7 +20,6 @@ */ /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -400,8 +399,6 @@ return; } - exi_hold(exi); - /* * If the public filehandle is used then allow * a multi-component lookup, i.e. evaluate @@ -412,16 +409,9 @@ * which is OK as long as the filesystem is exported. */ if (PUBLIC_FH2(fhp)) { - struct exportinfo *new; - publicfh_flag = TRUE; - error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &new, + error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &exi, &sec); - - if (error == 0) { - exi_rele(exi); - exi = new; - } } else { /* * Do a normal single component lookup. @@ -462,10 +452,13 @@ VN_RELE(dvp); /* - * The passed argument exportinfo is released by the - * caller, comon_dispatch + * If publicfh_flag is true then we have called rfs_publicfh_mclookup + * and have obtained a new exportinfo in exi which needs to be + * released. Note the the original exportinfo pointed to by exi + * will be released by the caller, comon_dispatch. */ - exi_rele(exi); + if (publicfh_flag && exi != NULL) + exi_rele(exi); /* * If it's public fh, no 0x81, and client's flavor is