From 9fa27cbfdd93b24d8e25c28dc673df4ff499736c Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sat, 12 Jul 2014 02:15:14 -0700 Subject: fuse: fuse_readlink_cbk() - linkname NULL termination unnecessary op_ret incremented to compensate for NULL terminating character leads to self referential loop where OSXFUSE which would reply on a same READLINK() over and over again ~~~ [2014-07-12 08:41:29.815473] T [fuse-bridge.c:1372:fuse_readlink_cbk] 0-glusterfs-fuse: 1: /a/b/1 => ../../1 [2014-07-12 08:41:29.815820] T [fuse-bridge.c:1372:fuse_readlink_cbk] 0-glusterfs-fuse: 0: /a/b/1 => ../../1 [2014-07-12 08:41:29.816165] T [fuse-bridge.c:1372:fuse_readlink_cbk] 0-glusterfs-fuse: 1: /a/b/1 => ../../1 ~~~ It happens due to the problem being (op_ret + 1) > strlen(linkname), for some odd reason this isn't an issue on Linux where there are odd safegaurds on these things - Example of following code ~~~ ((char *)linkname)[op_ret] = '\0'; send_fuse_data (this, finh, (void *)linkname, op_ret + 2048); <---- Here! ~~~ This behaves normally with no issue, the reasoning i have is that internally 'readlink()' is verified with strlen() again or perhaps the size is re-adjusted to the strlen() of `linkname` This isn't the case on OSX, one needs to make sure that ~~~ strlen(linkname) == op_ret ~~~ Otherwise you would get READLINK() loops as shown above. This patch fixes the problem. Many thanks to Anand Avati for helping me out on this. Change-Id: Ia35818de78a5e4d89bad03ab06e2c5ed6e6753a4 BUG: 1095525 Signed-off-by: Harshavardhana Reviewed-on: http://review.gluster.org/8336 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/mount/fuse/src/fuse-bridge.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index 473911a2cb0..0aadb649fbd 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -1365,13 +1365,10 @@ fuse_readlink_cbk (call_frame_t *frame, void *cookie, xlator_t *this, uuid_utoa (state->loc.gfid)); if (op_ret > 0) { - ((char *)linkname)[op_ret] = '\0'; - gf_log ("glusterfs-fuse", GF_LOG_TRACE, - "%"PRIu64": %s => %s", frame->root->unique, - state->loc.path, linkname); - - send_fuse_data (this, finh, (void *)linkname, op_ret + 1); + "%"PRIu64": %s => %s (size:%d)", frame->root->unique, + state->loc.path, linkname, op_ret); + send_fuse_data (this, finh, (void *)linkname, op_ret); } else { gf_log ("glusterfs-fuse", GF_LOG_WARNING, "%"PRIu64": %s => -1 (%s)", frame->root->unique, -- cgit