All of lore.kernel.org
 help / color / mirror / Atom feed
From: Li Zefan <lizefan@huawei.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [PATCH] idr: fix a subtle bug in idr_get_next()
Date: Mon, 4 Feb 2013 11:39:50 +0800	[thread overview]
Message-ID: <510F2D86.5050408@huawei.com> (raw)
In-Reply-To: <20130202231048.GA3940@mtj.dyndns.org>

On 2013/2/3 7:10, Tejun Heo wrote:
> The iteration logic of idr_get_next() is borrowed mostly verbatim from
> idr_for_each().  It walks down the tree looking for the slot matching
> the current ID.  If the matching slot is not found, the ID is
> incremented by the distance of single slot at the given level and
> repeats.
> 
> The implementation assumes that during the whole iteration id is
> aligned to the layer boundaries of the level closest to the leaf,
> which is true for all iterations starting from zero or an existing
> element and thus is fine for idr_for_each().
> 
> However, idr_get_next() may be given any point and if the starting id
> hits in the middle of a non-existent layer, increment to the next
> layer will end up skipping the same offset into it.  For example, an
> IDR with IDs filled between [64, 127] would look like the following.
> 
>           [  0  64 ... ]
>        /----/   |
>        |        |
>       NULL    [ 64 ... 127 ]
> 
> If idr_get_next() is called with 63 as the starting point, it will try
> to follow down the pointer from 0.  As it is NULL, it will then try to
> proceed to the next slot in the same level by adding the slot distance
> at that level which is 64 - making the next try 127.  It goes around
> the loop and finds and returns 127 skipping [64, 126].
> 
> Note that this bug also triggers in idr_for_each_entry() loop which
> deletes during iteration as deletions can make layers go away leaving
> the iteration with unaligned ID into missing layers.
> 
> Fix it by ensuring proceeding to the next slot doesn't carry over the
> unaligned offset - ie. use round_up(id + 1, slot_distance) instead of
> id += slot_distance.
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>

Don't we need to cc stable?

> Reported-by: David Teigland <teigland@redhat.com>
> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
> ---
>  lib/idr.c |    9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/idr.c b/lib/idr.c
> index 6482390..ca5aa00 100644
> --- a/lib/idr.c
> +++ b/lib/idr.c
> @@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int *nextidp)
>  			return p;
>  		}
>  
> -		id += 1 << n;
> +		/*
> +		 * Proceed to the next layer at the current level.  Unlike
> +		 * idr_for_each(), @id isn't guaranteed to be aligned to
> +		 * layer boundary at this point and adding 1 << n may
> +		 * incorrectly skip IDs.  Make sure we jump to the
> +		 * beginning of the next layer using round_up().
> +		 */
> +		id = round_up(id + 1, 1 << n);
>  		while (n < fls(id)) {
>  			n += IDR_BITS;
>  			p = *--paa;
> --



WARNING: multiple messages have this Message-ID (diff)
From: Li Zefan <lizefan@huawei.com>
To: Tejun Heo <tj@kernel.org>
Cc: David Teigland <teigland@redhat.com>, <akpm@linux-foundation.org>,
	<rusty@rustcorp.com.au>, <linux-kernel@vger.kernel.org>,
	Christine Caulfield <ccaulfie@redhat.com>,
	<cluster-devel@redhat.com>,
	KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Subject: Re: [PATCH] idr: fix a subtle bug in idr_get_next()
Date: Mon, 4 Feb 2013 11:39:50 +0800	[thread overview]
Message-ID: <510F2D86.5050408@huawei.com> (raw)
In-Reply-To: <20130202231048.GA3940@mtj.dyndns.org>

On 2013/2/3 7:10, Tejun Heo wrote:
> The iteration logic of idr_get_next() is borrowed mostly verbatim from
> idr_for_each().  It walks down the tree looking for the slot matching
> the current ID.  If the matching slot is not found, the ID is
> incremented by the distance of single slot at the given level and
> repeats.
> 
> The implementation assumes that during the whole iteration id is
> aligned to the layer boundaries of the level closest to the leaf,
> which is true for all iterations starting from zero or an existing
> element and thus is fine for idr_for_each().
> 
> However, idr_get_next() may be given any point and if the starting id
> hits in the middle of a non-existent layer, increment to the next
> layer will end up skipping the same offset into it.  For example, an
> IDR with IDs filled between [64, 127] would look like the following.
> 
>           [  0  64 ... ]
>        /----/   |
>        |        |
>       NULL    [ 64 ... 127 ]
> 
> If idr_get_next() is called with 63 as the starting point, it will try
> to follow down the pointer from 0.  As it is NULL, it will then try to
> proceed to the next slot in the same level by adding the slot distance
> at that level which is 64 - making the next try 127.  It goes around
> the loop and finds and returns 127 skipping [64, 126].
> 
> Note that this bug also triggers in idr_for_each_entry() loop which
> deletes during iteration as deletions can make layers go away leaving
> the iteration with unaligned ID into missing layers.
> 
> Fix it by ensuring proceeding to the next slot doesn't carry over the
> unaligned offset - ie. use round_up(id + 1, slot_distance) instead of
> id += slot_distance.
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>

Don't we need to cc stable?

> Reported-by: David Teigland <teigland@redhat.com>
> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
> ---
>  lib/idr.c |    9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/idr.c b/lib/idr.c
> index 6482390..ca5aa00 100644
> --- a/lib/idr.c
> +++ b/lib/idr.c
> @@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int *nextidp)
>  			return p;
>  		}
>  
> -		id += 1 << n;
> +		/*
> +		 * Proceed to the next layer at the current level.  Unlike
> +		 * idr_for_each(), @id isn't guaranteed to be aligned to
> +		 * layer boundary at this point and adding 1 << n may
> +		 * incorrectly skip IDs.  Make sure we jump to the
> +		 * beginning of the next layer using round_up().
> +		 */
> +		id = round_up(id + 1, 1 << n);
>  		while (n < fls(id)) {
>  			n += IDR_BITS;
>  			p = *--paa;
> --


  parent reply	other threads:[~2013-02-04  3:39 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-26  1:30 [PATCHSET] idr: deprecate idr_remove_all() Tejun Heo
2013-01-26  1:30 ` [PATCH 01/14] idr: make idr_destroy() imply idr_remove_all() Tejun Heo
2013-01-26  1:31 ` [PATCH 02/14] atm/nicstar: don't use idr_remove_all() Tejun Heo
2013-01-27  6:43   ` David Miller
2013-02-04 17:52   ` [PATCH v2 " Tejun Heo
2013-02-04 18:10     ` chas williams - CONTRACTOR
2013-02-04 18:35       ` Tejun Heo
2013-01-26  1:31 ` [PATCH 03/14] block/loop: " Tejun Heo
2013-01-26  1:31 ` [PATCH 04/14] firewire: " Tejun Heo
2013-01-26  9:07   ` Stefan Richter
2013-01-26  1:31 ` [PATCH 05/14] drm: " Tejun Heo
2013-01-26  1:31   ` Tejun Heo
2013-01-26  1:31 ` [PATCH 06/14] dm: " Tejun Heo
2013-01-26  1:31 ` [PATCH 07/14] remoteproc: " Tejun Heo
2013-01-26  1:31 ` [PATCH 08/14] rpmsg: " Tejun Heo
2013-01-26  1:31 ` [Cluster-devel] [PATCH 09/14] dlm: use idr_for_each_entry() in recover_idr_clear() error path Tejun Heo
2013-01-26  1:31   ` Tejun Heo
2013-01-28 15:55   ` [Cluster-devel] " David Teigland
2013-01-28 15:55     ` David Teigland
2013-01-26  1:31 ` [Cluster-devel] [PATCH 10/14] dlm: don't use idr_remove_all() Tejun Heo
2013-01-26  1:31   ` Tejun Heo
2013-01-28 15:57   ` [Cluster-devel] " David Teigland
2013-01-28 15:57     ` David Teigland
2013-01-29 15:13     ` [Cluster-devel] " David Teigland
2013-01-29 15:13       ` David Teigland
2013-01-30 21:24       ` [Cluster-devel] " David Teigland
2013-01-30 21:24         ` David Teigland
2013-01-31 23:53         ` [Cluster-devel] " Tejun Heo
2013-01-31 23:53           ` Tejun Heo
2013-02-01  0:18           ` [Cluster-devel] " Tejun Heo
2013-02-01  0:18             ` Tejun Heo
2013-02-01 17:44             ` [Cluster-devel] " David Teigland
2013-02-01 17:44               ` David Teigland
2013-02-01 18:00               ` [Cluster-devel] " Tejun Heo
2013-02-01 18:00                 ` Tejun Heo
2013-02-02 23:10                 ` [Cluster-devel] [PATCH] idr: fix a subtle bug in idr_get_next() Tejun Heo
2013-02-02 23:10                   ` Tejun Heo
2013-02-02 23:11                   ` [Cluster-devel] " Tejun Heo
2013-02-02 23:11                     ` Tejun Heo
2013-02-03  2:15                     ` [Cluster-devel] " Randy Dunlap
2013-02-03  2:15                       ` Randy Dunlap
2013-02-03 17:53                       ` [Cluster-devel] " Hugh Dickins
2013-02-03 17:53                         ` Hugh Dickins
2013-02-05 15:36                     ` [Cluster-devel] " David Teigland
2013-02-05 15:36                       ` David Teigland
2013-02-04  3:39                   ` Li Zefan [this message]
2013-02-04  3:39                     ` Li Zefan
2013-02-04 17:44                     ` [Cluster-devel] " Tejun Heo
2013-02-04 17:44                       ` Tejun Heo
2013-01-26  1:31 ` [PATCH 11/14] nfs: idr_destroy() no longer needs idr_remove_all() Tejun Heo
2013-01-29 22:58   ` J. Bruce Fields
2013-01-30  2:18     ` Myklebust, Trond
2013-02-01  0:08       ` Tejun Heo
2013-01-26  1:31 ` [PATCH 12/14] inotify: don't use idr_remove_all() Tejun Heo
     [not found] ` <1359163872-1949-1-git-send-email-tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-01-26  1:31   ` [PATCH 13/14] cgroup: " Tejun Heo
2013-01-26  1:31     ` Tejun Heo
2013-01-26  1:31 ` [PATCH 14/14] idr: deprecate idr_remove_all() Tejun Heo
2013-01-26 13:48   ` Arnd Bergmann
2013-01-26 14:24     ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=510F2D86.5050408@huawei.com \
    --to=lizefan@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.