aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ppp
diff options
context:
space:
mode:
authorGuillaume Nault <g.nault@alphalink.fr>2016-03-14 16:17:16 -0400
committerDavid S. Miller <davem@davemloft.net>2016-03-16 19:35:06 -0400
commite8e56ffd9d2973398b60ece1f1bebb8d67b4d032 (patch)
tree06154afcd07d48f65e66a388f0f8634efdd6cfbf /drivers/net/ppp
parentc8f5d29899901cea94bf4b8cf721e1b83e51174e (diff)
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>
Diffstat (limited to 'drivers/net/ppp')
-rw-r--r--drivers/net/ppp/ppp_generic.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 931836e09a6b..4fd861063ed4 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -575,7 +575,7 @@ static int get_filter(void __user *arg, struct sock_filter **p)
575 575
576static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 576static 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 struct ppp *ppp; 579 struct ppp *ppp;
580 int err = -EFAULT, val, val2, i; 580 int err = -EFAULT, val, val2, i;
581 struct ppp_idle idle; 581 struct ppp_idle idle;
@@ -585,9 +585,14 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
585 void __user *argp = (void __user *)arg; 585 void __user *argp = (void __user *)arg;
586 int __user *p = argp; 586 int __user *p = argp;
587 587
588 if (!pf) 588 mutex_lock(&ppp_mutex);
589 return ppp_unattached_ioctl(current->nsproxy->net_ns, 589
590 pf, file, cmd, arg); 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 if (cmd == PPPIOCDETACH) { 597 if (cmd == PPPIOCDETACH) {
593 /* 598 /*
@@ -602,7 +607,6 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
602 * this fd and reopening /dev/ppp. 607 * this fd and reopening /dev/ppp.
603 */ 608 */
604 err = -EINVAL; 609 err = -EINVAL;
605 mutex_lock(&ppp_mutex);
606 if (pf->kind == INTERFACE) { 610 if (pf->kind == INTERFACE) {
607 ppp = PF_TO_PPP(pf); 611 ppp = PF_TO_PPP(pf);
608 rtnl_lock(); 612 rtnl_lock();
@@ -616,15 +620,13 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
616 } else 620 } else
617 pr_warn("PPPIOCDETACH file->f_count=%ld\n", 621 pr_warn("PPPIOCDETACH file->f_count=%ld\n",
618 atomic_long_read(&file->f_count)); 622 atomic_long_read(&file->f_count));
619 mutex_unlock(&ppp_mutex); 623 goto out;
620 return err;
621 } 624 }
622 625
623 if (pf->kind == CHANNEL) { 626 if (pf->kind == CHANNEL) {
624 struct channel *pch; 627 struct channel *pch;
625 struct ppp_channel *chan; 628 struct ppp_channel *chan;
626 629
627 mutex_lock(&ppp_mutex);
628 pch = PF_TO_CHANNEL(pf); 630 pch = PF_TO_CHANNEL(pf);
629 631
630 switch (cmd) { 632 switch (cmd) {
@@ -646,17 +648,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
646 err = chan->ops->ioctl(chan, cmd, arg); 648 err = chan->ops->ioctl(chan, cmd, arg);
647 up_read(&pch->chan_sem); 649 up_read(&pch->chan_sem);
648 } 650 }
649 mutex_unlock(&ppp_mutex); 651 goto out;
650 return err;
651 } 652 }
652 653
653 if (pf->kind != INTERFACE) { 654 if (pf->kind != INTERFACE) {
654 /* can't happen */ 655 /* can't happen */
655 pr_err("PPP: not interface or channel??\n"); 656 pr_err("PPP: not interface or channel??\n");
656 return -EINVAL; 657 err = -EINVAL;
658 goto out;
657 } 659 }
658 660
659 mutex_lock(&ppp_mutex);
660 ppp = PF_TO_PPP(pf); 661 ppp = PF_TO_PPP(pf);
661 switch (cmd) { 662 switch (cmd) {
662 case PPPIOCSMRU: 663 case PPPIOCSMRU:
@@ -831,7 +832,10 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
831 default: 832 default:
832 err = -ENOTTY; 833 err = -ENOTTY;
833 } 834 }
835
836out:
834 mutex_unlock(&ppp_mutex); 837 mutex_unlock(&ppp_mutex);
838
835 return err; 839 return err;
836} 840}
837 841
@@ -844,7 +848,6 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
844 struct ppp_net *pn; 848 struct ppp_net *pn;
845 int __user *p = (int __user *)arg; 849 int __user *p = (int __user *)arg;
846 850
847 mutex_lock(&ppp_mutex);
848 switch (cmd) { 851 switch (cmd) {
849 case PPPIOCNEWUNIT: 852 case PPPIOCNEWUNIT:
850 /* Create a new ppp unit */ 853 /* Create a new ppp unit */
@@ -894,7 +897,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
894 default: 897 default:
895 err = -ENOTTY; 898 err = -ENOTTY;
896 } 899 }
897 mutex_unlock(&ppp_mutex); 900
898 return err; 901 return err;
899} 902}
900 903