diff options
| author | Guillaume Nault <g.nault@alphalink.fr> | 2016-03-14 16:17:16 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-03-16 19:35:06 -0400 |
| commit | e8e56ffd9d2973398b60ece1f1bebb8d67b4d032 (patch) | |
| tree | 06154afcd07d48f65e66a388f0f8634efdd6cfbf /drivers/net/ppp | |
| parent | c8f5d29899901cea94bf4b8cf721e1b83e51174e (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.c | 31 |
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 | ||
| 576 | static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 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 | 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 | |||
| 836 | out: | ||
| 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 | ||
