]> rtime.felk.cvut.cz Git - coffee/buildroot.git/blob - package/quagga/0006-bgpd-security-Fix-double-free-of-unknown-attribute.patch
quagga: add upstream security fixes
[coffee/buildroot.git] / package / quagga / 0006-bgpd-security-Fix-double-free-of-unknown-attribute.patch
1 From e69b535f92eafb599329bf725d9b4c6fd5d7fded Mon Sep 17 00:00:00 2001
2 From: Paul Jakma <paul@jakma.org>
3 Date: Sat, 6 Jan 2018 19:52:10 +0000
4 Subject: [PATCH] bgpd/security: Fix double free of unknown attribute
5
6 Security issue: Quagga-2018-1114
7 See: https://www.quagga.net/security/Quagga-2018-1114.txt
8
9 It is possible for bgpd to double-free an unknown attribute. This can happen
10 via bgp_update_receive receiving an UPDATE with an invalid unknown attribute.
11 bgp_update_receive then will call bgp_attr_unintern_sub and bgp_attr_flush,
12 and the latter may try free an already freed unknown attr.
13
14 * bgpd/bgp_attr.c: (transit_unintern) Take a pointer to the caller's storage
15   for the (struct transit *), so that transit_unintern can NULL out the
16   caller's reference if the (struct transit) is freed.
17   (cluster_unintern) By inspection, appears to have a similar issue.
18   (bgp_attr_unintern_sub) adjust for above.
19
20 Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
21 ---
22  bgpd/bgp_attr.c | 33 +++++++++++++++++++--------------
23  bgpd/bgp_attr.h |  4 ++--
24  2 files changed, 21 insertions(+), 16 deletions(-)
25
26 diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
27 index 9564637e..0c2806b5 100644
28 --- a/bgpd/bgp_attr.c
29 +++ b/bgpd/bgp_attr.c
30 @@ -199,15 +199,17 @@ cluster_intern (struct cluster_list *cluster)
31  }
32  
33  void
34 -cluster_unintern (struct cluster_list *cluster)
35 +cluster_unintern (struct cluster_list **cluster)
36  {
37 -  if (cluster->refcnt)
38 -    cluster->refcnt--;
39 +  struct cluster_list *c = *cluster;
40 +  if (c->refcnt)
41 +    c->refcnt--;
42  
43 -  if (cluster->refcnt == 0)
44 +  if (c->refcnt == 0)
45      {
46 -      hash_release (cluster_hash, cluster);
47 -      cluster_free (cluster);
48 +      hash_release (cluster_hash, c);
49 +      cluster_free (c);
50 +      *cluster = NULL;
51      }
52  }
53  
54 @@ -357,15 +359,18 @@ transit_intern (struct transit *transit)
55  }
56  
57  void
58 -transit_unintern (struct transit *transit)
59 +transit_unintern (struct transit **transit)
60  {
61 -  if (transit->refcnt)
62 -    transit->refcnt--;
63 +  struct transit *t = *transit;
64 +  
65 +  if (t->refcnt)
66 +    t->refcnt--;
67  
68 -  if (transit->refcnt == 0)
69 +  if (t->refcnt == 0)
70      {
71 -      hash_release (transit_hash, transit);
72 -      transit_free (transit);
73 +      hash_release (transit_hash, t);
74 +      transit_free (t);
75 +      *transit = NULL;
76      }
77  }
78  
79 @@ -820,11 +825,11 @@ bgp_attr_unintern_sub (struct attr *attr)
80        UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
81        
82        if (attr->extra->cluster)
83 -        cluster_unintern (attr->extra->cluster);
84 +        cluster_unintern (&attr->extra->cluster);
85        UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST));
86        
87        if (attr->extra->transit)
88 -        transit_unintern (attr->extra->transit);
89 +        transit_unintern (&attr->extra->transit);
90      }
91  }
92  
93 diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
94 index 9ff074b2..052acc7d 100644
95 --- a/bgpd/bgp_attr.h
96 +++ b/bgpd/bgp_attr.h
97 @@ -187,10 +187,10 @@ extern unsigned long int attr_unknown_count (void);
98  
99  /* Cluster list prototypes. */
100  extern int cluster_loop_check (struct cluster_list *, struct in_addr);
101 -extern void cluster_unintern (struct cluster_list *);
102 +extern void cluster_unintern (struct cluster_list **);
103  
104  /* Transit attribute prototypes. */
105 -void transit_unintern (struct transit *);
106 +void transit_unintern (struct transit **);
107  
108  /* Below exported for unit-test purposes only */
109  struct bgp_attr_parser_args {
110 -- 
111 2.11.0
112