aboutsummaryrefslogtreecommitdiffstats
path: root/main/libevent/CVE-2016-10196.patch
blob: 02116a150453ebcc624674590424664e0841b8a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
Source: https://github.com/libevent/libevent/commit/329acc18a0768c21ba22522f01a5c7f46cacc4d5

commit 329acc18a0768c21ba22522f01a5c7f46cacc4d5
Author: Azat Khuzhin <a3at.mail@gmail.com>
Date:   Sun Jan 31 00:57:16 2016 +0300

    evutil_parse_sockaddr_port(): fix buffer overflow
    
    @asn-the-goblin-slayer:
      "Length between '[' and ']' is cast to signed 32 bit integer on line 1815. Is
       the length is more than 2<<31 (INT_MAX), len will hold a negative value.
       Consequently, it will pass the check at line 1816. Segfault happens at line
       1819.
    
       Generate a resolv.conf with generate-resolv.conf, then compile and run
       poc.c. See entry-functions.txt for functions in tor that might be
       vulnerable.
    
       Please credit 'Guido Vranken' for this discovery through the Tor bug bounty
       program."
    
    Reproducer for gdb (https://gist.github.com/azat/be2b0d5e9417ba0dfe2c):
      start
      p (1ULL<<31)+1ULL
      # $1 = 2147483649
      p malloc(sizeof(struct sockaddr))
      # $2 = (void *) 0x646010
      p malloc(sizeof(int))
      # $3 = (void *) 0x646030
      p malloc($1)
      # $4 = (void *) 0x7fff76a2a010
      p memset($4, 1, $1)
      # $5 = 1990369296
      p (char *)$4
      # $6 = 0x7fff76a2a010 '\001' <repeats 200 times>...
      set $6[0]='['
      set $6[$1]=']'
      p evutil_parse_sockaddr_port($4, $2, $3)
      # $7 = -1
    
    Before:
      $ gdb bin/http-connect < gdb
      (gdb) $1 = 2147483649
      (gdb) (gdb) $2 = (void *) 0x646010
      (gdb) (gdb) $3 = (void *) 0x646030
      (gdb) (gdb) $4 = (void *) 0x7fff76a2a010
      (gdb) (gdb) $5 = 1990369296
      (gdb) (gdb) $6 = 0x7fff76a2a010 '\001' <repeats 200 times>...
      (gdb) (gdb) (gdb) (gdb)
      Program received signal SIGSEGV, Segmentation fault.
      __memcpy_sse2_unaligned () at memcpy-sse2-unaligned.S:36
    
    After:
      $ gdb bin/http-connect < gdb
      (gdb) $1 = 2147483649
      (gdb) (gdb) $2 = (void *) 0x646010
      (gdb) (gdb) $3 = (void *) 0x646030
      (gdb) (gdb) $4 = (void *) 0x7fff76a2a010
      (gdb) (gdb) $5 = 1990369296
      (gdb) (gdb) $6 = 0x7fff76a2a010 '\001' <repeats 200 times>...
      (gdb) (gdb) (gdb) (gdb) $7 = -1
      (gdb) (gdb) quit
    
    Fixes: #318

diff --git a/evutil.c b/evutil.c
index 79d825d9..495bfcc0 100644
--- a/evutil.c
+++ b/evutil.c
@@ -2058,12 +2058,12 @@ evutil_parse_sockaddr_port(const char *ip_as_string, struct sockaddr *out, int *
 
 	cp = strchr(ip_as_string, ':');
 	if (*ip_as_string == '[') {
-		int len;
+		size_t len;
 		if (!(cp = strchr(ip_as_string, ']'))) {
 			return -1;
 		}
-		len = (int) ( cp-(ip_as_string + 1) );
-		if (len > (int)sizeof(buf)-1) {
+		len = ( cp-(ip_as_string + 1) );
+		if (len > sizeof(buf)-1) {
 			return -1;
 		}
 		memcpy(buf, ip_as_string+1, len);