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
1 change: 1 addition & 0 deletions drivers/i2c/busses/i2c-designware-master.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,

dev->msgs = msgs;
dev->msgs_num = num_msgs;
dev->msg_write_idx = 0;
i2c_dw_xfer_init(dev);
i2c_dw_disable_int(dev);

Expand Down
6 changes: 6 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2470,6 +2470,12 @@ struct net *dev_net(const struct net_device *dev)
return read_pnet(&dev->nd_net);
}

static inline
struct net *dev_net_rcu(const struct net_device *dev)
{
return read_pnet_rcu(&dev->nd_net);
}

static inline
void dev_net_set(struct net_device *dev, struct net *net)
{
Expand Down
15 changes: 12 additions & 3 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,21 +348,30 @@ static inline void put_net_track(struct net *net, netns_tracker *tracker)

typedef struct {
#ifdef CONFIG_NET_NS
struct net *net;
struct net __rcu *net;
#endif
} possible_net_t;

static inline void write_pnet(possible_net_t *pnet, struct net *net)
{
#ifdef CONFIG_NET_NS
pnet->net = net;
rcu_assign_pointer(pnet->net, net);
#endif
}

static inline struct net *read_pnet(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
return pnet->net;
return rcu_dereference_protected(pnet->net, true);
#else
return &init_net;
#endif
}

static inline struct net *read_pnet_rcu(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
return rcu_dereference(pnet->net);
#else
return &init_net;
#endif
Expand Down
5 changes: 5 additions & 0 deletions net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
const unsigned char *dest;
u16 vid = 0;

if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) {
kfree_skb(skb);
return NETDEV_TX_OK;
}

memset(skb->cb, 0, sizeof(struct br_input_skb_cb));

rcu_read_lock();
Expand Down
34 changes: 20 additions & 14 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -4101,21 +4101,20 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
skb_frag_t *frag = skb_shinfo(head_skb)->frags;
unsigned int mss = skb_shinfo(head_skb)->gso_size;
unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
struct sk_buff *frag_skb = head_skb;
unsigned int offset = doffset;
unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
unsigned int partial_segs = 0;
unsigned int headroom;
unsigned int len = head_skb->len;
struct sk_buff *frag_skb;
skb_frag_t *frag;
__be16 proto;
bool csum, sg;
int nfrags = skb_shinfo(head_skb)->nr_frags;
int err = -ENOMEM;
int i = 0;
int pos;
int nfrags, pos;

if ((skb_shinfo(head_skb)->gso_type & SKB_GSO_DODGY) &&
mss != GSO_BY_FRAGS && mss != skb_headlen(head_skb)) {
Expand Down Expand Up @@ -4192,6 +4191,13 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
headroom = skb_headroom(head_skb);
pos = skb_headlen(head_skb);

if (skb_orphan_frags(head_skb, GFP_ATOMIC))
return ERR_PTR(-ENOMEM);

nfrags = skb_shinfo(head_skb)->nr_frags;
frag = skb_shinfo(head_skb)->frags;
frag_skb = head_skb;

do {
struct sk_buff *nskb;
skb_frag_t *nskb_frag;
Expand All @@ -4212,6 +4218,10 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
(skb_headlen(list_skb) == len || sg)) {
BUG_ON(skb_headlen(list_skb) > len);

nskb = skb_clone(list_skb, GFP_ATOMIC);
if (unlikely(!nskb))
goto err;

i = 0;
nfrags = skb_shinfo(list_skb)->nr_frags;
frag = skb_shinfo(list_skb)->frags;
Expand All @@ -4230,12 +4240,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
frag++;
}

nskb = skb_clone(list_skb, GFP_ATOMIC);
list_skb = list_skb->next;

if (unlikely(!nskb))
goto err;

if (unlikely(pskb_trim(nskb, len))) {
kfree_skb(nskb);
goto err;
Expand Down Expand Up @@ -4312,12 +4318,16 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
skb_shinfo(nskb)->flags |= skb_shinfo(head_skb)->flags &
SKBFL_SHARED_FRAG;

if (skb_orphan_frags(frag_skb, GFP_ATOMIC) ||
skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC))
if (skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC))
goto err;

while (pos < offset + len) {
if (i >= nfrags) {
if (skb_orphan_frags(list_skb, GFP_ATOMIC) ||
skb_zerocopy_clone(nskb, list_skb,
GFP_ATOMIC))
goto err;

i = 0;
nfrags = skb_shinfo(list_skb)->nr_frags;
frag = skb_shinfo(list_skb)->frags;
Expand All @@ -4331,10 +4341,6 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
i--;
frag--;
}
if (skb_orphan_frags(frag_skb, GFP_ATOMIC) ||
skb_zerocopy_clone(nskb, frag_skb,
GFP_ATOMIC))
goto err;

list_skb = list_skb->next;
}
Expand Down
10 changes: 4 additions & 6 deletions net/ipv6/ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,15 +414,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
{
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
struct sk_buff *skb;

skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
if (!skb) {
ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
__func__);
if (!skb)
return NULL;
}

skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev;
Expand All @@ -433,7 +429,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
/* Manually assign socket ownership as we avoid calling
* sock_alloc_send_pskb() to bypass wmem buffer limits
*/
skb_set_owner_w(skb, sk);
rcu_read_lock();
skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk);
rcu_read_unlock();

return skb;
}
Expand Down
3 changes: 1 addition & 2 deletions net/tls/tls_strp.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,8 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
if (inq < strp->stm.full_len)
return tls_strp_read_copy(strp, true);

tls_strp_load_anchor_with_queue(strp, inq);
if (!strp->stm.full_len) {
tls_strp_load_anchor_with_queue(strp, inq);

sz = tls_rx_msg_size(strp, strp->anchor);
if (sz < 0) {
tls_strp_abort_strp(strp, sz);
Expand Down