aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-01-09 19:44:00 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-10 15:54:32 -0500
commit03b9feca89366952ae5dfe4ad8107b1ece50b710 (patch)
tree401e94d15d3f28a759ce716b8b5a742f5d32a520 /net
parent15db34702cfafd24acc60295cf14861e497502ab (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.c57
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;