From: Chris Wright Date: Wed, 11 Jan 2006 07:01:54 +0000 (-0800) Subject: pptp nat helper fixes from Patrick McHardy X-Git-Tag: v2.6.14.7~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=743e547d608e03bc4fb1754fae422ba63a8ed223;p=thirdparty%2Fkernel%2Fstable-queue.git pptp nat helper fixes from Patrick McHardy --- diff --git a/queue/netfilter-fix-another-crash-in-ip_nat_pptp.patch b/queue/netfilter-fix-another-crash-in-ip_nat_pptp.patch new file mode 100644 index 00000000000..1420c531d27 --- /dev/null +++ b/queue/netfilter-fix-another-crash-in-ip_nat_pptp.patch @@ -0,0 +1,152 @@ +From stable-bounces@linux.kernel.org Mon Jan 9 17:04:42 2006 +Message-ID: <43C30717.8030205@trash.net> +Date: Tue, 10 Jan 2006 02:00:07 +0100 +From: Patrick McHardy +To: stable@kernel.org +Cc: +Subject: [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 +Signed-off-by: Chris Wright +--- + net/ipv4/netfilter/ip_nat_helper_pptp.c | 57 +++++++++++++++----------------- + 1 file changed, 27 insertions(+), 30 deletions(-) + +--- linux-2.6.15.y.orig/net/ipv4/netfilter/ip_nat_helper_pptp.c ++++ linux-2.6.15.y/net/ipv4/netfilter/ip_nat_helper_pptp.c +@@ -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 +@@ -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, +@@ -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; +@@ -299,7 +296,8 @@ 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; + +@@ -307,23 +305,23 @@ pptp_inbound_pkt(struct sk_buff **pskb, + + 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: +@@ -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; diff --git a/queue/netfilter-fix-crash-in-ip_nat_pptp.patch b/queue/netfilter-fix-crash-in-ip_nat_pptp.patch new file mode 100644 index 00000000000..682e1d99b12 --- /dev/null +++ b/queue/netfilter-fix-crash-in-ip_nat_pptp.patch @@ -0,0 +1,30 @@ +From stable-bounces@linux.kernel.org Mon Jan 9 17:04:42 2006 +Message-ID: <43C30717.8030205@trash.net> +Date: Tue, 10 Jan 2006 02:00:07 +0100 +From: Patrick McHardy +To: stable@kernel.org +Cc: +Subject: [NETFILTER]: Fix crash in ip_nat_pptp + +When an inbound PPTP_IN_CALL_REQUEST packet is received the +PPTP NAT helper uses a NULL pointer in pointer arithmentic to +calculate the offset in the packet which needs to be mangled +and corrupts random memory or crashes. + +Signed-off-by: Patrick McHardy +Signed-off-by: Chris Wright +--- + net/ipv4/netfilter/ip_nat_helper_pptp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- linux-2.6.15.y.orig/net/ipv4/netfilter/ip_nat_helper_pptp.c ++++ linux-2.6.15.y/net/ipv4/netfilter/ip_nat_helper_pptp.c +@@ -315,7 +315,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, + break; + case PPTP_IN_CALL_REQUEST: + /* only need to nat in case PAC is behind NAT box */ +- break; ++ return NF_ACCEPT; + case PPTP_WAN_ERROR_NOTIFY: + pcid = &pptpReq->wanerr.peersCallID; + break; diff --git a/queue/series b/queue/series index ac7f2baee4f..2779d42c440 100644 --- a/queue/series +++ b/queue/series @@ -6,3 +6,5 @@ ppc32-re-add-embed_configc-to-ml300-ep405.patch vgacon-fix-doublescan-mode.patch fix-workqueue-oops-during-cpu-offline.patch netlink-oops-fix-due-to-incorrect-error-code.patch +netfilter-fix-crash-in-ip_nat_pptp.patch +netfilter-fix-another-crash-in-ip_nat_pptp.patch