# HG changeset patch # User Vitaliy Gusev # Date 1345640611 0 # Node ID 829c00a55a37ed691a26ca0bbf637f6b53a96ee0 # Parent 57f9d55c2a3146260b9e4cfd24903b43590bee19 2986 nfs: exi refcounter leak at rfs3_lookup Reviewed by: Albert Lee Reviewed by: Gordon Ross Approved by: Albert Lee diff -r 57f9d55c2a31 -r 829c00a55a37 usr/src/uts/common/fs/nfs/nfs3_srv.c --- a/usr/src/uts/common/fs/nfs/nfs3_srv.c Wed Sep 12 04:54:49 2012 +0000 +++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c Wed Aug 22 13:03:31 2012 +0000 @@ -433,16 +433,25 @@ 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, - &exi, &sec); - if (error && exi != NULL) - exi_rele(exi); /* See comment below Re: publicfh_flag */ + &new, &sec); + + if (error == 0) { + exi_rele(exi); + exi = new; + } + /* * Since WebNFS may bypass MOUNT, we need to ensure this * request didn't come from an unlabeled admin_low client. @@ -464,8 +473,6 @@ 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; @@ -491,8 +498,6 @@ 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; @@ -519,18 +524,10 @@ 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; @@ -552,6 +549,12 @@ 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 57f9d55c2a31 -r 829c00a55a37 usr/src/uts/common/fs/nfs/nfs_server.c --- a/usr/src/uts/common/fs/nfs/nfs_server.c Wed Sep 12 04:54:49 2012 +0000 +++ b/usr/src/uts/common/fs/nfs/nfs_server.c Wed Aug 22 13:03:31 2012 +0000 @@ -21,6 +21,7 @@ /* * 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. */ /* @@ -2800,8 +2801,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); @@ -2814,6 +2815,9 @@ if (mc_dvp) VN_RELE(mc_dvp); + if (error && *exi != NULL) + exi_rele(*exi); + return (error); } @@ -2959,16 +2963,19 @@ /* * 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 **exi) + struct exportinfo **exip) { int walk; int error = 0; - - *exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE); - if (*exi == NULL) + struct exportinfo *exi; + + exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE); + if (exi == NULL) error = EACCES; else { /* @@ -2977,10 +2984,13 @@ * 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 57f9d55c2a31 -r 829c00a55a37 usr/src/uts/common/fs/nfs/nfs_srv.c --- a/usr/src/uts/common/fs/nfs/nfs_srv.c Wed Sep 12 04:54:49 2012 +0000 +++ b/usr/src/uts/common/fs/nfs/nfs_srv.c Wed Aug 22 13:03:31 2012 +0000 @@ -20,6 +20,7 @@ */ /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 Nexenta Systems, Inc. All rights reserved. */ /* @@ -399,6 +400,8 @@ return; } + exi_hold(exi); + /* * If the public filehandle is used then allow * a multi-component lookup, i.e. evaluate @@ -409,9 +412,16 @@ * 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, &exi, + error = rfs_publicfh_mclookup(name, dvp, cr, &vp, &new, &sec); + + if (error == 0) { + exi_rele(exi); + exi = new; + } } else { /* * Do a normal single component lookup. @@ -452,13 +462,10 @@ VN_RELE(dvp); /* - * 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. + * The passed argument exportinfo is released by the + * caller, comon_dispatch */ - if (publicfh_flag && exi != NULL) - exi_rele(exi); + exi_rele(exi); /* * If it's public fh, no 0x81, and client's flavor is