Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Pull networking fixes from David Miller:

 1) Fix IGMP handling wrt VRF, from David Ahern.

 2) Fix timer access to freed object in dccp, from Eric Dumazet.

 3) Use kmalloc_array() in ptr_ring to avoid overflow cases which are
    triggerable by userspace. Also from Eric Dumazet.

 4) Fix infinite loop in unmapping cleanup of nfp driver, from Colin Ian
    King.

 5) Correct datagram peek handling of empty SKBs, from Matthew Dawson.

 6) Fix use after free in TIPC, from Eric Dumazet.

 7) When replacing a route in ipv6 we need to reset the round robin
    pointer, from Wei Wang.

 8) Fix bug in pci_find_pcie_root_port() which was unearthed by the
    relaxed ordering changes, from Thierry Redding. I made sure to get
    an explicit ACK from Bjorn this time around :-)

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (27 commits)
  ipv6: repair fib6 tree in failure case
  net_sched: fix order of queue length updates in qdisc_replace()
  tools lib bpf: improve warning
  switchdev: documentation: minor typo fixes
  bpf, doc: also add s390x as arch to sysctl description
  net: sched: fix NULL pointer dereference when action calls some targets
  rxrpc: Fix oops when discarding a preallocated service call
  irda: do not leak initialized list.dev to userspace
  net/mlx4_core: Enable 4K UAR if SRIOV module parameter is not enabled
  PCI: Allow PCI express root ports to find themselves
  tcp: when rearming RTO, if RTO time is in past then fire RTO ASAP
  net: check and errout if res->fi is NULL when RTM_F_FIB_MATCH is set
  ipv6: reset fn->rr_ptr when replacing route
  sctp: fully initialize the IPv6 address in sctp_v6_to_addr()
  tipc: fix use-after-free
  tun: handle register_netdevice() failures properly
  datagram: When peeking datagrams with offset < 0 don't skip empty skbs
  bpf, doc: improve sysctl knob description
  netxen: fix incorrect loop counter decrement
  nfp: fix infinite loop on umapping cleanup
  ...
This commit is contained in:
Linus Torvalds 2017-08-21 13:16:27 -07:00
commit e3181f2c0c
31 changed files with 144 additions and 72 deletions

View File

@ -228,7 +228,7 @@ Learning on the device port should be enabled, as well as learning_sync:
bridge link set dev DEV learning on self bridge link set dev DEV learning on self
bridge link set dev DEV learning_sync on self bridge link set dev DEV learning_sync on self
Learning_sync attribute enables syncing of the learned/forgotton FDB entry to Learning_sync attribute enables syncing of the learned/forgotten FDB entry to
the bridge's FDB. It's possible, but not optimal, to enable learning on the the bridge's FDB. It's possible, but not optimal, to enable learning on the
device port and on the bridge port, and disable learning_sync. device port and on the bridge port, and disable learning_sync.
@ -245,7 +245,7 @@ the responsibility of the port driver/device to age out these entries. If the
port device supports ageing, when the FDB entry expires, it will notify the port device supports ageing, when the FDB entry expires, it will notify the
driver which in turn will notify the bridge with SWITCHDEV_FDB_DEL. If the driver which in turn will notify the bridge with SWITCHDEV_FDB_DEL. If the
device does not support ageing, the driver can simulate ageing using a device does not support ageing, the driver can simulate ageing using a
garbage collection timer to monitor FBD entries. Expired entries will be garbage collection timer to monitor FDB entries. Expired entries will be
notified to the bridge using SWITCHDEV_FDB_DEL. See rocker driver for notified to the bridge using SWITCHDEV_FDB_DEL. See rocker driver for
example of driver running ageing timer. example of driver running ageing timer.

View File

@ -35,9 +35,34 @@ Table : Subdirectories in /proc/sys/net
bpf_jit_enable bpf_jit_enable
-------------- --------------
This enables Berkeley Packet Filter Just in Time compiler. This enables the BPF Just in Time (JIT) compiler. BPF is a flexible
Currently supported on x86_64 architecture, bpf_jit provides a framework and efficient infrastructure allowing to execute bytecode at various
to speed packet filtering, the one used by tcpdump/libpcap for example. hook points. It is used in a number of Linux kernel subsystems such
as networking (e.g. XDP, tc), tracing (e.g. kprobes, uprobes, tracepoints)
and security (e.g. seccomp). LLVM has a BPF back end that can compile
restricted C into a sequence of BPF instructions. After program load
through bpf(2) and passing a verifier in the kernel, a JIT will then
translate these BPF proglets into native CPU instructions. There are
two flavors of JITs, the newer eBPF JIT currently supported on:
- x86_64
- arm64
- ppc64
- sparc64
- mips64
- s390x
And the older cBPF JIT supported on the following archs:
- arm
- mips
- ppc
- sparc
eBPF JITs are a superset of cBPF JITs, meaning the kernel will
migrate cBPF instructions into eBPF instructions and then JIT
compile them transparently. Older cBPF JITs can only translate
tcpdump filters, seccomp rules, etc, but not mentioned eBPF
programs loaded through bpf(2).
Values : Values :
0 - disable the JIT (default value) 0 - disable the JIT (default value)
1 - enable the JIT 1 - enable the JIT
@ -46,9 +71,9 @@ Values :
bpf_jit_harden bpf_jit_harden
-------------- --------------
This enables hardening for the Berkeley Packet Filter Just in Time compiler. This enables hardening for the BPF JIT compiler. Supported are eBPF
Supported are eBPF JIT backends. Enabling hardening trades off performance, JIT backends. Enabling hardening trades off performance, but can
but can mitigate JIT spraying. mitigate JIT spraying.
Values : Values :
0 - disable JIT hardening (default value) 0 - disable JIT hardening (default value)
1 - enable JIT hardening for unprivileged users only 1 - enable JIT hardening for unprivileged users only
@ -57,11 +82,11 @@ Values :
bpf_jit_kallsyms bpf_jit_kallsyms
---------------- ----------------
When Berkeley Packet Filter Just in Time compiler is enabled, then compiled When BPF JIT compiler is enabled, then compiled images are unknown
images are unknown addresses to the kernel, meaning they neither show up in addresses to the kernel, meaning they neither show up in traces nor
traces nor in /proc/kallsyms. This enables export of these addresses, which in /proc/kallsyms. This enables export of these addresses, which can
can be used for debugging/tracing. If bpf_jit_harden is enabled, this feature be used for debugging/tracing. If bpf_jit_harden is enabled, this
is disabled. feature is disabled.
Values : Values :
0 - disable JIT kallsyms export (default value) 0 - disable JIT kallsyms export (default value)
1 - enable JIT kallsyms export for privileged users only 1 - enable JIT kallsyms export for privileged users only

View File

@ -432,7 +432,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
/* Virtual PCI function needs to determine UAR page size from /* Virtual PCI function needs to determine UAR page size from
* firmware. Only master PCI function can set the uar page size * firmware. Only master PCI function can set the uar page size
*/ */
if (enable_4k_uar) if (enable_4k_uar || !dev->persist->num_vfs)
dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT; dev->uar_page_shift = DEFAULT_UAR_PAGE_SHIFT;
else else
dev->uar_page_shift = PAGE_SHIFT; dev->uar_page_shift = PAGE_SHIFT;
@ -2277,7 +2277,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1; dev->caps.max_fmr_maps = (1 << (32 - ilog2(dev->caps.num_mpts))) - 1;
if (enable_4k_uar) { if (enable_4k_uar || !dev->persist->num_vfs) {
init_hca.log_uar_sz = ilog2(dev->caps.num_uars) + init_hca.log_uar_sz = ilog2(dev->caps.num_uars) +
PAGE_SHIFT - DEFAULT_UAR_PAGE_SHIFT; PAGE_SHIFT - DEFAULT_UAR_PAGE_SHIFT;
init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12; init_hca.uar_page_sz = DEFAULT_UAR_PAGE_SHIFT - 12;

View File

@ -908,8 +908,7 @@ static int nfp_net_tx(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
err_unmap: err_unmap:
--f; while (--f >= 0) {
while (f >= 0) {
frag = &skb_shinfo(skb)->frags[f]; frag = &skb_shinfo(skb)->frags[f];
dma_unmap_page(dp->dev, tx_ring->txbufs[wr_idx].dma_addr, dma_unmap_page(dp->dev, tx_ring->txbufs[wr_idx].dma_addr,
skb_frag_size(frag), DMA_TO_DEVICE); skb_frag_size(frag), DMA_TO_DEVICE);

View File

@ -2311,7 +2311,7 @@ netxen_md_rdqueue(struct netxen_adapter *adapter,
loop_cnt++) { loop_cnt++) {
NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id); NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id);
read_addr = queueEntry->read_addr; read_addr = queueEntry->read_addr;
for (k = 0; k < read_cnt; k--) { for (k = 0; k < read_cnt; k++) {
NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0,
&read_value); &read_value);
*data_buff++ = read_value; *data_buff++ = read_value;

View File

@ -1879,6 +1879,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
err_detach: err_detach:
tun_detach_all(dev); tun_detach_all(dev);
/* register_netdevice() already called tun_free_netdev() */
goto err_free_dev;
err_free_flow: err_free_flow:
tun_flow_uninit(tun); tun_flow_uninit(tun);
security_tun_dev_free_security(tun->security); security_tun_dev_free_security(tun->security);

View File

@ -514,7 +514,7 @@ EXPORT_SYMBOL(pci_find_resource);
*/ */
struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev) struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev)
{ {
struct pci_dev *bridge, *highest_pcie_bridge = NULL; struct pci_dev *bridge, *highest_pcie_bridge = dev;
bridge = pci_upstream_bridge(dev); bridge = pci_upstream_bridge(dev);
while (bridge && pci_is_pcie(bridge)) { while (bridge && pci_is_pcie(bridge)) {
@ -522,11 +522,10 @@ struct pci_dev *pci_find_pcie_root_port(struct pci_dev *dev)
bridge = pci_upstream_bridge(bridge); bridge = pci_upstream_bridge(bridge);
} }
if (highest_pcie_bridge && if (pci_pcie_type(highest_pcie_bridge) != PCI_EXP_TYPE_ROOT_PORT)
pci_pcie_type(highest_pcie_bridge) == PCI_EXP_TYPE_ROOT_PORT)
return highest_pcie_bridge;
return NULL; return NULL;
return highest_pcie_bridge;
} }
EXPORT_SYMBOL(pci_find_pcie_root_port); EXPORT_SYMBOL(pci_find_pcie_root_port);

View File

@ -436,9 +436,9 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r,
__PTR_RING_PEEK_CALL_v; \ __PTR_RING_PEEK_CALL_v; \
}) })
static inline void **__ptr_ring_init_queue_alloc(int size, gfp_t gfp) static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp)
{ {
return kzalloc(ALIGN(size * sizeof(void *), SMP_CACHE_BYTES), gfp); return kcalloc(size, sizeof(void *), gfp);
} }
static inline void __ptr_ring_set_size(struct ptr_ring *r, int size) static inline void __ptr_ring_set_size(struct ptr_ring *r, int size)
@ -582,7 +582,8 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp,
* In particular if you consume ring in interrupt or BH context, you must * In particular if you consume ring in interrupt or BH context, you must
* disable interrupts/BH when doing so. * disable interrupts/BH when doing so.
*/ */
static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, static inline int ptr_ring_resize_multiple(struct ptr_ring **rings,
unsigned int nrings,
int size, int size,
gfp_t gfp, void (*destroy)(void *)) gfp_t gfp, void (*destroy)(void *))
{ {
@ -590,7 +591,7 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings,
void ***queues; void ***queues;
int i; int i;
queues = kmalloc(nrings * sizeof *queues, gfp); queues = kmalloc_array(nrings, sizeof(*queues), gfp);
if (!queues) if (!queues)
goto noqueues; goto noqueues;

View File

@ -193,7 +193,8 @@ static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp)
} }
static inline int skb_array_resize_multiple(struct skb_array **rings, static inline int skb_array_resize_multiple(struct skb_array **rings,
int nrings, int size, gfp_t gfp) int nrings, unsigned int size,
gfp_t gfp)
{ {
BUILD_BUG_ON(offsetof(struct skb_array, ring)); BUILD_BUG_ON(offsetof(struct skb_array, ring));
return ptr_ring_resize_multiple((struct ptr_ring **)rings, return ptr_ring_resize_multiple((struct ptr_ring **)rings,

View File

@ -352,7 +352,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
!forwarding) !forwarding)
return dst_mtu(dst); return dst_mtu(dst);
return min(dst->dev->mtu, IP_MAX_MTU); return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
} }
static inline unsigned int ip_skb_dst_mtu(struct sock *sk, static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
@ -364,7 +364,7 @@ static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
} }
return min(skb_dst(skb)->dev->mtu, IP_MAX_MTU); return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
} }
u32 ip_idents_reserve(u32 hash, int segs); u32 ip_idents_reserve(u32 hash, int segs);

View File

@ -806,8 +806,11 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
old = *pold; old = *pold;
*pold = new; *pold = new;
if (old != NULL) { if (old != NULL) {
qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog); unsigned int qlen = old->q.qlen;
unsigned int backlog = old->qstats.backlog;
qdisc_reset(old); qdisc_reset(old);
qdisc_tree_reduce_backlog(old, qlen, backlog);
} }
sch_tree_unlock(sch); sch_tree_unlock(sch);

View File

@ -507,9 +507,7 @@ int sk_set_peek_off(struct sock *sk, int val);
static inline int sk_peek_offset(struct sock *sk, int flags) static inline int sk_peek_offset(struct sock *sk, int flags)
{ {
if (unlikely(flags & MSG_PEEK)) { if (unlikely(flags & MSG_PEEK)) {
s32 off = READ_ONCE(sk->sk_peek_off); return READ_ONCE(sk->sk_peek_off);
if (off >= 0)
return off;
} }
return 0; return 0;

View File

@ -169,14 +169,20 @@ struct sk_buff *__skb_try_recv_from_queue(struct sock *sk,
int *peeked, int *off, int *err, int *peeked, int *off, int *err,
struct sk_buff **last) struct sk_buff **last)
{ {
bool peek_at_off = false;
struct sk_buff *skb; struct sk_buff *skb;
int _off = *off; int _off = 0;
if (unlikely(flags & MSG_PEEK && *off >= 0)) {
peek_at_off = true;
_off = *off;
}
*last = queue->prev; *last = queue->prev;
skb_queue_walk(queue, skb) { skb_queue_walk(queue, skb) {
if (flags & MSG_PEEK) { if (flags & MSG_PEEK) {
if (_off >= skb->len && (skb->len || _off || if (peek_at_off && _off >= skb->len &&
skb->peeked)) { (_off || skb->peeked)) {
_off -= skb->len; _off -= skb->len;
continue; continue;
} }

View File

@ -24,6 +24,7 @@
#include <net/checksum.h> #include <net/checksum.h>
#include <net/inet_sock.h> #include <net/inet_sock.h>
#include <net/inet_common.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/xfrm.h> #include <net/xfrm.h>
@ -170,6 +171,15 @@ const char *dccp_packet_name(const int type)
EXPORT_SYMBOL_GPL(dccp_packet_name); EXPORT_SYMBOL_GPL(dccp_packet_name);
static void dccp_sk_destruct(struct sock *sk)
{
struct dccp_sock *dp = dccp_sk(sk);
ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
dp->dccps_hc_tx_ccid = NULL;
inet_sock_destruct(sk);
}
int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized) int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
{ {
struct dccp_sock *dp = dccp_sk(sk); struct dccp_sock *dp = dccp_sk(sk);
@ -179,6 +189,7 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
icsk->icsk_syn_retries = sysctl_dccp_request_retries; icsk->icsk_syn_retries = sysctl_dccp_request_retries;
sk->sk_state = DCCP_CLOSED; sk->sk_state = DCCP_CLOSED;
sk->sk_write_space = dccp_write_space; sk->sk_write_space = dccp_write_space;
sk->sk_destruct = dccp_sk_destruct;
icsk->icsk_sync_mss = dccp_sync_mss; icsk->icsk_sync_mss = dccp_sync_mss;
dp->dccps_mss_cache = 536; dp->dccps_mss_cache = 536;
dp->dccps_rate_last = jiffies; dp->dccps_rate_last = jiffies;
@ -219,8 +230,7 @@ void dccp_destroy_sock(struct sock *sk)
dp->dccps_hc_rx_ackvec = NULL; dp->dccps_hc_rx_ackvec = NULL;
} }
ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk); ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk); dp->dccps_hc_rx_ccid = NULL;
dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL;
/* clean up feature negotiation state */ /* clean up feature negotiation state */
dccp_feat_list_purge(&dp->dccps_featneg); dccp_feat_list_purge(&dp->dccps_featneg);

View File

@ -1007,10 +1007,18 @@ int igmp_rcv(struct sk_buff *skb)
{ {
/* This basically follows the spec line by line -- see RFC1112 */ /* This basically follows the spec line by line -- see RFC1112 */
struct igmphdr *ih; struct igmphdr *ih;
struct in_device *in_dev = __in_dev_get_rcu(skb->dev); struct net_device *dev = skb->dev;
struct in_device *in_dev;
int len = skb->len; int len = skb->len;
bool dropped = true; bool dropped = true;
if (netif_is_l3_master(dev)) {
dev = dev_get_by_index_rcu(dev_net(dev), IPCB(skb)->iif);
if (!dev)
goto drop;
}
in_dev = __in_dev_get_rcu(dev);
if (!in_dev) if (!in_dev)
goto drop; goto drop;

View File

@ -1267,7 +1267,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
if (mtu) if (mtu)
return mtu; return mtu;
mtu = dst->dev->mtu; mtu = READ_ONCE(dst->dev->mtu);
if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
if (rt->rt_uses_gateway && mtu > 576) if (rt->rt_uses_gateway && mtu > 576)
@ -2763,14 +2763,21 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE) if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE)
table_id = rt->rt_table_id; table_id = rt->rt_table_id;
if (rtm->rtm_flags & RTM_F_FIB_MATCH) if (rtm->rtm_flags & RTM_F_FIB_MATCH) {
if (!res.fi) {
err = fib_props[res.type].error;
if (!err)
err = -EHOSTUNREACH;
goto errout_free;
}
err = fib_dump_info(skb, NETLINK_CB(in_skb).portid, err = fib_dump_info(skb, NETLINK_CB(in_skb).portid,
nlh->nlmsg_seq, RTM_NEWROUTE, table_id, nlh->nlmsg_seq, RTM_NEWROUTE, table_id,
rt->rt_type, res.prefix, res.prefixlen, rt->rt_type, res.prefix, res.prefixlen,
fl4.flowi4_tos, res.fi, 0); fl4.flowi4_tos, res.fi, 0);
else } else {
err = rt_fill_info(net, dst, src, table_id, &fl4, skb, err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
NETLINK_CB(in_skb).portid, nlh->nlmsg_seq); NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
}
if (err < 0) if (err < 0)
goto errout_free; goto errout_free;

View File

@ -3009,8 +3009,7 @@ void tcp_rearm_rto(struct sock *sk)
/* delta_us may not be positive if the socket is locked /* delta_us may not be positive if the socket is locked
* when the retrans timer fires and is rescheduled. * when the retrans timer fires and is rescheduled.
*/ */
if (delta_us > 0) rto = usecs_to_jiffies(max_t(int, delta_us, 1));
rto = usecs_to_jiffies(delta_us);
} }
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto, inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, rto,
TCP_RTO_MAX); TCP_RTO_MAX);

View File

@ -1574,7 +1574,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
return ip_recv_error(sk, msg, len, addr_len); return ip_recv_error(sk, msg, len, addr_len);
try_again: try_again:
peeking = off = sk_peek_offset(sk, flags); peeking = flags & MSG_PEEK;
off = sk_peek_offset(sk, flags);
skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err); skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err);
if (!skb) if (!skb)
return err; return err;

View File

@ -914,6 +914,8 @@ add:
} }
nsiblings = iter->rt6i_nsiblings; nsiblings = iter->rt6i_nsiblings;
fib6_purge_rt(iter, fn, info->nl_net); fib6_purge_rt(iter, fn, info->nl_net);
if (fn->rr_ptr == iter)
fn->rr_ptr = NULL;
rt6_release(iter); rt6_release(iter);
if (nsiblings) { if (nsiblings) {
@ -926,6 +928,8 @@ add:
if (rt6_qualify_for_ecmp(iter)) { if (rt6_qualify_for_ecmp(iter)) {
*ins = iter->dst.rt6_next; *ins = iter->dst.rt6_next;
fib6_purge_rt(iter, fn, info->nl_net); fib6_purge_rt(iter, fn, info->nl_net);
if (fn->rr_ptr == iter)
fn->rr_ptr = NULL;
rt6_release(iter); rt6_release(iter);
nsiblings--; nsiblings--;
} else { } else {
@ -1014,7 +1018,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
/* Create subtree root node */ /* Create subtree root node */
sfn = node_alloc(); sfn = node_alloc();
if (!sfn) if (!sfn)
goto st_failure; goto failure;
sfn->leaf = info->nl_net->ipv6.ip6_null_entry; sfn->leaf = info->nl_net->ipv6.ip6_null_entry;
atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref); atomic_inc(&info->nl_net->ipv6.ip6_null_entry->rt6i_ref);
@ -1031,12 +1035,12 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
if (IS_ERR(sn)) { if (IS_ERR(sn)) {
/* If it is failed, discard just allocated /* If it is failed, discard just allocated
root, and then (in st_failure) stale node root, and then (in failure) stale node
in main tree. in main tree.
*/ */
node_free(sfn); node_free(sfn);
err = PTR_ERR(sn); err = PTR_ERR(sn);
goto st_failure; goto failure;
} }
/* Now link new subtree to main tree */ /* Now link new subtree to main tree */
@ -1051,7 +1055,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt,
if (IS_ERR(sn)) { if (IS_ERR(sn)) {
err = PTR_ERR(sn); err = PTR_ERR(sn);
goto st_failure; goto failure;
} }
} }
@ -1092,18 +1096,17 @@ out:
atomic_inc(&pn->leaf->rt6i_ref); atomic_inc(&pn->leaf->rt6i_ref);
} }
#endif #endif
/* Always release dst as dst->__refcnt is guaranteed goto failure;
* to be taken before entering this function
*/
dst_release_immediate(&rt->dst);
} }
return err; return err;
#ifdef CONFIG_IPV6_SUBTREES failure:
/* Subtree creation failed, probably main tree node /* fn->leaf could be NULL if fn is an intermediate node and we
is orphan. If it is, shoot it. * failed to add the new route to it in both subtree creation
* failure and fib6_add_rt2node() failure case.
* In both cases, fib6_repair_tree() should be called to fix
* fn->leaf.
*/ */
st_failure:
if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT))) if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
fib6_repair_tree(info->nl_net, fn); fib6_repair_tree(info->nl_net, fn);
/* Always release dst as dst->__refcnt is guaranteed /* Always release dst as dst->__refcnt is guaranteed
@ -1111,7 +1114,6 @@ st_failure:
*/ */
dst_release_immediate(&rt->dst); dst_release_immediate(&rt->dst);
return err; return err;
#endif
} }
/* /*

View File

@ -362,7 +362,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
return ipv6_recv_rxpmtu(sk, msg, len, addr_len); return ipv6_recv_rxpmtu(sk, msg, len, addr_len);
try_again: try_again:
peeking = off = sk_peek_offset(sk, flags); peeking = flags & MSG_PEEK;
off = sk_peek_offset(sk, flags);
skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err); skb = __skb_recv_udp(sk, flags, noblock, &peeked, &off, &err);
if (!skb) if (!skb)
return err; return err;

View File

@ -2213,7 +2213,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk); struct irda_sock *self = irda_sk(sk);
struct irda_device_list list; struct irda_device_list list = { 0 };
struct irda_device_info *discoveries; struct irda_device_info *discoveries;
struct irda_ias_set * ias_opt; /* IAS get/query params */ struct irda_ias_set * ias_opt; /* IAS get/query params */
struct ias_object * ias_obj; /* Object in IAS */ struct ias_object * ias_obj; /* Object in IAS */

View File

@ -1337,6 +1337,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
goto out; goto out;
} }
OVS_CB(skb)->acts_origlen = acts->orig_len;
err = do_execute_actions(dp, skb, key, err = do_execute_actions(dp, skb, key,
acts->actions, acts->actions_len); acts->actions, acts->actions_len);

View File

@ -381,7 +381,7 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
} }
static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info, static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
unsigned int hdrlen) unsigned int hdrlen, int actions_attrlen)
{ {
size_t size = NLMSG_ALIGN(sizeof(struct ovs_header)) size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
+ nla_total_size(hdrlen) /* OVS_PACKET_ATTR_PACKET */ + nla_total_size(hdrlen) /* OVS_PACKET_ATTR_PACKET */
@ -398,7 +398,7 @@ static size_t upcall_msg_size(const struct dp_upcall_info *upcall_info,
/* OVS_PACKET_ATTR_ACTIONS */ /* OVS_PACKET_ATTR_ACTIONS */
if (upcall_info->actions_len) if (upcall_info->actions_len)
size += nla_total_size(upcall_info->actions_len); size += nla_total_size(actions_attrlen);
/* OVS_PACKET_ATTR_MRU */ /* OVS_PACKET_ATTR_MRU */
if (upcall_info->mru) if (upcall_info->mru)
@ -465,7 +465,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
else else
hlen = skb->len; hlen = skb->len;
len = upcall_msg_size(upcall_info, hlen - cutlen); len = upcall_msg_size(upcall_info, hlen - cutlen,
OVS_CB(skb)->acts_origlen);
user_skb = genlmsg_new(len, GFP_ATOMIC); user_skb = genlmsg_new(len, GFP_ATOMIC);
if (!user_skb) { if (!user_skb) {
err = -ENOMEM; err = -ENOMEM;

View File

@ -99,11 +99,13 @@ struct datapath {
* when a packet is received by OVS. * when a packet is received by OVS.
* @mru: The maximum received fragement size; 0 if the packet is not * @mru: The maximum received fragement size; 0 if the packet is not
* fragmented. * fragmented.
* @acts_origlen: The netlink size of the flow actions applied to this skb.
* @cutlen: The number of bytes from the packet end to be removed. * @cutlen: The number of bytes from the packet end to be removed.
*/ */
struct ovs_skb_cb { struct ovs_skb_cb {
struct vport *input_vport; struct vport *input_vport;
u16 mru; u16 mru;
u16 acts_origlen;
u32 cutlen; u32 cutlen;
}; };
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb) #define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)

View File

@ -223,6 +223,7 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
tail = b->call_backlog_tail; tail = b->call_backlog_tail;
while (CIRC_CNT(head, tail, size) > 0) { while (CIRC_CNT(head, tail, size) > 0) {
struct rxrpc_call *call = b->call_backlog[tail]; struct rxrpc_call *call = b->call_backlog[tail];
call->socket = rx;
if (rx->discard_new_call) { if (rx->discard_new_call) {
_debug("discard %lx", call->user_call_ID); _debug("discard %lx", call->user_call_ID);
rx->discard_new_call(call, call->user_call_ID); rx->discard_new_call(call, call->user_call_ID);

View File

@ -41,6 +41,7 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
{ {
struct xt_tgchk_param par; struct xt_tgchk_param par;
struct xt_target *target; struct xt_target *target;
struct ipt_entry e = {};
int ret = 0; int ret = 0;
target = xt_request_find_target(AF_INET, t->u.user.name, target = xt_request_find_target(AF_INET, t->u.user.name,
@ -52,6 +53,7 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
memset(&par, 0, sizeof(par)); memset(&par, 0, sizeof(par));
par.net = net; par.net = net;
par.table = table; par.table = table;
par.entryinfo = &e;
par.target = target; par.target = target;
par.targinfo = t->data; par.targinfo = t->data;
par.hook_mask = hook; par.hook_mask = hook;

View File

@ -205,7 +205,7 @@ static void tcf_chain_flush(struct tcf_chain *chain)
{ {
struct tcf_proto *tp; struct tcf_proto *tp;
if (*chain->p_filter_chain) if (chain->p_filter_chain)
RCU_INIT_POINTER(*chain->p_filter_chain, NULL); RCU_INIT_POINTER(*chain->p_filter_chain, NULL);
while ((tp = rtnl_dereference(chain->filter_chain)) != NULL) { while ((tp = rtnl_dereference(chain->filter_chain)) != NULL) {
RCU_INIT_POINTER(chain->filter_chain, tp->next); RCU_INIT_POINTER(chain->filter_chain, tp->next);

View File

@ -512,7 +512,9 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr,
{ {
addr->sa.sa_family = AF_INET6; addr->sa.sa_family = AF_INET6;
addr->v6.sin6_port = port; addr->v6.sin6_port = port;
addr->v6.sin6_flowinfo = 0;
addr->v6.sin6_addr = *saddr; addr->v6.sin6_addr = *saddr;
addr->v6.sin6_scope_id = 0;
} }
/* Compare addresses exactly. /* Compare addresses exactly.

View File

@ -258,13 +258,15 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
arg = nlmsg_new(0, GFP_KERNEL); arg = nlmsg_new(0, GFP_KERNEL);
if (!arg) { if (!arg) {
kfree_skb(msg->rep); kfree_skb(msg->rep);
msg->rep = NULL;
return -ENOMEM; return -ENOMEM;
} }
err = __tipc_nl_compat_dumpit(cmd, msg, arg); err = __tipc_nl_compat_dumpit(cmd, msg, arg);
if (err) if (err) {
kfree_skb(msg->rep); kfree_skb(msg->rep);
msg->rep = NULL;
}
kfree_skb(arg); kfree_skb(arg);
return err; return err;

View File

@ -2304,10 +2304,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
*/ */
mutex_lock(&u->iolock); mutex_lock(&u->iolock);
if (flags & MSG_PEEK) skip = max(sk_peek_offset(sk, flags), 0);
skip = sk_peek_offset(sk, flags);
else
skip = 0;
do { do {
int chunk; int chunk;

View File

@ -879,7 +879,8 @@ bpf_object__create_maps(struct bpf_object *obj)
size_t j; size_t j;
int err = *pfd; int err = *pfd;
pr_warning("failed to create map: %s\n", pr_warning("failed to create map (name: '%s'): %s\n",
obj->maps[i].name,
strerror(errno)); strerror(errno));
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
zclose(obj->maps[j].fd); zclose(obj->maps[j].fd);