aboutsummaryrefslogtreecommitdiffstats
path: root/net/x25/x25_facilities.c
diff options
context:
space:
mode:
authorMatthew Daley <mattjd@gmail.com>2011-10-14 14:45:04 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-17 19:31:39 -0400
commitcb101ed2c3c7c0224d16953fe77bfb9d6c2cb9df (patch)
tree3d266ac18673ebc85a99e4d10d8d381ff1ebd782 /net/x25/x25_facilities.c
parentc7fd0d48bde943e228e9c28ce971a22d6a1744c4 (diff)
x25: Handle undersized/fragmented skbs
There are multiple locations in the X.25 packet layer where a skb is assumed to be of at least a certain size and that all its data is currently available at skb->data. These assumptions are not checked, hence buffer overreads may occur. Use pskb_may_pull to check these minimal size assumptions and ensure that data is available at skb->data when necessary, as well as use skb_copy_bits where needed. Signed-off-by: Matthew Daley <mattjd@gmail.com> Cc: Eric Dumazet <eric.dumazet@gmail.com> Cc: Andrew Hendry <andrew.hendry@gmail.com> Cc: stable <stable@kernel.org> Acked-by: Andrew Hendry <andrew.hendry@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/x25/x25_facilities.c')
-rw-r--r--net/x25/x25_facilities.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index f77e4e75f914..36384a1fa9f2 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -44,7 +44,7 @@
44int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, 44int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
45 struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) 45 struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask)
46{ 46{
47 unsigned char *p = skb->data; 47 unsigned char *p;
48 unsigned int len; 48 unsigned int len;
49 49
50 *vc_fac_mask = 0; 50 *vc_fac_mask = 0;
@@ -60,14 +60,16 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
60 memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); 60 memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae));
61 memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); 61 memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae));
62 62
63 if (skb->len < 1) 63 if (!pskb_may_pull(skb, 1))
64 return 0; 64 return 0;
65 65
66 len = *p++; 66 len = skb->data[0];
67 67
68 if (len >= skb->len) 68 if (!pskb_may_pull(skb, 1 + len))
69 return -1; 69 return -1;
70 70
71 p = skb->data + 1;
72
71 while (len > 0) { 73 while (len > 0) {
72 switch (*p & X25_FAC_CLASS_MASK) { 74 switch (*p & X25_FAC_CLASS_MASK) {
73 case X25_FAC_CLASS_A: 75 case X25_FAC_CLASS_A: