From 34d09417b76eb38a4be52b0c90551239af99a839 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Sun, 20 Oct 2013 17:08:42 +0800 Subject: [PATCH] client: fix invalid iterator dereference in Client::trim_caps() trimming inode drops a reference to the inode's parent, it may cause the inode's parent also be trimmed. If the cap iterator 'p' happens to point to the inode's parent and the inode's parent is trimmed, the cap iterator 'p' become invalid. Fix the issue by delaying removing cap from the seesion cap list. (similar to what the kclient does) Fixes #6599 Signed-off-by: Yan, Zheng --- src/client/Client.cc | 19 +++++++++++++++---- src/client/MetaSession.h | 4 +++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 20651892c0c4..89de94ee6ea5 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -2921,8 +2921,6 @@ void Client::remove_cap(Cap *cap) i.seq = cap->issue_seq; i.migrate_seq = cap->mseq; session->release->caps.push_back(i); - - cap->cap_item.remove_myself(); if (in->auth_cap == cap) { if (in->flushing_cap_item.is_on_list()) { @@ -2933,7 +2931,13 @@ void Client::remove_cap(Cap *cap) } assert(in->caps.count(mds)); in->caps.erase(mds); - delete cap; + + if (cap == session->s_cap_iterator) { + cap->inode = NULL; + } else { + cap->cap_item.remove_myself(); + delete cap; + } if (!in->is_any_caps()) { ldout(cct, 15) << "remove_cap last one, closing snaprealm " << in->snaprealm << dendl; @@ -2966,7 +2970,7 @@ void Client::trim_caps(MetaSession *s, int max) xlist::iterator p = s->caps.begin(); while (s->caps.size() > max && !p.end()) { Cap *cap = *p; - ++p; + s->s_cap_iterator = cap; Inode *in = cap->inode; if (in->caps.size() > 1 && cap != in->auth_cap) { // disposable non-auth cap @@ -2992,7 +2996,14 @@ void Client::trim_caps(MetaSession *s, int max) if (all) trimmed++; } + + ++p; + if (!cap->inode) { + cap->cap_item.remove_myself(); + delete cap; + } } + s->s_cap_iterator = NULL; } void Client::mark_caps_dirty(Inode *in, int caps) diff --git a/src/client/MetaSession.h b/src/client/MetaSession.h index a6cf634c9690..d9fcbb881d92 100644 --- a/src/client/MetaSession.h +++ b/src/client/MetaSession.h @@ -43,12 +43,14 @@ struct MetaSession { xlist requests; xlist unsafe_requests; + Cap *s_cap_iterator; + MClientCapRelease *release; MetaSession() : mds_num(-1), con(NULL), seq(0), cap_gen(0), cap_renew_seq(0), num_caps(0), - state(STATE_NEW), + state(STATE_NEW), s_cap_iterator(NULL), release(NULL) {} ~MetaSession(); -- 2.47.3