Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ppp: ensure file->private_data can't be overridden

Locking ppp_mutex must be done before dereferencing file->private_data,
otherwise it could be modified before ppp_unattached_ioctl() takes the
lock. This could lead ppp_unattached_ioctl() to override ->private_data,
thus leaking reference to the ppp_file previously pointed to.

v2: lock all ppp_ioctl() instead of just checking private_data in
ppp_unattached_ioctl(), to avoid ambiguous behaviour.

Fixes: f3ff8a4d80e8 ("ppp: push BKL down into the driver")
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Guillaume Nault and committed by
David S. Miller
e8e56ffd c8f5d298

+17 -14
+17 -14
drivers/net/ppp/ppp_generic.c
··· 575 575 576 576 static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 577 577 { 578 - struct ppp_file *pf = file->private_data; 578 + struct ppp_file *pf; 579 579 struct ppp *ppp; 580 580 int err = -EFAULT, val, val2, i; 581 581 struct ppp_idle idle; ··· 585 585 void __user *argp = (void __user *)arg; 586 586 int __user *p = argp; 587 587 588 - if (!pf) 589 - return ppp_unattached_ioctl(current->nsproxy->net_ns, 590 - pf, file, cmd, arg); 588 + mutex_lock(&ppp_mutex); 589 + 590 + pf = file->private_data; 591 + if (!pf) { 592 + err = ppp_unattached_ioctl(current->nsproxy->net_ns, 593 + pf, file, cmd, arg); 594 + goto out; 595 + } 591 596 592 597 if (cmd == PPPIOCDETACH) { 593 598 /* ··· 607 602 * this fd and reopening /dev/ppp. 608 603 */ 609 604 err = -EINVAL; 610 - mutex_lock(&ppp_mutex); 611 605 if (pf->kind == INTERFACE) { 612 606 ppp = PF_TO_PPP(pf); 613 607 rtnl_lock(); ··· 620 616 } else 621 617 pr_warn("PPPIOCDETACH file->f_count=%ld\n", 622 618 atomic_long_read(&file->f_count)); 623 - mutex_unlock(&ppp_mutex); 624 - return err; 619 + goto out; 625 620 } 626 621 627 622 if (pf->kind == CHANNEL) { 628 623 struct channel *pch; 629 624 struct ppp_channel *chan; 630 625 631 - mutex_lock(&ppp_mutex); 632 626 pch = PF_TO_CHANNEL(pf); 633 627 634 628 switch (cmd) { ··· 648 646 err = chan->ops->ioctl(chan, cmd, arg); 649 647 up_read(&pch->chan_sem); 650 648 } 651 - mutex_unlock(&ppp_mutex); 652 - return err; 649 + goto out; 653 650 } 654 651 655 652 if (pf->kind != INTERFACE) { 656 653 /* can't happen */ 657 654 pr_err("PPP: not interface or channel??\n"); 658 - return -EINVAL; 655 + err = -EINVAL; 656 + goto out; 659 657 } 660 658 661 - mutex_lock(&ppp_mutex); 662 659 ppp = PF_TO_PPP(pf); 663 660 switch (cmd) { 664 661 case PPPIOCSMRU: ··· 832 831 default: 833 832 err = -ENOTTY; 834 833 } 834 + 835 + out: 835 836 mutex_unlock(&ppp_mutex); 837 + 836 838 return err; 837 839 } 838 840 ··· 848 844 struct ppp_net *pn; 849 845 int __user *p = (int __user *)arg; 850 846 851 - mutex_lock(&ppp_mutex); 852 847 switch (cmd) { 853 848 case PPPIOCNEWUNIT: 854 849 /* Create a new ppp unit */ ··· 897 894 default: 898 895 err = -ENOTTY; 899 896 } 900 - mutex_unlock(&ppp_mutex); 897 + 901 898 return err; 902 899 } 903 900