Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -3690,6 +3690,18 @@ skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer)
skb_headlen(skb), buffer);
}

/* Variant of skb_header_pointer() where @offset is user-controlled
* and potentially negative.
*/
static inline void * __must_check
skb_header_pointer_careful(const struct sk_buff *skb, int offset,
int len, void *buffer)
{
if (unlikely(offset < 0 && -offset > skb_headroom(skb)))
return NULL;
return skb_header_pointer(skb, offset, len, buffer);
}

/**
* skb_needs_linearize - check if we need to linearize a given skb
* depending on the given device features.
Expand Down
13 changes: 6 additions & 7 deletions net/sched/cls_u32.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,8 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
int toff = off + key->off + (off2 & key->offmask);
__be32 *data, hdata;

if (skb_headroom(skb) + toff > INT_MAX)
goto out;

data = skb_header_pointer(skb, toff, 4, &hdata);
data = skb_header_pointer_careful(skb, toff, 4,
&hdata);
if (!data)
goto out;
if ((*data ^ key->val) & key->mask) {
Expand Down Expand Up @@ -206,8 +204,9 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
if (ht->divisor) {
__be32 *data, hdata;

data = skb_header_pointer(skb, off + n->sel.hoff, 4,
&hdata);
data = skb_header_pointer_careful(skb,
off + n->sel.hoff,
4, &hdata);
if (!data)
goto out;
sel = ht->divisor & u32_hash_fold(*data, &n->sel,
Expand All @@ -221,7 +220,7 @@ static int u32_classify(struct sk_buff *skb, const struct tcf_proto *tp,
if (n->sel.flags & TC_U32_VAROFFSET) {
__be16 *data, hdata;

data = skb_header_pointer(skb,
data = skb_header_pointer_careful(skb,
off + n->sel.offoff,
2, &hdata);
if (!data)
Expand Down
26 changes: 13 additions & 13 deletions net/smc/smc_clc.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,26 +305,26 @@ static int smc_clc_prfx_match6_rcu(struct net_device *dev,
int smc_clc_prfx_match(struct socket *clcsock,
struct smc_clc_msg_proposal_prefix *prop)
{
struct dst_entry *dst = sk_dst_get(clcsock->sk);
struct net_device *dev;
struct dst_entry *dst;
int rc;

if (!dst) {
rc = -ENOTCONN;
goto out;
}
if (!dst->dev) {
rcu_read_lock();

dst = __sk_dst_get(clcsock->sk);
dev = dst ? dst_dev_rcu(dst) : NULL;
if (!dev) {
rc = -ENODEV;
goto out_rel;
goto out;
}
rcu_read_lock();

if (!prop->ipv6_prefixes_cnt)
rc = smc_clc_prfx_match4_rcu(dst->dev, prop);
rc = smc_clc_prfx_match4_rcu(dev, prop);
else
rc = smc_clc_prfx_match6_rcu(dst->dev, prop);
rcu_read_unlock();
out_rel:
dst_release(dst);
rc = smc_clc_prfx_match6_rcu(dev, prop);
out:
rcu_read_unlock();

return rc;
}

Expand Down
Loading