summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAravind Srinivasan <raa.aars@gmail.com>2009-04-02 16:58:59 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 19:05:05 -0700
commit2c53d9109f077900e140edb8b766132ad93b81cc (patch)
tree082c063da6c83fe2a2aa84ed0b33c504e19d05f4
parentedb79a213223488735fae1d408f4c136e9ed25d6 (diff)
relay: fix for possible loss/corruption of produced subbufs
Fix possible loss/corruption of produced subbufs in relay_subbufs_consumed(). When buf->subbufs_produced wraps around after UINT_MAX and buf->subbufs_consumed is still < UINT_MAX, the condition if (buf->subbufs_consumed > buf->subbufs_produced) will be true even for certain valid values of subbufs_consumed. This may lead to loss or corruption of produced subbufs. Signed-off-by: Aravind Srinivasan <raa.aars@gmail.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Tom Zanussi <zanussi@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/relay.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/kernel/relay.c b/kernel/relay.c
index 8f2179c8056f..e92db8c06acf 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -797,13 +797,15 @@ void relay_subbufs_consumed(struct rchan *chan,
if (!chan)
return;
- if (cpu >= NR_CPUS || !chan->buf[cpu])
+ if (cpu >= NR_CPUS || !chan->buf[cpu] ||
+ subbufs_consumed > chan->n_subbufs)
return;
buf = chan->buf[cpu];
- buf->subbufs_consumed += subbufs_consumed;
- if (buf->subbufs_consumed > buf->subbufs_produced)
+ if (subbufs_consumed > buf->subbufs_produced - buf->subbufs_consumed)
buf->subbufs_consumed = buf->subbufs_produced;
+ else
+ buf->subbufs_consumed += subbufs_consumed;
}
EXPORT_SYMBOL_GPL(relay_subbufs_consumed);