s390/sclp_ctl: fix potential information leak with /dev/sclp
The sclp_ctl_ioctl_sccb function uses two copy_from_user calls to retrieve the sclp request from user space. The first copy_from_user fetches the length of the request which is stored in the first two bytes of the request. The second copy_from_user gets the complete sclp request, but this copies the length field a second time. A malicious user may have changed the length in the meantime. Reported-by: Pengfei Wang <wpengfeinudt@gmail.com> Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Родитель
723cacbd9d
Коммит
532c34b5fb
|
@ -56,6 +56,7 @@ static int sclp_ctl_ioctl_sccb(void __user *user_area)
|
|||
{
|
||||
struct sclp_ctl_sccb ctl_sccb;
|
||||
struct sccb_header *sccb;
|
||||
unsigned long copied;
|
||||
int rc;
|
||||
|
||||
if (copy_from_user(&ctl_sccb, user_area, sizeof(ctl_sccb)))
|
||||
|
@ -65,14 +66,15 @@ static int sclp_ctl_ioctl_sccb(void __user *user_area)
|
|||
sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
||||
if (!sccb)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sizeof(*sccb))) {
|
||||
copied = PAGE_SIZE -
|
||||
copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), PAGE_SIZE);
|
||||
if (offsetof(struct sccb_header, length) +
|
||||
sizeof(sccb->length) > copied || sccb->length > copied) {
|
||||
rc = -EFAULT;
|
||||
goto out_free;
|
||||
}
|
||||
if (sccb->length > PAGE_SIZE || sccb->length < 8)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sccb->length)) {
|
||||
rc = -EFAULT;
|
||||
if (sccb->length < 8) {
|
||||
rc = -EINVAL;
|
||||
goto out_free;
|
||||
}
|
||||
rc = sclp_sync_request(ctl_sccb.cmdw, sccb);
|
||||
|
|
Загрузка…
Ссылка в новой задаче