forked from Minki/linux
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== The following patchset contains four netfilter fixes, they are: * Fix possible invalid access and mangling of the TCPMSS option in xt_TCPMSS. This was spotted by Julian Anastasov. * Fix possible off by one access and mangling of the TCP packet in xt_TCPOPTSTRIP, also spotted by Julian Anastasov. * Fix possible information leak due to missing initialization of one padding field of several structures that are included in nfqueue and nflog netlink messages, from Dan Carpenter. * Fix TCP window tracking with Fast Open, from Yuchung Cheng. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4209423c29
@ -526,7 +526,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
|
||||
const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple;
|
||||
__u32 seq, ack, sack, end, win, swin;
|
||||
s16 receiver_offset;
|
||||
bool res;
|
||||
bool res, in_recv_win;
|
||||
|
||||
/*
|
||||
* Get the required data from the packet.
|
||||
@ -649,14 +649,18 @@ static bool tcp_in_window(const struct nf_conn *ct,
|
||||
receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
|
||||
receiver->td_scale);
|
||||
|
||||
/* Is the ending sequence in the receive window (if available)? */
|
||||
in_recv_win = !receiver->td_maxwin ||
|
||||
after(end, sender->td_end - receiver->td_maxwin - 1);
|
||||
|
||||
pr_debug("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
|
||||
before(seq, sender->td_maxend + 1),
|
||||
after(end, sender->td_end - receiver->td_maxwin - 1),
|
||||
(in_recv_win ? 1 : 0),
|
||||
before(sack, receiver->td_end + 1),
|
||||
after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1));
|
||||
|
||||
if (before(seq, sender->td_maxend + 1) &&
|
||||
after(end, sender->td_end - receiver->td_maxwin - 1) &&
|
||||
in_recv_win &&
|
||||
before(sack, receiver->td_end + 1) &&
|
||||
after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1)) {
|
||||
/*
|
||||
@ -725,7 +729,7 @@ static bool tcp_in_window(const struct nf_conn *ct,
|
||||
nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
|
||||
"nf_ct_tcp: %s ",
|
||||
before(seq, sender->td_maxend + 1) ?
|
||||
after(end, sender->td_end - receiver->td_maxwin - 1) ?
|
||||
in_recv_win ?
|
||||
before(sack, receiver->td_end + 1) ?
|
||||
after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG"
|
||||
: "ACK is under the lower bound (possible overly delayed ACK)"
|
||||
|
@ -419,6 +419,7 @@ __build_packet_message(struct nfnl_log_net *log,
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(inst->group_num);
|
||||
|
||||
memset(&pmsg, 0, sizeof(pmsg));
|
||||
pmsg.hw_protocol = skb->protocol;
|
||||
pmsg.hook = hooknum;
|
||||
|
||||
@ -498,7 +499,10 @@ __build_packet_message(struct nfnl_log_net *log,
|
||||
if (indev && skb->dev &&
|
||||
skb->mac_header != skb->network_header) {
|
||||
struct nfulnl_msg_packet_hw phw;
|
||||
int len = dev_parse_header(skb, phw.hw_addr);
|
||||
int len;
|
||||
|
||||
memset(&phw, 0, sizeof(phw));
|
||||
len = dev_parse_header(skb, phw.hw_addr);
|
||||
if (len > 0) {
|
||||
phw.hw_addrlen = htons(len);
|
||||
if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw))
|
||||
|
@ -463,7 +463,10 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
|
||||
if (indev && entskb->dev &&
|
||||
entskb->mac_header != entskb->network_header) {
|
||||
struct nfqnl_msg_packet_hw phw;
|
||||
int len = dev_parse_header(entskb, phw.hw_addr);
|
||||
int len;
|
||||
|
||||
memset(&phw, 0, sizeof(phw));
|
||||
len = dev_parse_header(entskb, phw.hw_addr);
|
||||
if (len) {
|
||||
phw.hw_addrlen = htons(len);
|
||||
if (nla_put(skb, NFQA_HWADDR, sizeof(phw), &phw))
|
||||
|
@ -52,7 +52,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
||||
{
|
||||
const struct xt_tcpmss_info *info = par->targinfo;
|
||||
struct tcphdr *tcph;
|
||||
unsigned int tcplen, i;
|
||||
int len, tcp_hdrlen;
|
||||
unsigned int i;
|
||||
__be16 oldval;
|
||||
u16 newmss;
|
||||
u8 *opt;
|
||||
@ -64,11 +65,14 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
||||
if (!skb_make_writable(skb, skb->len))
|
||||
return -1;
|
||||
|
||||
tcplen = skb->len - tcphoff;
|
||||
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
|
||||
len = skb->len - tcphoff;
|
||||
if (len < (int)sizeof(struct tcphdr))
|
||||
return -1;
|
||||
|
||||
/* Header cannot be larger than the packet */
|
||||
if (tcplen < tcph->doff*4)
|
||||
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
|
||||
tcp_hdrlen = tcph->doff * 4;
|
||||
|
||||
if (len < tcp_hdrlen)
|
||||
return -1;
|
||||
|
||||
if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
|
||||
@ -87,9 +91,8 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
||||
newmss = info->mss;
|
||||
|
||||
opt = (u_int8_t *)tcph;
|
||||
for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) {
|
||||
if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS &&
|
||||
opt[i+1] == TCPOLEN_MSS) {
|
||||
for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) {
|
||||
if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) {
|
||||
u_int16_t oldmss;
|
||||
|
||||
oldmss = (opt[i+2] << 8) | opt[i+3];
|
||||
@ -112,9 +115,10 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
/* There is data after the header so the option can't be added
|
||||
without moving it, and doing so may make the SYN packet
|
||||
itself too large. Accept the packet unmodified instead. */
|
||||
if (tcplen > tcph->doff*4)
|
||||
* without moving it, and doing so may make the SYN packet
|
||||
* itself too large. Accept the packet unmodified instead.
|
||||
*/
|
||||
if (len > tcp_hdrlen)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -143,10 +147,10 @@ tcpmss_mangle_packet(struct sk_buff *skb,
|
||||
newmss = min(newmss, (u16)1220);
|
||||
|
||||
opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
|
||||
memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
|
||||
memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr));
|
||||
|
||||
inet_proto_csum_replace2(&tcph->check, skb,
|
||||
htons(tcplen), htons(tcplen + TCPOLEN_MSS), 1);
|
||||
htons(len), htons(len + TCPOLEN_MSS), 1);
|
||||
opt[0] = TCPOPT_MSS;
|
||||
opt[1] = TCPOLEN_MSS;
|
||||
opt[2] = (newmss & 0xff00) >> 8;
|
||||
|
@ -38,7 +38,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
|
||||
struct tcphdr *tcph;
|
||||
u_int16_t n, o;
|
||||
u_int8_t *opt;
|
||||
int len;
|
||||
int len, tcp_hdrlen;
|
||||
|
||||
/* This is a fragment, no TCP header is available */
|
||||
if (par->fragoff != 0)
|
||||
@ -52,7 +52,9 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
|
||||
return NF_DROP;
|
||||
|
||||
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
|
||||
if (tcph->doff * 4 > len)
|
||||
tcp_hdrlen = tcph->doff * 4;
|
||||
|
||||
if (len < tcp_hdrlen)
|
||||
return NF_DROP;
|
||||
|
||||
opt = (u_int8_t *)tcph;
|
||||
@ -61,10 +63,10 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
|
||||
* Walk through all TCP options - if we find some option to remove,
|
||||
* set all octets to %TCPOPT_NOP and adjust checksum.
|
||||
*/
|
||||
for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) {
|
||||
for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) {
|
||||
optl = optlen(opt, i);
|
||||
|
||||
if (i + optl > tcp_hdrlen(skb))
|
||||
if (i + optl > tcp_hdrlen)
|
||||
break;
|
||||
|
||||
if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))
|
||||
|
Loading…
Reference in New Issue
Block a user