netfilter: tcpmss, optstrip: prefer skb_ensure_writable

This also changes optstrip to only make the tcp header writeable
rather than the entire packet.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal 2019-05-23 15:44:11 +02:00 committed by Pablo Neira Ayuso
parent 8e03707f11
commit fb2eb1c131
2 changed files with 15 additions and 17 deletions

View file

@ -89,7 +89,7 @@ tcpmss_mangle_packet(struct sk_buff *skb,
if (par->fragoff != 0) if (par->fragoff != 0)
return 0; return 0;
if (!skb_make_writable(skb, skb->len)) if (skb_ensure_writable(skb, skb->len))
return -1; return -1;
len = skb->len - tcphoff; len = skb->len - tcphoff;

View file

@ -31,33 +31,33 @@ static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset)
static unsigned int static unsigned int
tcpoptstrip_mangle_packet(struct sk_buff *skb, tcpoptstrip_mangle_packet(struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
unsigned int tcphoff, unsigned int minlen) unsigned int tcphoff)
{ {
const struct xt_tcpoptstrip_target_info *info = par->targinfo; const struct xt_tcpoptstrip_target_info *info = par->targinfo;
struct tcphdr *tcph, _th;
unsigned int optl, i, j; unsigned int optl, i, j;
struct tcphdr *tcph;
u_int16_t n, o; u_int16_t n, o;
u_int8_t *opt; u_int8_t *opt;
int len, tcp_hdrlen; int tcp_hdrlen;
/* This is a fragment, no TCP header is available */ /* This is a fragment, no TCP header is available */
if (par->fragoff != 0) if (par->fragoff != 0)
return XT_CONTINUE; return XT_CONTINUE;
if (!skb_make_writable(skb, skb->len)) tcph = skb_header_pointer(skb, tcphoff, sizeof(_th), &_th);
if (!tcph)
return NF_DROP; return NF_DROP;
len = skb->len - tcphoff;
if (len < (int)sizeof(struct tcphdr))
return NF_DROP;
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
tcp_hdrlen = tcph->doff * 4; tcp_hdrlen = tcph->doff * 4;
if (tcp_hdrlen < sizeof(struct tcphdr))
if (len < tcp_hdrlen)
return NF_DROP; return NF_DROP;
opt = (u_int8_t *)tcph; if (skb_ensure_writable(skb, tcphoff + tcp_hdrlen))
return NF_DROP;
/* must reload tcph, might have been moved */
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
opt = (u8 *)tcph;
/* /*
* Walk through all TCP options - if we find some option to remove, * Walk through all TCP options - if we find some option to remove,
@ -91,8 +91,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
static unsigned int static unsigned int
tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par)
{ {
return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb), return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb));
sizeof(struct iphdr) + sizeof(struct tcphdr));
} }
#if IS_ENABLED(CONFIG_IP6_NF_MANGLE) #if IS_ENABLED(CONFIG_IP6_NF_MANGLE)
@ -109,8 +108,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par)
if (tcphoff < 0) if (tcphoff < 0)
return NF_DROP; return NF_DROP;
return tcpoptstrip_mangle_packet(skb, par, tcphoff, return tcpoptstrip_mangle_packet(skb, par, tcphoff);
sizeof(*ipv6h) + sizeof(struct tcphdr));
} }
#endif #endif