diff options
author | Shreyas Siravara <sshreyas@fb.com> | 2017-12-07 08:00:16 -0800 |
---|---|---|
committer | Jeff Darcy <jeff@pl.atyp.us> | 2017-12-08 22:33:20 +0000 |
commit | 1926cada4a7acf48aa7cbf5ef8bb8942ae10b522 (patch) | |
tree | 060a48ca983a9cb6052865cf2d44ae01d8ae26a9 /xlators | |
parent | 742a4eed244833761697646044f20675d1411292 (diff) |
nfs: Reference count export items
Export items are used in the auth cache and need to be reference
counted to avoid use-after free bugs.
Change-Id: I5cdcdc1cc6abad26c7077d66a14f263da07678ac
BUG: 1522847
Signed-off-by: Shreyas Siravara <sshreyas@fb.com>
Diffstat (limited to 'xlators')
-rw-r--r-- | xlators/nfs/server/src/auth-cache.c | 8 | ||||
-rw-r--r-- | xlators/nfs/server/src/exports.c | 45 | ||||
-rw-r--r-- | xlators/nfs/server/src/exports.h | 1 |
3 files changed, 32 insertions, 22 deletions
diff --git a/xlators/nfs/server/src/auth-cache.c b/xlators/nfs/server/src/auth-cache.c index 2b37a7f06bd..a1aacaba61a 100644 --- a/xlators/nfs/server/src/auth-cache.c +++ b/xlators/nfs/server/src/auth-cache.c @@ -232,6 +232,8 @@ auth_cache_get (struct auth_cache *cache, char *hashkey, if (_auth_cache_expired (cache, lookup_res)) { ret = ENTRY_EXPIRED; + GF_REF_PUT (lookup_res->item); + lookup_res->item = NULL; /* free entry and remove from the cache */ GF_FREE (lookup_res); @@ -473,7 +475,11 @@ cache_nfs_fh (struct auth_cache *cache, struct nfs3_fh *fh, } entry->timestamp = time (NULL); - entry->item = export_item; + /* Update entry->item if it is pointing to a different export_item */ + if (entry->item && entry->item != export_item) { + GF_REF_PUT (entry->item); + } + entry->item = GF_REF_GET (export_item); ret = auth_cache_add (cache, hashkey, entry); GF_REF_PUT (entry); diff --git a/xlators/nfs/server/src/exports.c b/xlators/nfs/server/src/exports.c index 83aec254040..75780587147 100644 --- a/xlators/nfs/server/src/exports.c +++ b/xlators/nfs/server/src/exports.c @@ -227,6 +227,24 @@ out: } /** + * _export_item_deinit -- Free memory used by an export item + * + * @expdir : Pointer to the export item to free + * + * Not for external use. + */ +static void +_export_item_deinit (struct export_item *item) +{ + if (!item) + return; + + _export_options_deinit (item->opts); + GF_FREE (item->name); + GF_FREE (item); +} + +/** * _export_item_init -- Initialize an export item structure * * @return : success: Pointer to an allocated exports item struct @@ -240,32 +258,17 @@ _export_item_init () struct export_item *item = GF_CALLOC (1, sizeof (*item), gf_common_mt_nfs_exports); - if (!item) + if (item) { + GF_REF_INIT(item, _export_item_deinit); + } else { gf_msg (GF_EXP, GF_LOG_CRITICAL, ENOMEM, NFS_MSG_NO_MEMORY, "Failed to allocate export item!"); + } return item; } /** - * _export_item_deinit -- Free memory used by an export item - * - * @expdir : Pointer to the export item to free - * - * Not for external use. - */ -static void -_export_item_deinit (struct export_item *item) -{ - if (!item) - return; - - _export_options_deinit (item->opts); - GF_FREE (item->name); - GF_FREE (item); -} - -/** * _export_host_init -- Initialize an export options struct * * @return : success: Pointer to an allocated options struct @@ -355,7 +358,7 @@ static int __exp_dict_free_walk (dict_t *dict, char *key, data_t *val, void *tmp) { if (val) { - _export_item_deinit ((struct export_item *)val->data); + GF_REF_PUT ((struct export_item *)val->data); val->data = NULL; dict_del (dict, key); } @@ -768,7 +771,7 @@ __exp_line_ng_host_str_parse (char *str, struct export_item **exp_item) ret = __exp_line_opt_parse (optstr, &exp_opts); if (ret != 0) { /* Bubble up the error to the caller */ - _export_item_deinit (item); + GF_REF_PUT (item); goto out; } diff --git a/xlators/nfs/server/src/exports.h b/xlators/nfs/server/src/exports.h index 0079b9a3deb..87795dadaee 100644 --- a/xlators/nfs/server/src/exports.h +++ b/xlators/nfs/server/src/exports.h @@ -55,6 +55,7 @@ struct export_options { struct export_item { char *name; /* Name of the export item */ struct export_options *opts; /* NFS Options */ + GF_REF_DECL; }; struct export_dir { |