* [PATCH] mm: Fix possible off-by-one in walk_pte_range() @ 2008-04-15 14:00 Johannes Weiner 2008-04-15 15:36 ` Mikael Pettersson 0 siblings, 1 reply; 5+ messages in thread From: Johannes Weiner @ 2008-04-15 14:00 UTC (permalink / raw) To: LKML Cc: Johannes Weiner, Roel Kluin, Andreas Schwab, Matt Mackall, Andrew Morton After the loop in walk_pte_range() pte might point to the first address after the pmd it walks. The pte_unmap() is then applied to something bad. Spotted by Roel Kluin and Andreas Schwab. Signed-off-by: Johannes Weiner <hannes@saeurebad.de> CC: Roel Kluin <12o3l@tiscali.nl> CC: Andreas Schwab <schwab@suse.de> CC: Matt Mackall <mpm@selenic.com> CC: Andrew Morton <akpm@linux-foundation.org> --- A bug is unlikely, though. kunmap_atomic() looks up the kmap entry by map-type instead of the address the pte points. So the worst thing I could find with a quick grep was that a wrong TLB entry is being flushed. Still, the code is wrong :) diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 1cf1417..cf3c004 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -13,7 +13,7 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private); if (err) break; - } while (pte++, addr += PAGE_SIZE, addr != end); + } while (addr += PAGE_SIZE, addr != end && pte++); pte_unmap(pte); return err; ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] mm: Fix possible off-by-one in walk_pte_range() 2008-04-15 14:00 [PATCH] mm: Fix possible off-by-one in walk_pte_range() Johannes Weiner @ 2008-04-15 15:36 ` Mikael Pettersson 2008-04-15 16:16 ` [PATCH v2] " Johannes Weiner 0 siblings, 1 reply; 5+ messages in thread From: Mikael Pettersson @ 2008-04-15 15:36 UTC (permalink / raw) To: Johannes Weiner Cc: LKML, Roel Kluin, Andreas Schwab, Matt Mackall, Andrew Morton Johannes Weiner writes: > After the loop in walk_pte_range() pte might point to the first address > after the pmd it walks. The pte_unmap() is then applied to something > bad. > > Spotted by Roel Kluin and Andreas Schwab. > > Signed-off-by: Johannes Weiner <hannes@saeurebad.de> > CC: Roel Kluin <12o3l@tiscali.nl> > CC: Andreas Schwab <schwab@suse.de> > CC: Matt Mackall <mpm@selenic.com> > CC: Andrew Morton <akpm@linux-foundation.org> > --- > > A bug is unlikely, though. kunmap_atomic() looks up the kmap entry by > map-type instead of the address the pte points. So the worst thing I > could find with a quick grep was that a wrong TLB entry is being > flushed. Still, the code is wrong :) > > diff --git a/mm/pagewalk.c b/mm/pagewalk.c > index 1cf1417..cf3c004 100644 > --- a/mm/pagewalk.c > +++ b/mm/pagewalk.c > @@ -13,7 +13,7 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, > err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private); > if (err) > break; > - } while (pte++, addr += PAGE_SIZE, addr != end); > + } while (addr += PAGE_SIZE, addr != end && pte++); Instead of obfuscating the code by putting "&& pte++" in the condition (it will always be true in valid C), you should IMO rewrite the do-while as a for loop + break, like this: for (;;) { // same body as before addr += PAGE_SIZE; if (addr == end) break; pte++; } This makes the ordering constraints very clear. ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] mm: Fix possible off-by-one in walk_pte_range() 2008-04-15 15:36 ` Mikael Pettersson @ 2008-04-15 16:16 ` Johannes Weiner 2008-04-15 21:34 ` Matt Mackall 2008-04-16 7:48 ` Mikael Pettersson 0 siblings, 2 replies; 5+ messages in thread From: Johannes Weiner @ 2008-04-15 16:16 UTC (permalink / raw) To: Mikael Pettersson Cc: LKML, Roel Kluin, Andreas Schwab, Matt Mackall, Andrew Morton Hi, Mikael Pettersson <mikpe@it.uu.se> writes: > Johannes Weiner writes: > > After the loop in walk_pte_range() pte might point to the first address > > after the pmd it walks. The pte_unmap() is then applied to something > > bad. > > > > Spotted by Roel Kluin and Andreas Schwab. > > > > Signed-off-by: Johannes Weiner <hannes@saeurebad.de> > > CC: Roel Kluin <12o3l@tiscali.nl> > > CC: Andreas Schwab <schwab@suse.de> > > CC: Matt Mackall <mpm@selenic.com> > > CC: Andrew Morton <akpm@linux-foundation.org> > > --- > > > > A bug is unlikely, though. kunmap_atomic() looks up the kmap entry by > > map-type instead of the address the pte points. So the worst thing I > > could find with a quick grep was that a wrong TLB entry is being > > flushed. Still, the code is wrong :) > > > > diff --git a/mm/pagewalk.c b/mm/pagewalk.c > > index 1cf1417..cf3c004 100644 > > --- a/mm/pagewalk.c > > +++ b/mm/pagewalk.c > > @@ -13,7 +13,7 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, > > err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private); > > if (err) > > break; > > - } while (pte++, addr += PAGE_SIZE, addr != end); > > + } while (addr += PAGE_SIZE, addr != end && pte++); > > Instead of obfuscating the code by putting "&& pte++" in the > condition (it will always be true in valid C), you should IMO > rewrite the do-while as a for loop + break, like this: > > for (;;) { > // same body as before > addr += PAGE_SIZE; > if (addr == end) > break; > pte++; > } Sorry, I think too lispy :) Hannes --- From: Johannes Weiner <hannes@saeurebad.de> Subject: [PATCH] mm: Fix possible off-by-one in walk_pte_range() After the loop in walk_pte_range() pte might point to the first address after the pmd it walks. The pte_unmap() is then applied to something bad. Spotted by Roel Kluin and Andreas Schwab. Signed-off-by: Johannes Weiner <hannes@saeurebad.de> CC: Roel Kluin <12o3l@tiscali.nl> CC: Andreas Schwab <schwab@suse.de> CC: Matt Mackall <mpm@selenic.com> CC: Andrew Morton <akpm@linux-foundation.org> --- A bug is unlikely, though. kunmap_atomic() looks up the kmap entry by map-type instead of the address the pte points. So the worst thing I could find with a quick grep was that a wrong TLB entry is being flushed. Still, the code is wrong :) diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 1cf1417..0afd238 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -9,11 +9,15 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, int err = 0; pte = pte_offset_map(pmd, addr); - do { + for (;;) { err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private); if (err) break; - } while (pte++, addr += PAGE_SIZE, addr != end); + addr += PAGE_SIZE; + if (addr == end) + break; + pte++; + } pte_unmap(pte); return err; ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] mm: Fix possible off-by-one in walk_pte_range() 2008-04-15 16:16 ` [PATCH v2] " Johannes Weiner @ 2008-04-15 21:34 ` Matt Mackall 2008-04-16 7:48 ` Mikael Pettersson 1 sibling, 0 replies; 5+ messages in thread From: Matt Mackall @ 2008-04-15 21:34 UTC (permalink / raw) To: Johannes Weiner Cc: Mikael Pettersson, LKML, Roel Kluin, Andreas Schwab, Andrew Morton On Tue, 2008-04-15 at 18:16 +0200, Johannes Weiner wrote: > From: Johannes Weiner <hannes@saeurebad.de> > Subject: [PATCH] mm: Fix possible off-by-one in walk_pte_range() > > After the loop in walk_pte_range() pte might point to the first address > after the pmd it walks. The pte_unmap() is then applied to something > bad. > > Spotted by Roel Kluin and Andreas Schwab. > > Signed-off-by: Johannes Weiner <hannes@saeurebad.de> Acked-by: Matt Mackall <mpm@selenic.com> -- Mathematics is the supreme nostalgia of our time. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] mm: Fix possible off-by-one in walk_pte_range() 2008-04-15 16:16 ` [PATCH v2] " Johannes Weiner 2008-04-15 21:34 ` Matt Mackall @ 2008-04-16 7:48 ` Mikael Pettersson 1 sibling, 0 replies; 5+ messages in thread From: Mikael Pettersson @ 2008-04-16 7:48 UTC (permalink / raw) To: Johannes Weiner Cc: Mikael Pettersson, LKML, Roel Kluin, Andreas Schwab, Matt Mackall, Andrew Morton Johannes Weiner writes: > From: Johannes Weiner <hannes@saeurebad.de> > Subject: [PATCH] mm: Fix possible off-by-one in walk_pte_range() > > After the loop in walk_pte_range() pte might point to the first address > after the pmd it walks. The pte_unmap() is then applied to something > bad. > > Spotted by Roel Kluin and Andreas Schwab. > > Signed-off-by: Johannes Weiner <hannes@saeurebad.de> > CC: Roel Kluin <12o3l@tiscali.nl> > CC: Andreas Schwab <schwab@suse.de> > CC: Matt Mackall <mpm@selenic.com> > CC: Andrew Morton <akpm@linux-foundation.org> Thanks, v2 looks much nicer. Acked-by: Mikael Pettersson <mikpe@it.uu.se> ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-04-16 7:50 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-04-15 14:00 [PATCH] mm: Fix possible off-by-one in walk_pte_range() Johannes Weiner 2008-04-15 15:36 ` Mikael Pettersson 2008-04-15 16:16 ` [PATCH v2] " Johannes Weiner 2008-04-15 21:34 ` Matt Mackall 2008-04-16 7:48 ` Mikael Pettersson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox