On Mon, Feb 15, 2021 at 09:44:24AM +0100, Michal Hocko wrote: > On Sat 13-02-21 15:05:28, Ivan Safonov wrote: > > memdup_user() is shorter and safer equivalent > > of kmalloc/copy_from_user pair. > > > > Signed-off-by: Ivan Safonov <insafo...@gmail.com> > > --- > > drivers/staging/wlan-ng/p80211netdev.c | 28 ++++++++++++-------------- > > 1 file changed, 13 insertions(+), 15 deletions(-) > > > > diff --git a/drivers/staging/wlan-ng/p80211netdev.c > > b/drivers/staging/wlan-ng/p80211netdev.c > > index a15abb2c8f54..6f9666dc0277 100644 > > --- a/drivers/staging/wlan-ng/p80211netdev.c > > +++ b/drivers/staging/wlan-ng/p80211netdev.c > > @@ -569,24 +569,22 @@ static int p80211knetdev_do_ioctl(struct net_device > > *dev, > > goto bail; > > } > > > > - /* Allocate a buf of size req->len */ > > - msgbuf = kmalloc(req->len, GFP_KERNEL); > > - if (msgbuf) { > > - if (copy_from_user(msgbuf, (void __user *)req->data, req->len)) > > - result = -EFAULT; > > - else > > - result = p80211req_dorequest(wlandev, msgbuf); > > + msgbuf = memdup_user(req->data, req->len); > > Move to memdup_user is definitely a right step. What is the range of > req->len though? If this can be larger than PAGE_SIZE then vmemdup_user > would be a better alternative.
req->len shoudn't be anywhere close to PAGE_SIZE but it's actually important to check req->len and this code does not do that which leads to memory corruption: drivers/staging/wlan-ng/p80211netdev.c 566 goto bail; 567 } else if (cmd != P80211_IFREQ) { 568 result = -EINVAL; 569 goto bail; 570 } 571 572 msgbuf = memdup_user(req->data, req->len); 573 if (IS_ERR(msgbuf)) { 574 result = PTR_ERR(msgbuf); 575 goto bail; 576 } 577 578 result = p80211req_dorequest(wlandev, msgbuf); We don't know that "req->len" is >= sizeof(*msgbuf), and then we pass msgbuf top80211req_dorequest() which calls p80211req_handlemsg(). In p80211req_handlemsg() then "req->len" has to be larger than sizeof(struct p80211msg_lnxreq_hostwep). 579 580 if (result == 0) { 581 if (copy_to_user 582 ((void __user *)req->data, msgbuf, req->len)) { 583 result = -EFAULT; 584 } 585 } 586 kfree(msgbuf); 587 588 bail: 589 /* If allocate,copyfrom or copyto fails, return errno */ 590 return result; 591 } Smatch has a problem parsing this code because struct ifreq *ifr is a union and Smatch gets confused. :/ regards, dan carpenter