diff options
author | Ian Schram <ischram@telenet.be> | 2009-09-18 15:26:26 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-19 13:32:55 -0400 |
commit | cdf8073d6b2c6c5a3cd6ce0e6c1297157f7f99ba (patch) | |
tree | c5b68d4ded3b82a934c7bd25d798b8b3870e5b25 /kernel/perf_counter.c | |
parent | ec60a3fe478c0fc6d109eb5840b435ecee4d132b (diff) |
perf_counter: Fix perf_copy_attr() pointer arithmetic
There is still some weird code in per_copy_attr(). Which supposedly
checks that all bytes trailing a struct are zero.
It doesn't seem to get pointer arithmetic right. Since it
increments an iterating pointer by sizeof(unsigned long) rather
than 1.
Signed-off-by: Ian Schram <ischram@telenet.be>
[ v2: clean up the messy PTR_ALIGN logic as well. ]
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: <stable@kernel.org> # for v2.6.31.x
LKML-Reference: <4AB3DEE2.3030600@telenet.be>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/perf_counter.c')
-rw-r--r-- | kernel/perf_counter.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index d5899b62b276..cc768ab81ac8 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -4208,8 +4208,8 @@ done: | |||
4208 | static int perf_copy_attr(struct perf_counter_attr __user *uattr, | 4208 | static int perf_copy_attr(struct perf_counter_attr __user *uattr, |
4209 | struct perf_counter_attr *attr) | 4209 | struct perf_counter_attr *attr) |
4210 | { | 4210 | { |
4211 | int ret; | ||
4212 | u32 size; | 4211 | u32 size; |
4212 | int ret; | ||
4213 | 4213 | ||
4214 | if (!access_ok(VERIFY_WRITE, uattr, PERF_ATTR_SIZE_VER0)) | 4214 | if (!access_ok(VERIFY_WRITE, uattr, PERF_ATTR_SIZE_VER0)) |
4215 | return -EFAULT; | 4215 | return -EFAULT; |
@@ -4234,19 +4234,19 @@ static int perf_copy_attr(struct perf_counter_attr __user *uattr, | |||
4234 | 4234 | ||
4235 | /* | 4235 | /* |
4236 | * If we're handed a bigger struct than we know of, | 4236 | * If we're handed a bigger struct than we know of, |
4237 | * ensure all the unknown bits are 0. | 4237 | * ensure all the unknown bits are 0 - i.e. new |
4238 | * user-space does not rely on any kernel feature | ||
4239 | * extensions we dont know about yet. | ||
4238 | */ | 4240 | */ |
4239 | if (size > sizeof(*attr)) { | 4241 | if (size > sizeof(*attr)) { |
4240 | unsigned long val; | 4242 | unsigned char __user *addr; |
4241 | unsigned long __user *addr; | 4243 | unsigned char __user *end; |
4242 | unsigned long __user *end; | 4244 | unsigned char val; |
4243 | 4245 | ||
4244 | addr = PTR_ALIGN((void __user *)uattr + sizeof(*attr), | 4246 | addr = (void __user *)uattr + sizeof(*attr); |
4245 | sizeof(unsigned long)); | 4247 | end = (void __user *)uattr + size; |
4246 | end = PTR_ALIGN((void __user *)uattr + size, | ||
4247 | sizeof(unsigned long)); | ||
4248 | 4248 | ||
4249 | for (; addr < end; addr += sizeof(unsigned long)) { | 4249 | for (; addr < end; addr++) { |
4250 | ret = get_user(val, addr); | 4250 | ret = get_user(val, addr); |
4251 | if (ret) | 4251 | if (ret) |
4252 | return ret; | 4252 | return ret; |