diff options
author | Kotresh H R <khiremat@redhat.com> | 2014-03-25 11:11:41 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-04-03 09:36:42 -0700 |
commit | 997c89b6172116557f981510a94232486ec526b0 (patch) | |
tree | 000b97e39070143153909de6936c1afa3e6fee13 | |
parent | 5dedef81b6ef91d462ce49ded4e148dfc17deee2 (diff) |
features/gfid-access: Fix possible inode memory corruption.
During lookup, the inode is not ref'd. Added code
to ref the inode in call path and unref in cbk path.
Also fixed a case where we should always be putting
linked inode into context as it is not guaranteed
that we get same inode that we passed in a call to
inode_link.
Change-Id: Iaec083a9258658bef3047e83956729d3dbcd9a59
BUG: 1080295
Signed-off-by: Kotresh H R <khiremat@redhat.com>
Reviewed-on: http://review.gluster.org/7329
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Raghavendra G <rgowdapp@redhat.com>
Reviewed-by: Venky Shankar <vshankar@redhat.com>
-rw-r--r-- | xlators/features/gfid-access/src/gfid-access.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/xlators/features/gfid-access/src/gfid-access.c b/xlators/features/gfid-access/src/gfid-access.c index 8e614397c13..5cb6ecfbd4a 100644 --- a/xlators/features/gfid-access/src/gfid-access.c +++ b/xlators/features/gfid-access/src/gfid-access.c @@ -593,18 +593,19 @@ ga_virtual_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret, int32_t op_errno, inode_t *inode, struct iatt *buf, dict_t *xdata, struct iatt *postparent) { - int j = 0; - int i = 0; - int ret = 0; - uint64_t temp_ino = 0; - inode_t *cbk_inode = NULL; - inode_t *true_inode = NULL; - uuid_t random_gfid = {0,}; + int j = 0; + int i = 0; + int ret = 0; + uint64_t temp_ino = 0; + inode_t *cbk_inode = NULL; + inode_t *true_inode = NULL; + uuid_t random_gfid = {0,}; + inode_t *linked_inode = NULL; if (frame->local) cbk_inode = frame->local; else - cbk_inode = inode; + cbk_inode = inode_ref (inode); frame->local = NULL; if (op_ret) @@ -619,6 +620,10 @@ ga_virtual_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if its just previously discover()'d inode */ true_inode = inode_find (inode->table, buf->ia_gfid); if (!true_inode) { + /* This unref is for 'inode_ref()' done in beginning. + This is needed as cbk_inode is allocated new inode + whose unref is taken at the end*/ + inode_unref (cbk_inode); cbk_inode = inode_new (inode->table); if (!cbk_inode) { @@ -630,7 +635,8 @@ ga_virtual_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, path is not yet looked up. Use the current inode itself for now */ - inode_link (inode, NULL, NULL, buf); + linked_inode = inode_link (inode, NULL, NULL, buf); + inode = linked_inode; } else { /* 'inode_ref()' has been done in inode_find() */ inode = true_inode; @@ -674,6 +680,10 @@ unwind: STACK_UNWIND_STRICT (lookup, frame, op_ret, op_errno, cbk_inode, buf, xdata, postparent); + /* Also handles inode_unref of frame->local if done in ga_lookup */ + if (cbk_inode) + inode_unref (cbk_inode); + return 0; } @@ -819,6 +829,8 @@ ga_lookup (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) /* time do another lookup and update the context with proper inode */ op_errno = ESTALE; + /* 'inode_ref()' done in inode_find */ + inode_unref (true_inode); goto err; } @@ -833,7 +845,7 @@ discover: /* if revalidate, then we need to have the proper reference */ if (inode) { tmp_loc.inode = inode_ref (inode); - frame->local = loc->inode; + frame->local = inode_ref (loc->inode); } else { tmp_loc.inode = inode_ref (loc->inode); } |