summaryrefslogtreecommitdiffstats
path: root/xlators
diff options
context:
space:
mode:
authorShreyas Siravara <sshreyas@fb.com>2017-12-07 08:00:16 -0800
committerJeff Darcy <jeff@pl.atyp.us>2017-12-08 22:33:20 +0000
commit1926cada4a7acf48aa7cbf5ef8bb8942ae10b522 (patch)
tree060a48ca983a9cb6052865cf2d44ae01d8ae26a9 /xlators
parent742a4eed244833761697646044f20675d1411292 (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.c8
-rw-r--r--xlators/nfs/server/src/exports.c45
-rw-r--r--xlators/nfs/server/src/exports.h1
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 {