aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/busybox/busybox/CVE-2018-20679.patch
blob: e4693768e0bb43c60ac9567e2018121de9fb7822 (plain)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
From 6d3b4bb24da9a07c263f3c1acf8df85382ff562c Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Mon, 17 Dec 2018 18:07:18 +0100
Subject: [PATCH] udhcpc: check that 4-byte options are indeed 4-byte, closes
 11506

function                                             old     new   delta
udhcp_get_option32                                     -      27     +27
udhcp_get_option                                     231     248     +17
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 44/0)               Total: 44 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>

Upstream-Status: Backport
CVE: CVE-2018-20679

Affects < 1.30.0

signed-off-by: Armin Kuster <akuster@mvista.com>

---
 networking/udhcp/common.c | 19 +++++++++++++++++++
 networking/udhcp/common.h |  4 ++++
 networking/udhcp/dhcpc.c  |  6 +++---
 networking/udhcp/dhcpd.c  |  6 +++---
 4 files changed, 29 insertions(+), 6 deletions(-)

Index: busybox-1.29.3/networking/udhcp/common.c
===================================================================
--- busybox-1.29.3.orig/networking/udhcp/common.c
+++ busybox-1.29.3/networking/udhcp/common.c
@@ -270,6 +270,15 @@ uint8_t* FAST_FUNC udhcp_get_option(stru
 			goto complain; /* complain and return NULL */
 
 		if (optionptr[OPT_CODE] == code) {
+			if (optionptr[OPT_LEN] == 0) {
+				/* So far no valid option with length 0 known.
+				 * Having this check means that searching
+				 * for DHCP_MESSAGE_TYPE need not worry
+				 * that returned pointer might be unsafe
+				 * to dereference.
+				 */
+				goto complain; /* complain and return NULL */
+			}
 			log_option("option found", optionptr);
 			return optionptr + OPT_DATA;
 		}
@@ -287,6 +296,16 @@ uint8_t* FAST_FUNC udhcp_get_option(stru
 	return NULL;
 }
 
+uint8_t* FAST_FUNC udhcp_get_option32(struct dhcp_packet *packet, int code)
+{
+	uint8_t *r = udhcp_get_option(packet, code);
+	if (r) {
+		if (r[-1] != 4)
+			r = NULL;
+	}
+	return r;
+}
+
 /* Return the position of the 'end' option (no bounds checking) */
 int FAST_FUNC udhcp_end_option(uint8_t *optionptr)
 {
Index: busybox-1.29.3/networking/udhcp/common.h
===================================================================
--- busybox-1.29.3.orig/networking/udhcp/common.h
+++ busybox-1.29.3/networking/udhcp/common.h
@@ -204,6 +204,10 @@ extern const uint8_t dhcp_option_lengths
 unsigned FAST_FUNC udhcp_option_idx(const char *name, const char *option_strings);
 
 uint8_t *udhcp_get_option(struct dhcp_packet *packet, int code) FAST_FUNC;
+/* Same as above + ensures that option length is 4 bytes
+ * (returns NULL if size is different)
+ */
+uint8_t *udhcp_get_option32(struct dhcp_packet *packet, int code) FAST_FUNC;
 int udhcp_end_option(uint8_t *optionptr) FAST_FUNC;
 void udhcp_add_binary_option(struct dhcp_packet *packet, uint8_t *addopt) FAST_FUNC;
 #if ENABLE_UDHCPC || ENABLE_UDHCPD
Index: busybox-1.29.3/networking/udhcp/dhcpc.c
===================================================================
--- busybox-1.29.3.orig/networking/udhcp/dhcpc.c
+++ busybox-1.29.3/networking/udhcp/dhcpc.c
@@ -1694,7 +1694,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c
  * They say ISC DHCP client supports this case.
  */
 				server_addr = 0;
-				temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
+				temp = udhcp_get_option32(&packet, DHCP_SERVER_ID);
 				if (!temp) {
 					bb_error_msg("no server ID, using 0.0.0.0");
 				} else {
@@ -1721,7 +1721,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c
 				struct in_addr temp_addr;
 				uint8_t *temp;
 
-				temp = udhcp_get_option(&packet, DHCP_LEASE_TIME);
+				temp = udhcp_get_option32(&packet, DHCP_LEASE_TIME);
 				if (!temp) {
 					bb_error_msg("no lease time with ACK, using 1 hour lease");
 					lease_seconds = 60 * 60;
@@ -1817,7 +1817,7 @@ int udhcpc_main(int argc UNUSED_PARAM, c
 					uint32_t svid;
 					uint8_t *temp;
 
-					temp = udhcp_get_option(&packet, DHCP_SERVER_ID);
+					temp = udhcp_get_option32(&packet, DHCP_SERVER_ID);
 					if (!temp) {
  non_matching_svid:
 						log1("received DHCP NAK with wrong"
Index: busybox-1.29.3/networking/udhcp/dhcpd.c
===================================================================
--- busybox-1.29.3.orig/networking/udhcp/dhcpd.c
+++ busybox-1.29.3/networking/udhcp/dhcpd.c
@@ -640,7 +640,7 @@ static void add_server_options(struct dh
 static uint32_t select_lease_time(struct dhcp_packet *packet)
 {
 	uint32_t lease_time_sec = server_config.max_lease_sec;
-	uint8_t *lease_time_opt = udhcp_get_option(packet, DHCP_LEASE_TIME);
+	uint8_t *lease_time_opt = udhcp_get_option32(packet, DHCP_LEASE_TIME);
 	if (lease_time_opt) {
 		move_from_unaligned32(lease_time_sec, lease_time_opt);
 		lease_time_sec = ntohl(lease_time_sec);
@@ -987,7 +987,7 @@ int udhcpd_main(int argc UNUSED_PARAM, c
 		}
 
 		/* Get SERVER_ID if present */
-		server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID);
+		server_id_opt = udhcp_get_option32(&packet, DHCP_SERVER_ID);
 		if (server_id_opt) {
 			uint32_t server_id_network_order;
 			move_from_unaligned32(server_id_network_order, server_id_opt);
@@ -1011,7 +1011,7 @@ int udhcpd_main(int argc UNUSED_PARAM, c
 		}
 
 		/* Get REQUESTED_IP if present */
-		requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP);
+		requested_ip_opt = udhcp_get_option32(&packet, DHCP_REQUESTED_IP);
 		if (requested_ip_opt) {
 			move_from_unaligned32(requested_nip, requested_ip_opt);
 		}