Skip to content

Commit 22f93b3

Browse files
rveerama1jhedberg
authored andcommitted
net: ipv4: Fix parsing of IPv4 header options
If IPv4 header options has wrong options length (e.g. options length is more that actual data), then parser decrements opts_len without checking actual data length. Which crashes the network stack. Signed-off-by: Ravi kumar Veeramally <[email protected]>
1 parent 6056397 commit 22f93b3

File tree

1 file changed

+15
-7
lines changed

1 file changed

+15
-7
lines changed

subsys/net/ip/ipv4.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ int net_ipv4_parse_hdr_options(struct net_pkt *pkt,
116116
{
117117
struct net_pkt_cursor cur;
118118
u8_t opt_data[NET_IPV4_HDR_OPTNS_MAX_LEN];
119-
u8_t opts_len;
119+
u8_t total_opts_len;
120120

121121
if (!cb) {
122122
return -EINVAL;
@@ -129,29 +129,33 @@ int net_ipv4_parse_hdr_options(struct net_pkt *pkt,
129129
return -EINVAL;
130130
}
131131

132-
opts_len = net_pkt_ipv4_opts_len(pkt);
132+
total_opts_len = net_pkt_ipv4_opts_len(pkt);
133133

134-
while (opts_len) {
134+
while (total_opts_len) {
135135
u8_t opt_len = 0U;
136136
u8_t opt_type;
137137

138138
if (net_pkt_read_u8(pkt, &opt_type)) {
139139
return -EINVAL;
140140
}
141141

142-
opts_len--;
142+
total_opts_len--;
143143

144144
if (!(opt_type == NET_IPV4_OPTS_EO ||
145145
opt_type == NET_IPV4_OPTS_NOP)) {
146146
if (net_pkt_read_u8(pkt, &opt_len)) {
147147
return -EINVAL;
148148
}
149149

150+
if (opt_len < 2U || total_opts_len < 1U) {
151+
return -EINVAL;
152+
}
153+
150154
opt_len -= 2U;
151-
opts_len--;
155+
total_opts_len--;
152156
}
153157

154-
if (opt_len > opts_len) {
158+
if (opt_len > total_opts_len) {
155159
return -EINVAL;
156160
}
157161

@@ -187,7 +191,7 @@ int net_ipv4_parse_hdr_options(struct net_pkt *pkt,
187191
break;
188192
}
189193

190-
opts_len -= opt_len;
194+
total_opts_len -= opt_len;
191195
}
192196

193197
net_pkt_cursor_restore(pkt, &cur);
@@ -239,6 +243,10 @@ enum net_verdict net_ipv4_input(struct net_pkt *pkt)
239243
net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv4_hdr));
240244

241245
opts_len = hdr_len - sizeof(struct net_ipv4_hdr);
246+
if (opts_len > NET_IPV4_HDR_OPTNS_MAX_LEN) {
247+
return -EINVAL;
248+
}
249+
242250
net_pkt_set_ipv4_opts_len(pkt, opts_len);
243251

244252
pkt_len = ntohs(hdr->len);

0 commit comments

Comments
 (0)