diff options
author | Patrick McHardy <kaber@trash.net> | 2006-01-09 19:44:00 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-01-10 15:54:32 -0500 |
commit | 03b9feca89366952ae5dfe4ad8107b1ece50b710 (patch) | |
tree | 401e94d15d3f28a759ce716b8b5a742f5d32a520 /net | |
parent | 15db34702cfafd24acc60295cf14861e497502ab (diff) |
[NETFILTER]: Fix another crash in ip_nat_pptp
The PPTP NAT helper calculates the offset at which the packet needs
to be mangled as difference between two pointers to the header. With
non-linear skbs however the pointers may point to two seperate buffers
on the stack and the calculation results in a wrong offset beeing
used.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ip_nat_helper_pptp.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c index 8ad7b36e242d..50960cb681f8 100644 --- a/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c | |||
@@ -148,14 +148,14 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
148 | { | 148 | { |
149 | struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; | 149 | struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; |
150 | struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; | 150 | struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; |
151 | 151 | u_int16_t msg, new_callid; | |
152 | u_int16_t msg, *cid = NULL, new_callid; | 152 | unsigned int cid_off; |
153 | 153 | ||
154 | new_callid = htons(ct_pptp_info->pns_call_id); | 154 | new_callid = htons(ct_pptp_info->pns_call_id); |
155 | 155 | ||
156 | switch (msg = ntohs(ctlh->messageType)) { | 156 | switch (msg = ntohs(ctlh->messageType)) { |
157 | case PPTP_OUT_CALL_REQUEST: | 157 | case PPTP_OUT_CALL_REQUEST: |
158 | cid = &pptpReq->ocreq.callID; | 158 | cid_off = offsetof(union pptp_ctrl_union, ocreq.callID); |
159 | /* FIXME: ideally we would want to reserve a call ID | 159 | /* FIXME: ideally we would want to reserve a call ID |
160 | * here. current netfilter NAT core is not able to do | 160 | * here. current netfilter NAT core is not able to do |
161 | * this :( For now we use TCP source port. This breaks | 161 | * this :( For now we use TCP source port. This breaks |
@@ -172,10 +172,10 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
172 | ct_pptp_info->pns_call_id = ntohs(new_callid); | 172 | ct_pptp_info->pns_call_id = ntohs(new_callid); |
173 | break; | 173 | break; |
174 | case PPTP_IN_CALL_REPLY: | 174 | case PPTP_IN_CALL_REPLY: |
175 | cid = &pptpReq->icreq.callID; | 175 | cid_off = offsetof(union pptp_ctrl_union, icreq.callID); |
176 | break; | 176 | break; |
177 | case PPTP_CALL_CLEAR_REQUEST: | 177 | case PPTP_CALL_CLEAR_REQUEST: |
178 | cid = &pptpReq->clrreq.callID; | 178 | cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); |
179 | break; | 179 | break; |
180 | default: | 180 | default: |
181 | DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, | 181 | DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, |
@@ -197,18 +197,15 @@ pptp_outbound_pkt(struct sk_buff **pskb, | |||
197 | 197 | ||
198 | /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass | 198 | /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass |
199 | * down to here */ | 199 | * down to here */ |
200 | |||
201 | IP_NF_ASSERT(cid); | ||
202 | |||
203 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", | 200 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", |
204 | ntohs(*cid), ntohs(new_callid)); | 201 | ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid)); |
205 | 202 | ||
206 | /* mangle packet */ | 203 | /* mangle packet */ |
207 | if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 204 | if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, |
208 | (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), | 205 | cid_off + sizeof(struct pptp_pkt_hdr) + |
209 | sizeof(new_callid), | 206 | sizeof(struct PptpControlHeader), |
210 | (char *)&new_callid, | 207 | sizeof(new_callid), (char *)&new_callid, |
211 | sizeof(new_callid)) == 0) | 208 | sizeof(new_callid)) == 0) |
212 | return NF_DROP; | 209 | return NF_DROP; |
213 | 210 | ||
214 | return NF_ACCEPT; | 211 | return NF_ACCEPT; |
@@ -299,7 +296,8 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
299 | union pptp_ctrl_union *pptpReq) | 296 | union pptp_ctrl_union *pptpReq) |
300 | { | 297 | { |
301 | struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; | 298 | struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; |
302 | u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL; | 299 | u_int16_t msg, new_cid = 0, new_pcid; |
300 | unsigned int pcid_off, cid_off = 0; | ||
303 | 301 | ||
304 | int ret = NF_ACCEPT, rv; | 302 | int ret = NF_ACCEPT, rv; |
305 | 303 | ||
@@ -307,23 +305,23 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
307 | 305 | ||
308 | switch (msg = ntohs(ctlh->messageType)) { | 306 | switch (msg = ntohs(ctlh->messageType)) { |
309 | case PPTP_OUT_CALL_REPLY: | 307 | case PPTP_OUT_CALL_REPLY: |
310 | pcid = &pptpReq->ocack.peersCallID; | 308 | pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID); |
311 | cid = &pptpReq->ocack.callID; | 309 | cid_off = offsetof(union pptp_ctrl_union, ocack.callID); |
312 | break; | 310 | break; |
313 | case PPTP_IN_CALL_CONNECT: | 311 | case PPTP_IN_CALL_CONNECT: |
314 | pcid = &pptpReq->iccon.peersCallID; | 312 | pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID); |
315 | break; | 313 | break; |
316 | case PPTP_IN_CALL_REQUEST: | 314 | case PPTP_IN_CALL_REQUEST: |
317 | /* only need to nat in case PAC is behind NAT box */ | 315 | /* only need to nat in case PAC is behind NAT box */ |
318 | return NF_ACCEPT; | 316 | return NF_ACCEPT; |
319 | case PPTP_WAN_ERROR_NOTIFY: | 317 | case PPTP_WAN_ERROR_NOTIFY: |
320 | pcid = &pptpReq->wanerr.peersCallID; | 318 | pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID); |
321 | break; | 319 | break; |
322 | case PPTP_CALL_DISCONNECT_NOTIFY: | 320 | case PPTP_CALL_DISCONNECT_NOTIFY: |
323 | pcid = &pptpReq->disc.callID; | 321 | pcid_off = offsetof(union pptp_ctrl_union, disc.callID); |
324 | break; | 322 | break; |
325 | case PPTP_SET_LINK_INFO: | 323 | case PPTP_SET_LINK_INFO: |
326 | pcid = &pptpReq->setlink.peersCallID; | 324 | pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID); |
327 | break; | 325 | break; |
328 | 326 | ||
329 | default: | 327 | default: |
@@ -345,25 +343,24 @@ pptp_inbound_pkt(struct sk_buff **pskb, | |||
345 | * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ | 343 | * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ |
346 | 344 | ||
347 | /* mangle packet */ | 345 | /* mangle packet */ |
348 | IP_NF_ASSERT(pcid); | ||
349 | DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", | 346 | DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", |
350 | ntohs(*pcid), ntohs(new_pcid)); | 347 | ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid)); |
351 | 348 | ||
352 | rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 349 | rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, |
353 | (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), | 350 | pcid_off + sizeof(struct pptp_pkt_hdr) + |
351 | sizeof(struct PptpControlHeader), | ||
354 | sizeof(new_pcid), (char *)&new_pcid, | 352 | sizeof(new_pcid), (char *)&new_pcid, |
355 | sizeof(new_pcid)); | 353 | sizeof(new_pcid)); |
356 | if (rv != NF_ACCEPT) | 354 | if (rv != NF_ACCEPT) |
357 | return rv; | 355 | return rv; |
358 | 356 | ||
359 | if (new_cid) { | 357 | if (new_cid) { |
360 | IP_NF_ASSERT(cid); | ||
361 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", | 358 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", |
362 | ntohs(*cid), ntohs(new_cid)); | 359 | ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid)); |
363 | rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, | 360 | rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, |
364 | (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), | 361 | cid_off + sizeof(struct pptp_pkt_hdr) + |
365 | sizeof(new_cid), | 362 | sizeof(struct PptpControlHeader), |
366 | (char *)&new_cid, | 363 | sizeof(new_cid), (char *)&new_cid, |
367 | sizeof(new_cid)); | 364 | sizeof(new_cid)); |
368 | if (rv != NF_ACCEPT) | 365 | if (rv != NF_ACCEPT) |
369 | return rv; | 366 | return rv; |