Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933100Ab3FEVuq (ORCPT ); Wed, 5 Jun 2013 17:50:46 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:37944 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932559Ab3FEVfw (ORCPT ); Wed, 5 Jun 2013 17:35:52 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Tejun Heo , Michal Hocko Subject: [ 081/127] cgroup: fix a subtle bug in descendant pre-order walk Date: Wed, 5 Jun 2013 14:34:08 -0700 Message-Id: <20130605213227.149125525@linuxfoundation.org> X-Mailer: git-send-email 1.8.3.rc0.20.gb99dd2e In-Reply-To: <20130605213217.966891866@linuxfoundation.org> References: <20130605213217.966891866@linuxfoundation.org> User-Agent: quilt/0.60-5.1.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2763 Lines: 82 3.9-stable review patch. If anyone has any objections, please let me know. ------------------ From: Tejun Heo commit 7805d000db30a3787a4c969bab6ae4d8a5fd8ce6 upstream. When cgroup_next_descendant_pre() initiates a walk, it checks whether the subtree root doesn't have any children and if not returns NULL. Later code assumes that the subtree isn't empty. This is broken because the subtree may become empty inbetween, which can lead to the traversal escaping the subtree by walking to the sibling of the subtree root. There's no reason to have the early exit path. Remove it along with the later assumption that the subtree isn't empty. This simplifies the code a bit and fixes the subtle bug. While at it, fix the comment of cgroup_for_each_descendant_pre() which was incorrectly referring to ->css_offline() instead of ->css_online(). Signed-off-by: Tejun Heo Reviewed-by: Michal Hocko Signed-off-by: Greg Kroah-Hartman --- include/linux/cgroup.h | 2 +- kernel/cgroup.c | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -570,7 +570,7 @@ struct cgroup *cgroup_rightmost_descenda * * If a subsystem synchronizes against the parent in its ->css_online() and * before starting iterating, and synchronizes against @pos on each - * iteration, any descendant cgroup which finished ->css_offline() is + * iteration, any descendant cgroup which finished ->css_online() is * guaranteed to be visible in the future iterations. * * In other words, the following guarantees that a descendant can't escape --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -3000,11 +3000,8 @@ struct cgroup *cgroup_next_descendant_pr WARN_ON_ONCE(!rcu_read_lock_held()); /* if first iteration, pretend we just visited @cgroup */ - if (!pos) { - if (list_empty(&cgroup->children)) - return NULL; + if (!pos) pos = cgroup; - } /* visit the first child if exists */ next = list_first_or_null_rcu(&pos->children, struct cgroup, sibling); @@ -3012,14 +3009,14 @@ struct cgroup *cgroup_next_descendant_pr return next; /* no child, visit my or the closest ancestor's next sibling */ - do { + while (pos != cgroup) { next = list_entry_rcu(pos->sibling.next, struct cgroup, sibling); if (&next->sibling != &pos->parent->children) return next; pos = pos->parent; - } while (pos != cgroup); + } return NULL; } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/