Commit 04a1e62c authored by Linus Torvalds's avatar Linus Torvalds

x86/ptrace: make genregs[32]_get/set more robust

The loop condition is fragile: we compare an unsigned value to zero, and
then decrement it by something larger than one in the loop.  All the
callers should be passing in appropriately aligned buffer lengths, but
it's better to just not rely on it, and have some appropriate defensive
loop limits.
Acked-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 718deb6b
...@@ -509,14 +509,14 @@ static int genregs_get(struct task_struct *target, ...@@ -509,14 +509,14 @@ static int genregs_get(struct task_struct *target,
{ {
if (kbuf) { if (kbuf) {
unsigned long *k = kbuf; unsigned long *k = kbuf;
while (count > 0) { while (count >= sizeof(*k)) {
*k++ = getreg(target, pos); *k++ = getreg(target, pos);
count -= sizeof(*k); count -= sizeof(*k);
pos += sizeof(*k); pos += sizeof(*k);
} }
} else { } else {
unsigned long __user *u = ubuf; unsigned long __user *u = ubuf;
while (count > 0) { while (count >= sizeof(*u)) {
if (__put_user(getreg(target, pos), u++)) if (__put_user(getreg(target, pos), u++))
return -EFAULT; return -EFAULT;
count -= sizeof(*u); count -= sizeof(*u);
...@@ -535,14 +535,14 @@ static int genregs_set(struct task_struct *target, ...@@ -535,14 +535,14 @@ static int genregs_set(struct task_struct *target,
int ret = 0; int ret = 0;
if (kbuf) { if (kbuf) {
const unsigned long *k = kbuf; const unsigned long *k = kbuf;
while (count > 0 && !ret) { while (count >= sizeof(*k) && !ret) {
ret = putreg(target, pos, *k++); ret = putreg(target, pos, *k++);
count -= sizeof(*k); count -= sizeof(*k);
pos += sizeof(*k); pos += sizeof(*k);
} }
} else { } else {
const unsigned long __user *u = ubuf; const unsigned long __user *u = ubuf;
while (count > 0 && !ret) { while (count >= sizeof(*u) && !ret) {
unsigned long word; unsigned long word;
ret = __get_user(word, u++); ret = __get_user(word, u++);
if (ret) if (ret)
...@@ -1458,14 +1458,14 @@ static int genregs32_get(struct task_struct *target, ...@@ -1458,14 +1458,14 @@ static int genregs32_get(struct task_struct *target,
{ {
if (kbuf) { if (kbuf) {
compat_ulong_t *k = kbuf; compat_ulong_t *k = kbuf;
while (count > 0) { while (count >= sizeof(*k)) {
getreg32(target, pos, k++); getreg32(target, pos, k++);
count -= sizeof(*k); count -= sizeof(*k);
pos += sizeof(*k); pos += sizeof(*k);
} }
} else { } else {
compat_ulong_t __user *u = ubuf; compat_ulong_t __user *u = ubuf;
while (count > 0) { while (count >= sizeof(*u)) {
compat_ulong_t word; compat_ulong_t word;
getreg32(target, pos, &word); getreg32(target, pos, &word);
if (__put_user(word, u++)) if (__put_user(word, u++))
...@@ -1486,14 +1486,14 @@ static int genregs32_set(struct task_struct *target, ...@@ -1486,14 +1486,14 @@ static int genregs32_set(struct task_struct *target,
int ret = 0; int ret = 0;
if (kbuf) { if (kbuf) {
const compat_ulong_t *k = kbuf; const compat_ulong_t *k = kbuf;
while (count > 0 && !ret) { while (count >= sizeof(*k) && !ret) {
ret = putreg32(target, pos, *k++); ret = putreg32(target, pos, *k++);
count -= sizeof(*k); count -= sizeof(*k);
pos += sizeof(*k); pos += sizeof(*k);
} }
} else { } else {
const compat_ulong_t __user *u = ubuf; const compat_ulong_t __user *u = ubuf;
while (count > 0 && !ret) { while (count >= sizeof(*u) && !ret) {
compat_ulong_t word; compat_ulong_t word;
ret = __get_user(word, u++); ret = __get_user(word, u++);
if (ret) if (ret)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment