| From 9225c0b7b976dd9ceac2b80727a60d8fcb906a62 Mon Sep 17 00:00:00 2001 |
| From: Al Viro <viro@ZenIV.linux.org.uk> |
| Date: Tue, 1 Dec 2015 19:52:12 +0000 |
| Subject: staging: lustre: echo_copy.._lsm() dereferences userland pointers directly |
| |
| From: Al Viro <viro@ZenIV.linux.org.uk> |
| |
| commit 9225c0b7b976dd9ceac2b80727a60d8fcb906a62 upstream. |
| |
| missing get_user() |
| |
| Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/staging/lustre/lustre/obdecho/echo_client.c | 20 +++++++++++--------- |
| 1 file changed, 11 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c |
| +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c |
| @@ -1268,6 +1268,7 @@ static int |
| echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob) |
| { |
| struct lov_stripe_md *ulsm = _ulsm; |
| + struct lov_oinfo **p; |
| int nob, i; |
| |
| nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]); |
| @@ -1277,9 +1278,10 @@ echo_copyout_lsm(struct lov_stripe_md *l |
| if (copy_to_user(ulsm, lsm, sizeof(*ulsm))) |
| return -EFAULT; |
| |
| - for (i = 0; i < lsm->lsm_stripe_count; i++) { |
| - if (copy_to_user(ulsm->lsm_oinfo[i], lsm->lsm_oinfo[i], |
| - sizeof(lsm->lsm_oinfo[0]))) |
| + for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) { |
| + struct lov_oinfo __user *up; |
| + if (get_user(up, ulsm->lsm_oinfo + i) || |
| + copy_to_user(up, *p, sizeof(struct lov_oinfo))) |
| return -EFAULT; |
| } |
| return 0; |
| @@ -1287,9 +1289,10 @@ echo_copyout_lsm(struct lov_stripe_md *l |
| |
| static int |
| echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm, |
| - void *ulsm, int ulsm_nob) |
| + struct lov_stripe_md __user *ulsm, int ulsm_nob) |
| { |
| struct echo_client_obd *ec = ed->ed_ec; |
| + struct lov_oinfo **p; |
| int i; |
| |
| if (ulsm_nob < sizeof(*lsm)) |
| @@ -1305,11 +1308,10 @@ echo_copyin_lsm(struct echo_device *ed, |
| return -EINVAL; |
| |
| |
| - for (i = 0; i < lsm->lsm_stripe_count; i++) { |
| - if (copy_from_user(lsm->lsm_oinfo[i], |
| - ((struct lov_stripe_md *)ulsm)-> \ |
| - lsm_oinfo[i], |
| - sizeof(lsm->lsm_oinfo[0]))) |
| + for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) { |
| + struct lov_oinfo __user *up; |
| + if (get_user(up, ulsm->lsm_oinfo + i) || |
| + copy_from_user(*p, up, sizeof(struct lov_oinfo))) |
| return -EFAULT; |
| } |
| return 0; |