Skip to content

Commit

Permalink
[NETFILTER]: Fix another crash in ip_nat_pptp
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
kaber authored and David S. Miller committed Jan 10, 2006
1 parent 15db347 commit 03b9fec
Showing 1 changed file with 27 additions and 30 deletions.
57 changes: 27 additions & 30 deletions net/ipv4/netfilter/ip_nat_helper_pptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@ pptp_outbound_pkt(struct sk_buff **pskb,
{
struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;

u_int16_t msg, *cid = NULL, new_callid;
u_int16_t msg, new_callid;
unsigned int cid_off;

new_callid = htons(ct_pptp_info->pns_call_id);

switch (msg = ntohs(ctlh->messageType)) {
case PPTP_OUT_CALL_REQUEST:
cid = &pptpReq->ocreq.callID;
cid_off = offsetof(union pptp_ctrl_union, ocreq.callID);
/* FIXME: ideally we would want to reserve a call ID
* here. current netfilter NAT core is not able to do
* this :( For now we use TCP source port. This breaks
Expand All @@ -172,10 +172,10 @@ pptp_outbound_pkt(struct sk_buff **pskb,
ct_pptp_info->pns_call_id = ntohs(new_callid);
break;
case PPTP_IN_CALL_REPLY:
cid = &pptpReq->icreq.callID;
cid_off = offsetof(union pptp_ctrl_union, icreq.callID);
break;
case PPTP_CALL_CLEAR_REQUEST:
cid = &pptpReq->clrreq.callID;
cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
break;
default:
DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
Expand All @@ -197,18 +197,15 @@ pptp_outbound_pkt(struct sk_buff **pskb,

/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
* down to here */

IP_NF_ASSERT(cid);

DEBUGP("altering call id from 0x%04x to 0x%04x\n",
ntohs(*cid), ntohs(new_callid));
ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid));

/* mangle packet */
if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
(void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
sizeof(new_callid),
(char *)&new_callid,
sizeof(new_callid)) == 0)
cid_off + sizeof(struct pptp_pkt_hdr) +
sizeof(struct PptpControlHeader),
sizeof(new_callid), (char *)&new_callid,
sizeof(new_callid)) == 0)
return NF_DROP;

return NF_ACCEPT;
Expand Down Expand Up @@ -299,31 +296,32 @@ pptp_inbound_pkt(struct sk_buff **pskb,
union pptp_ctrl_union *pptpReq)
{
struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
u_int16_t msg, new_cid = 0, new_pcid;
unsigned int pcid_off, cid_off = 0;

int ret = NF_ACCEPT, rv;

new_pcid = htons(nat_pptp_info->pns_call_id);

switch (msg = ntohs(ctlh->messageType)) {
case PPTP_OUT_CALL_REPLY:
pcid = &pptpReq->ocack.peersCallID;
cid = &pptpReq->ocack.callID;
pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID);
cid_off = offsetof(union pptp_ctrl_union, ocack.callID);
break;
case PPTP_IN_CALL_CONNECT:
pcid = &pptpReq->iccon.peersCallID;
pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID);
break;
case PPTP_IN_CALL_REQUEST:
/* only need to nat in case PAC is behind NAT box */
return NF_ACCEPT;
case PPTP_WAN_ERROR_NOTIFY:
pcid = &pptpReq->wanerr.peersCallID;
pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID);
break;
case PPTP_CALL_DISCONNECT_NOTIFY:
pcid = &pptpReq->disc.callID;
pcid_off = offsetof(union pptp_ctrl_union, disc.callID);
break;
case PPTP_SET_LINK_INFO:
pcid = &pptpReq->setlink.peersCallID;
pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
break;

default:
Expand All @@ -345,25 +343,24 @@ pptp_inbound_pkt(struct sk_buff **pskb,
* WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */

/* mangle packet */
IP_NF_ASSERT(pcid);
DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
ntohs(*pcid), ntohs(new_pcid));
ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid));

rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
(void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
pcid_off + sizeof(struct pptp_pkt_hdr) +
sizeof(struct PptpControlHeader),
sizeof(new_pcid), (char *)&new_pcid,
sizeof(new_pcid));
if (rv != NF_ACCEPT)
return rv;

if (new_cid) {
IP_NF_ASSERT(cid);
DEBUGP("altering call id from 0x%04x to 0x%04x\n",
ntohs(*cid), ntohs(new_cid));
rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
(void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)),
sizeof(new_cid),
(char *)&new_cid,
ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid));
rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
cid_off + sizeof(struct pptp_pkt_hdr) +
sizeof(struct PptpControlHeader),
sizeof(new_cid), (char *)&new_cid,
sizeof(new_cid));
if (rv != NF_ACCEPT)
return rv;
Expand Down

0 comments on commit 03b9fec

Please sign in to comment.