Skip to content

Commit 532c34b

Browse files
author
Martin Schwidefsky
committed
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>
1 parent 723cacb commit 532c34b

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

Diff for: drivers/s390/char/sclp_ctl.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static int sclp_ctl_ioctl_sccb(void __user *user_area)
5656
{
5757
struct sclp_ctl_sccb ctl_sccb;
5858
struct sccb_header *sccb;
59+
unsigned long copied;
5960
int rc;
6061

6162
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)
6566
sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
6667
if (!sccb)
6768
return -ENOMEM;
68-
if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sizeof(*sccb))) {
69+
copied = PAGE_SIZE -
70+
copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), PAGE_SIZE);
71+
if (offsetof(struct sccb_header, length) +
72+
sizeof(sccb->length) > copied || sccb->length > copied) {
6973
rc = -EFAULT;
7074
goto out_free;
7175
}
72-
if (sccb->length > PAGE_SIZE || sccb->length < 8)
73-
return -EINVAL;
74-
if (copy_from_user(sccb, u64_to_uptr(ctl_sccb.sccb), sccb->length)) {
75-
rc = -EFAULT;
76+
if (sccb->length < 8) {
77+
rc = -EINVAL;
7678
goto out_free;
7779
}
7880
rc = sclp_sync_request(ctl_sccb.cmdw, sccb);

0 commit comments

Comments
 (0)