diff options
| author | Ben Hutchings <ben@decadent.org.uk> | 2015-11-01 11:22:53 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-11-02 16:25:00 -0500 |
| commit | 4ab42d78e37a294ac7bc56901d563c642e03c4ae (patch) | |
| tree | eed185aafd345a302f05711c3e6d5d80fca7c3f9 | |
| parent | 0baa57d8dc32db78369d8b5176ef56c5e2e18ab3 (diff) | |
ppp, slip: Validate VJ compression slot parameters completely
Currently slhc_init() treats out-of-range values of rslots and tslots
as equivalent to 0, except that if tslots is too large it will
dereference a null pointer (CVE-2015-7799).
Add a range-check at the top of the function and make it return an
ERR_PTR() on error instead of NULL. Change the callers accordingly.
Compile-tested only.
Reported-by: 郭永刚 <guoyonggang@360.cn>
References: http://article.gmane.org/gmane.comp.security.oss.general/17908
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/isdn/i4l/isdn_ppp.c | 10 | ||||
| -rw-r--r-- | drivers/net/ppp/ppp_generic.c | 6 | ||||
| -rw-r--r-- | drivers/net/slip/slhc.c | 12 | ||||
| -rw-r--r-- | drivers/net/slip/slip.c | 2 |
4 files changed, 15 insertions, 15 deletions
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 86f9abebcb72..9c1e8adaf4fc 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c | |||
| @@ -322,9 +322,9 @@ isdn_ppp_open(int min, struct file *file) | |||
| 322 | * VJ header compression init | 322 | * VJ header compression init |
| 323 | */ | 323 | */ |
| 324 | is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ | 324 | is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ |
| 325 | if (!is->slcomp) { | 325 | if (IS_ERR(is->slcomp)) { |
| 326 | isdn_ppp_ccp_reset_free(is); | 326 | isdn_ppp_ccp_reset_free(is); |
| 327 | return -ENOMEM; | 327 | return PTR_ERR(is->slcomp); |
| 328 | } | 328 | } |
| 329 | #endif | 329 | #endif |
| 330 | #ifdef CONFIG_IPPP_FILTER | 330 | #ifdef CONFIG_IPPP_FILTER |
| @@ -573,10 +573,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) | |||
| 573 | is->maxcid = val; | 573 | is->maxcid = val; |
| 574 | #ifdef CONFIG_ISDN_PPP_VJ | 574 | #ifdef CONFIG_ISDN_PPP_VJ |
| 575 | sltmp = slhc_init(16, val); | 575 | sltmp = slhc_init(16, val); |
| 576 | if (!sltmp) { | 576 | if (IS_ERR(sltmp)) |
| 577 | printk(KERN_ERR "ippp, can't realloc slhc struct\n"); | 577 | return PTR_ERR(sltmp); |
| 578 | return -ENOMEM; | ||
| 579 | } | ||
| 580 | if (is->slcomp) | 578 | if (is->slcomp) |
| 581 | slhc_free(is->slcomp); | 579 | slhc_free(is->slcomp); |
| 582 | is->slcomp = sltmp; | 580 | is->slcomp = sltmp; |
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index ed00446759b2..9a863c6a6a33 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c | |||
| @@ -721,10 +721,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 721 | val &= 0xffff; | 721 | val &= 0xffff; |
| 722 | } | 722 | } |
| 723 | vj = slhc_init(val2+1, val+1); | 723 | vj = slhc_init(val2+1, val+1); |
| 724 | if (!vj) { | 724 | if (IS_ERR(vj)) { |
| 725 | netdev_err(ppp->dev, | 725 | err = PTR_ERR(vj); |
| 726 | "PPP: no memory (VJ compressor)\n"); | ||
| 727 | err = -ENOMEM; | ||
| 728 | break; | 726 | break; |
| 729 | } | 727 | } |
| 730 | ppp_lock(ppp); | 728 | ppp_lock(ppp); |
diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index 079f7adfcde5..27ed25252aac 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c | |||
| @@ -84,8 +84,9 @@ static long decode(unsigned char **cpp); | |||
| 84 | static unsigned char * put16(unsigned char *cp, unsigned short x); | 84 | static unsigned char * put16(unsigned char *cp, unsigned short x); |
| 85 | static unsigned short pull16(unsigned char **cpp); | 85 | static unsigned short pull16(unsigned char **cpp); |
| 86 | 86 | ||
| 87 | /* Initialize compression data structure | 87 | /* Allocate compression data structure |
| 88 | * slots must be in range 0 to 255 (zero meaning no compression) | 88 | * slots must be in range 0 to 255 (zero meaning no compression) |
| 89 | * Returns pointer to structure or ERR_PTR() on error. | ||
| 89 | */ | 90 | */ |
| 90 | struct slcompress * | 91 | struct slcompress * |
| 91 | slhc_init(int rslots, int tslots) | 92 | slhc_init(int rslots, int tslots) |
| @@ -94,11 +95,14 @@ slhc_init(int rslots, int tslots) | |||
| 94 | register struct cstate *ts; | 95 | register struct cstate *ts; |
| 95 | struct slcompress *comp; | 96 | struct slcompress *comp; |
| 96 | 97 | ||
| 98 | if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255) | ||
| 99 | return ERR_PTR(-EINVAL); | ||
| 100 | |||
| 97 | comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL); | 101 | comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL); |
| 98 | if (! comp) | 102 | if (! comp) |
| 99 | goto out_fail; | 103 | goto out_fail; |
| 100 | 104 | ||
| 101 | if ( rslots > 0 && rslots < 256 ) { | 105 | if (rslots > 0) { |
| 102 | size_t rsize = rslots * sizeof(struct cstate); | 106 | size_t rsize = rslots * sizeof(struct cstate); |
| 103 | comp->rstate = kzalloc(rsize, GFP_KERNEL); | 107 | comp->rstate = kzalloc(rsize, GFP_KERNEL); |
| 104 | if (! comp->rstate) | 108 | if (! comp->rstate) |
| @@ -106,7 +110,7 @@ slhc_init(int rslots, int tslots) | |||
| 106 | comp->rslot_limit = rslots - 1; | 110 | comp->rslot_limit = rslots - 1; |
| 107 | } | 111 | } |
| 108 | 112 | ||
| 109 | if ( tslots > 0 && tslots < 256 ) { | 113 | if (tslots > 0) { |
| 110 | size_t tsize = tslots * sizeof(struct cstate); | 114 | size_t tsize = tslots * sizeof(struct cstate); |
| 111 | comp->tstate = kzalloc(tsize, GFP_KERNEL); | 115 | comp->tstate = kzalloc(tsize, GFP_KERNEL); |
| 112 | if (! comp->tstate) | 116 | if (! comp->tstate) |
| @@ -141,7 +145,7 @@ out_free2: | |||
| 141 | out_free: | 145 | out_free: |
| 142 | kfree(comp); | 146 | kfree(comp); |
| 143 | out_fail: | 147 | out_fail: |
| 144 | return NULL; | 148 | return ERR_PTR(-ENOMEM); |
| 145 | } | 149 | } |
| 146 | 150 | ||
| 147 | 151 | ||
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 05387b1e2e95..a17d86a57734 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c | |||
| @@ -164,7 +164,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu) | |||
| 164 | if (cbuff == NULL) | 164 | if (cbuff == NULL) |
| 165 | goto err_exit; | 165 | goto err_exit; |
| 166 | slcomp = slhc_init(16, 16); | 166 | slcomp = slhc_init(16, 16); |
| 167 | if (slcomp == NULL) | 167 | if (IS_ERR(slcomp)) |
| 168 | goto err_exit; | 168 | goto err_exit; |
| 169 | #endif | 169 | #endif |
| 170 | spin_lock_bh(&sl->lock); | 170 | spin_lock_bh(&sl->lock); |
