Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Need to access netdev->num_rx_queues behind an accessor in netvsc driver otherwise the build breaks with some configs, from Arnd Bergmann. 2) Add dummy xfrm_dev_event() so that build doesn't fail when CONFIG_XFRM_OFFLOAD is not set. From Hangbin Liu. 3) Don't OOPS when pfkey_msg2xfrm_state() signals an erros, from Dan Carpenter. 4) Fix MCDI command size for filter operations in sfc driver, from Martin Habets. 5) Fix UFO segmenting so that we don't calculate incorrect checksums, from Michal Kubecek. 6) When ipv6 datagram connects fail, reset destination address and port. From Wei Wang. 7) TCP disconnect must reset the cached receive DST, from WANG Cong. 8) Fix sign extension bug on 32-bit in dev_get_stats(), from Eric Dumazet. 9) fman driver has to depend on HAS_DMA, from Madalin Bucur. 10) Fix bpf pointer leak with xadd in verifier, from Daniel Borkmann. 11) Fix negative page counts with GFO, from Michal Kubecek. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (41 commits) sfc: fix attempt to translate invalid filter ID net: handle NAPI_GRO_FREE_STOLEN_HEAD case also in napi_frags_finish() bpf: prevent leaking pointer via xadd on unpriviledged arcnet: com20020-pci: add missing pdev setup in netdev structure arcnet: com20020-pci: fix dev_id calculation arcnet: com20020: remove needless base_addr assignment Trivial fix to spelling mistake in arc_printk message arcnet: change irq handler to lock irqsave rocker: move dereference before free mlxsw: spectrum_router: Fix NULL pointer dereference net: sched: Fix one possible panic when no destroy callback virtio-net: serialize tx routine during reset net: usb: asix88179_178a: Add support for the Belkin B2B128 fsl/fman: add dependency on HAS_DMA net: prevent sign extension in dev_get_stats() tcp: reset sk_rx_dst in tcp_disconnect() net: ipv6: reset daddr and dport in sk if connect() fails bnx2x: Don't log mc removal needlessly bnxt_en: Fix netpoll handling. bnxt_en: Add missing logic to handle TPA end error conditions. ...
This commit is contained in:
commit
4d8a991d46
|
@ -756,6 +756,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
|||
struct net_device *dev = dev_id;
|
||||
struct arcnet_local *lp;
|
||||
int recbuf, status, diagstatus, didsomething, boguscount;
|
||||
unsigned long flags;
|
||||
int retval = IRQ_NONE;
|
||||
|
||||
arc_printk(D_DURING, dev, "\n");
|
||||
|
@ -765,7 +766,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
|||
lp = netdev_priv(dev);
|
||||
BUG_ON(!lp);
|
||||
|
||||
spin_lock(&lp->lock);
|
||||
spin_lock_irqsave(&lp->lock, flags);
|
||||
|
||||
/* RESET flag was enabled - if device is not running, we must
|
||||
* clear it right away (but nothing else).
|
||||
|
@ -774,7 +775,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
|||
if (lp->hw.status(dev) & RESETflag)
|
||||
lp->hw.command(dev, CFLAGScmd | RESETclear);
|
||||
lp->hw.intmask(dev, 0);
|
||||
spin_unlock(&lp->lock);
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -998,7 +999,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
|
|||
udelay(1);
|
||||
lp->hw.intmask(dev, lp->intmask);
|
||||
|
||||
spin_unlock(&lp->lock);
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(arcnet_interrupt);
|
||||
|
|
|
@ -212,7 +212,7 @@ static int ack_tx(struct net_device *dev, int acked)
|
|||
ackpkt->soft.cap.proto = 0; /* using protocol 0 for acknowledge */
|
||||
ackpkt->soft.cap.mes.ack = acked;
|
||||
|
||||
arc_printk(D_PROTO, dev, "Ackknowledge for cap packet %x.\n",
|
||||
arc_printk(D_PROTO, dev, "Acknowledge for cap packet %x.\n",
|
||||
*((int *)&ackpkt->soft.cap.cookie[0]));
|
||||
|
||||
ackskb->protocol = cpu_to_be16(ETH_P_ARCNET);
|
||||
|
|
|
@ -135,6 +135,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
|||
for (i = 0; i < ci->devcount; i++) {
|
||||
struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
|
||||
struct com20020_dev *card;
|
||||
int dev_id_mask = 0xf;
|
||||
|
||||
dev = alloc_arcdev(device);
|
||||
if (!dev) {
|
||||
|
@ -166,6 +167,7 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
|||
arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
|
||||
arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
|
||||
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
dev->base_addr = ioaddr;
|
||||
dev->dev_addr[0] = node;
|
||||
dev->irq = pdev->irq;
|
||||
|
@ -179,8 +181,8 @@ static int com20020pci_probe(struct pci_dev *pdev,
|
|||
|
||||
/* Get the dev_id from the PLX rotary coder */
|
||||
if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
|
||||
dev->dev_id = 0xc;
|
||||
dev->dev_id ^= inb(priv->misc + ci->rotary) >> 4;
|
||||
dev_id_mask = 0x3;
|
||||
dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
|
||||
|
||||
snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
|
||||
|
||||
|
|
|
@ -246,8 +246,6 @@ int com20020_found(struct net_device *dev, int shared)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev->base_addr = ioaddr;
|
||||
|
||||
arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
|
||||
lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);
|
||||
|
||||
|
|
|
@ -12729,7 +12729,7 @@ static int bnx2x_set_mc_list(struct bnx2x *bp)
|
|||
} else {
|
||||
/* If no mc addresses are required, flush the configuration */
|
||||
rc = bnx2x_config_mcast(bp, &rparam, BNX2X_MCAST_CMD_DEL);
|
||||
if (rc)
|
||||
if (rc < 0)
|
||||
BNX2X_ERR("Failed to clear multicast configuration %d\n",
|
||||
rc);
|
||||
}
|
||||
|
|
|
@ -1301,10 +1301,11 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
|
|||
cp_cons = NEXT_CMP(cp_cons);
|
||||
}
|
||||
|
||||
if (unlikely(agg_bufs > MAX_SKB_FRAGS)) {
|
||||
if (unlikely(agg_bufs > MAX_SKB_FRAGS || TPA_END_ERRORS(tpa_end1))) {
|
||||
bnxt_abort_tpa(bp, bnapi, cp_cons, agg_bufs);
|
||||
netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
|
||||
agg_bufs, (int)MAX_SKB_FRAGS);
|
||||
if (agg_bufs > MAX_SKB_FRAGS)
|
||||
netdev_warn(bp->dev, "TPA frags %d exceeded MAX_SKB_FRAGS %d\n",
|
||||
agg_bufs, (int)MAX_SKB_FRAGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1562,6 +1563,45 @@ next_rx_no_prod:
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* In netpoll mode, if we are using a combined completion ring, we need to
|
||||
* discard the rx packets and recycle the buffers.
|
||||
*/
|
||||
static int bnxt_force_rx_discard(struct bnxt *bp, struct bnxt_napi *bnapi,
|
||||
u32 *raw_cons, u8 *event)
|
||||
{
|
||||
struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
|
||||
u32 tmp_raw_cons = *raw_cons;
|
||||
struct rx_cmp_ext *rxcmp1;
|
||||
struct rx_cmp *rxcmp;
|
||||
u16 cp_cons;
|
||||
u8 cmp_type;
|
||||
|
||||
cp_cons = RING_CMP(tmp_raw_cons);
|
||||
rxcmp = (struct rx_cmp *)
|
||||
&cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
|
||||
|
||||
tmp_raw_cons = NEXT_RAW_CMP(tmp_raw_cons);
|
||||
cp_cons = RING_CMP(tmp_raw_cons);
|
||||
rxcmp1 = (struct rx_cmp_ext *)
|
||||
&cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
|
||||
|
||||
if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
|
||||
return -EBUSY;
|
||||
|
||||
cmp_type = RX_CMP_TYPE(rxcmp);
|
||||
if (cmp_type == CMP_TYPE_RX_L2_CMP) {
|
||||
rxcmp1->rx_cmp_cfa_code_errors_v2 |=
|
||||
cpu_to_le32(RX_CMPL_ERRORS_CRC_ERROR);
|
||||
} else if (cmp_type == CMP_TYPE_RX_L2_TPA_END_CMP) {
|
||||
struct rx_tpa_end_cmp_ext *tpa_end1;
|
||||
|
||||
tpa_end1 = (struct rx_tpa_end_cmp_ext *)rxcmp1;
|
||||
tpa_end1->rx_tpa_end_cmp_errors_v2 |=
|
||||
cpu_to_le32(RX_TPA_END_CMP_ERRORS);
|
||||
}
|
||||
return bnxt_rx_pkt(bp, bnapi, raw_cons, event);
|
||||
}
|
||||
|
||||
#define BNXT_GET_EVENT_PORT(data) \
|
||||
((data) & \
|
||||
ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
|
||||
|
@ -1744,7 +1784,11 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
|
|||
if (unlikely(tx_pkts > bp->tx_wake_thresh))
|
||||
rx_pkts = budget;
|
||||
} else if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
|
||||
rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event);
|
||||
if (likely(budget))
|
||||
rc = bnxt_rx_pkt(bp, bnapi, &raw_cons, &event);
|
||||
else
|
||||
rc = bnxt_force_rx_discard(bp, bnapi, &raw_cons,
|
||||
&event);
|
||||
if (likely(rc >= 0))
|
||||
rx_pkts += rc;
|
||||
else if (rc == -EBUSY) /* partial completion */
|
||||
|
@ -6663,12 +6707,11 @@ static void bnxt_poll_controller(struct net_device *dev)
|
|||
struct bnxt *bp = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bp->cp_nr_rings; i++) {
|
||||
struct bnxt_irq *irq = &bp->irq_tbl[i];
|
||||
/* Only process tx rings/combined rings in netpoll mode. */
|
||||
for (i = 0; i < bp->tx_nr_rings; i++) {
|
||||
struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
|
||||
|
||||
disable_irq(irq->vector);
|
||||
irq->handler(irq->vector, bp->bnapi[i]);
|
||||
enable_irq(irq->vector);
|
||||
napi_schedule(&txr->bnapi->napi);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -374,12 +374,16 @@ struct rx_tpa_end_cmp_ext {
|
|||
|
||||
__le32 rx_tpa_end_cmp_errors_v2;
|
||||
#define RX_TPA_END_CMP_V2 (0x1 << 0)
|
||||
#define RX_TPA_END_CMP_ERRORS (0x7fff << 1)
|
||||
#define RX_TPA_END_CMP_ERRORS (0x3 << 1)
|
||||
#define RX_TPA_END_CMPL_ERRORS_SHIFT 1
|
||||
|
||||
u32 rx_tpa_end_cmp_start_opaque;
|
||||
};
|
||||
|
||||
#define TPA_END_ERRORS(rx_tpa_end_ext) \
|
||||
((rx_tpa_end_ext)->rx_tpa_end_cmp_errors_v2 & \
|
||||
cpu_to_le32(RX_TPA_END_CMP_ERRORS))
|
||||
|
||||
#define DB_IDX_MASK 0xffffff
|
||||
#define DB_IDX_VALID (0x1 << 26)
|
||||
#define DB_IRQ_DIS (0x1 << 27)
|
||||
|
|
|
@ -2,6 +2,7 @@ config FSL_FMAN
|
|||
tristate "FMan support"
|
||||
depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
|
||||
select GENERIC_ALLOCATOR
|
||||
depends on HAS_DMA
|
||||
select PHYLIB
|
||||
default n
|
||||
help
|
||||
|
|
|
@ -3334,6 +3334,9 @@ static int mlxsw_sp_inetaddr_vlan_event(struct net_device *vlan_dev,
|
|||
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(vlan_dev);
|
||||
u16 vid = vlan_dev_vlan_id(vlan_dev);
|
||||
|
||||
if (netif_is_bridge_port(vlan_dev))
|
||||
return 0;
|
||||
|
||||
if (mlxsw_sp_port_dev_check(real_dev))
|
||||
return mlxsw_sp_inetaddr_vport_event(vlan_dev, real_dev, event,
|
||||
vid);
|
||||
|
|
|
@ -1505,8 +1505,8 @@ static int ofdpa_port_ipv4_nh(struct ofdpa_port *ofdpa_port,
|
|||
*index = entry->index;
|
||||
resolved = false;
|
||||
} else if (removing) {
|
||||
ofdpa_neigh_del(trans, found);
|
||||
*index = found->index;
|
||||
ofdpa_neigh_del(trans, found);
|
||||
} else if (updating) {
|
||||
ofdpa_neigh_update(found, trans, NULL, false);
|
||||
resolved = !is_zero_ether_addr(found->eth_dst);
|
||||
|
|
|
@ -4172,7 +4172,7 @@ found:
|
|||
* recipients
|
||||
*/
|
||||
if (is_mc_recip) {
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
|
||||
unsigned int depth, i;
|
||||
|
||||
memset(inbuf, 0, sizeof(inbuf));
|
||||
|
@ -4320,7 +4320,7 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
|
|||
efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
|
||||
} else {
|
||||
efx_mcdi_display_error(efx, MC_CMD_FILTER_OP,
|
||||
MC_CMD_FILTER_OP_IN_LEN,
|
||||
MC_CMD_FILTER_OP_EXT_IN_LEN,
|
||||
NULL, 0, rc);
|
||||
}
|
||||
}
|
||||
|
@ -4453,7 +4453,7 @@ static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx,
|
|||
struct efx_filter_spec *spec)
|
||||
{
|
||||
struct efx_ef10_filter_table *table = efx->filter_state;
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
|
||||
struct efx_filter_spec *saved_spec;
|
||||
unsigned int hash, i, depth = 1;
|
||||
bool replacing = false;
|
||||
|
@ -4940,7 +4940,7 @@ not_restored:
|
|||
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
|
||||
{
|
||||
struct efx_ef10_filter_table *table = efx->filter_state;
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_IN_LEN);
|
||||
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
|
||||
struct efx_filter_spec *spec;
|
||||
unsigned int filter_idx;
|
||||
int rc;
|
||||
|
@ -5105,6 +5105,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
|
|||
|
||||
/* Insert/renew filters */
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
EFX_WARN_ON_PARANOID(ids[i] != EFX_EF10_FILTER_ID_INVALID);
|
||||
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
|
||||
efx_filter_set_eth_local(&spec, vlan->vid, addr_list[i].addr);
|
||||
rc = efx_ef10_filter_insert(efx, &spec, true);
|
||||
|
@ -5122,11 +5123,11 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
|
|||
}
|
||||
return rc;
|
||||
} else {
|
||||
/* mark as not inserted, and carry on */
|
||||
rc = EFX_EF10_FILTER_ID_INVALID;
|
||||
/* keep invalid ID, and carry on */
|
||||
}
|
||||
} else {
|
||||
ids[i] = efx_ef10_filter_get_unsafe_id(rc);
|
||||
}
|
||||
ids[i] = efx_ef10_filter_get_unsafe_id(rc);
|
||||
}
|
||||
|
||||
if (multicast && rollback) {
|
||||
|
|
|
@ -90,7 +90,7 @@ int ti_cm_get_macid(struct device *dev, int slave, u8 *mac_addr)
|
|||
if (of_device_is_compatible(dev->of_node, "ti,dm816-emac"))
|
||||
return cpsw_am33xx_cm_get_macid(dev, 0x30, slave, mac_addr);
|
||||
|
||||
if (of_machine_is_compatible("ti,am4372"))
|
||||
if (of_machine_is_compatible("ti,am43"))
|
||||
return cpsw_am33xx_cm_get_macid(dev, 0x630, slave, mac_addr);
|
||||
|
||||
if (of_machine_is_compatible("ti,dra7"))
|
||||
|
|
|
@ -776,7 +776,7 @@ static int netvsc_set_channels(struct net_device *net,
|
|||
channels->rx_count || channels->tx_count || channels->other_count)
|
||||
return -EINVAL;
|
||||
|
||||
if (count > net->num_tx_queues || count > net->num_rx_queues)
|
||||
if (count > net->num_tx_queues || count > VRSS_CHANNEL_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (!nvdev || nvdev->destroy)
|
||||
|
@ -1203,7 +1203,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
|
|||
rndis_dev = ndev->extension;
|
||||
if (indir) {
|
||||
for (i = 0; i < ITAB_NUM; i++)
|
||||
if (indir[i] >= dev->num_rx_queues)
|
||||
if (indir[i] >= VRSS_CHANNEL_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ITAB_NUM; i++)
|
||||
|
|
|
@ -39,16 +39,20 @@
|
|||
#define MACVLAN_HASH_SIZE (1<<MACVLAN_HASH_BITS)
|
||||
#define MACVLAN_BC_QUEUE_LEN 1000
|
||||
|
||||
#define MACVLAN_F_PASSTHRU 1
|
||||
#define MACVLAN_F_ADDRCHANGE 2
|
||||
|
||||
struct macvlan_port {
|
||||
struct net_device *dev;
|
||||
struct hlist_head vlan_hash[MACVLAN_HASH_SIZE];
|
||||
struct list_head vlans;
|
||||
struct sk_buff_head bc_queue;
|
||||
struct work_struct bc_work;
|
||||
bool passthru;
|
||||
u32 flags;
|
||||
int count;
|
||||
struct hlist_head vlan_source_hash[MACVLAN_HASH_SIZE];
|
||||
DECLARE_BITMAP(mc_filter, MACVLAN_MC_FILTER_SZ);
|
||||
unsigned char perm_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct macvlan_source_entry {
|
||||
|
@ -66,6 +70,31 @@ struct macvlan_skb_cb {
|
|||
|
||||
static void macvlan_port_destroy(struct net_device *dev);
|
||||
|
||||
static inline bool macvlan_passthru(const struct macvlan_port *port)
|
||||
{
|
||||
return port->flags & MACVLAN_F_PASSTHRU;
|
||||
}
|
||||
|
||||
static inline void macvlan_set_passthru(struct macvlan_port *port)
|
||||
{
|
||||
port->flags |= MACVLAN_F_PASSTHRU;
|
||||
}
|
||||
|
||||
static inline bool macvlan_addr_change(const struct macvlan_port *port)
|
||||
{
|
||||
return port->flags & MACVLAN_F_ADDRCHANGE;
|
||||
}
|
||||
|
||||
static inline void macvlan_set_addr_change(struct macvlan_port *port)
|
||||
{
|
||||
port->flags |= MACVLAN_F_ADDRCHANGE;
|
||||
}
|
||||
|
||||
static inline void macvlan_clear_addr_change(struct macvlan_port *port)
|
||||
{
|
||||
port->flags &= ~MACVLAN_F_ADDRCHANGE;
|
||||
}
|
||||
|
||||
/* Hash Ethernet address */
|
||||
static u32 macvlan_eth_hash(const unsigned char *addr)
|
||||
{
|
||||
|
@ -181,11 +210,12 @@ static void macvlan_hash_change_addr(struct macvlan_dev *vlan,
|
|||
static bool macvlan_addr_busy(const struct macvlan_port *port,
|
||||
const unsigned char *addr)
|
||||
{
|
||||
/* Test to see if the specified multicast address is
|
||||
/* Test to see if the specified address is
|
||||
* currently in use by the underlying device or
|
||||
* another macvlan.
|
||||
*/
|
||||
if (ether_addr_equal_64bits(port->dev->dev_addr, addr))
|
||||
if (!macvlan_passthru(port) && !macvlan_addr_change(port) &&
|
||||
ether_addr_equal_64bits(port->dev->dev_addr, addr))
|
||||
return true;
|
||||
|
||||
if (macvlan_hash_lookup(port, addr))
|
||||
|
@ -445,7 +475,7 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
|
|||
}
|
||||
|
||||
macvlan_forward_source(skb, port, eth->h_source);
|
||||
if (port->passthru)
|
||||
if (macvlan_passthru(port))
|
||||
vlan = list_first_or_null_rcu(&port->vlans,
|
||||
struct macvlan_dev, list);
|
||||
else
|
||||
|
@ -574,7 +604,7 @@ static int macvlan_open(struct net_device *dev)
|
|||
struct net_device *lowerdev = vlan->lowerdev;
|
||||
int err;
|
||||
|
||||
if (vlan->port->passthru) {
|
||||
if (macvlan_passthru(vlan->port)) {
|
||||
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC)) {
|
||||
err = dev_set_promiscuity(lowerdev, 1);
|
||||
if (err < 0)
|
||||
|
@ -649,7 +679,7 @@ static int macvlan_stop(struct net_device *dev)
|
|||
dev_uc_unsync(lowerdev, dev);
|
||||
dev_mc_unsync(lowerdev, dev);
|
||||
|
||||
if (vlan->port->passthru) {
|
||||
if (macvlan_passthru(vlan->port)) {
|
||||
if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
|
||||
dev_set_promiscuity(lowerdev, -1);
|
||||
goto hash_del;
|
||||
|
@ -672,6 +702,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
|
|||
{
|
||||
struct macvlan_dev *vlan = netdev_priv(dev);
|
||||
struct net_device *lowerdev = vlan->lowerdev;
|
||||
struct macvlan_port *port = vlan->port;
|
||||
int err;
|
||||
|
||||
if (!(dev->flags & IFF_UP)) {
|
||||
|
@ -682,7 +713,7 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
|
|||
if (macvlan_addr_busy(vlan->port, addr))
|
||||
return -EBUSY;
|
||||
|
||||
if (!vlan->port->passthru) {
|
||||
if (!macvlan_passthru(port)) {
|
||||
err = dev_uc_add(lowerdev, addr);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -692,6 +723,15 @@ static int macvlan_sync_address(struct net_device *dev, unsigned char *addr)
|
|||
|
||||
macvlan_hash_change_addr(vlan, addr);
|
||||
}
|
||||
if (macvlan_passthru(port) && !macvlan_addr_change(port)) {
|
||||
/* Since addr_change isn't set, we are here due to lower
|
||||
* device change. Save the lower-dev address so we can
|
||||
* restore it later.
|
||||
*/
|
||||
ether_addr_copy(vlan->port->perm_addr,
|
||||
lowerdev->dev_addr);
|
||||
}
|
||||
macvlan_clear_addr_change(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -703,7 +743,12 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p)
|
|||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
/* If the addresses are the same, this is a no-op */
|
||||
if (ether_addr_equal(dev->dev_addr, addr->sa_data))
|
||||
return 0;
|
||||
|
||||
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
|
||||
macvlan_set_addr_change(vlan->port);
|
||||
dev_set_mac_address(vlan->lowerdev, addr);
|
||||
return 0;
|
||||
}
|
||||
|
@ -928,7 +973,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
|
|||
/* Support unicast filter only on passthru devices.
|
||||
* Multicast filter should be allowed on all devices.
|
||||
*/
|
||||
if (!vlan->port->passthru && is_unicast_ether_addr(addr))
|
||||
if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (flags & NLM_F_REPLACE)
|
||||
|
@ -952,7 +997,7 @@ static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
|
|||
/* Support unicast filter only on passthru devices.
|
||||
* Multicast filter should be allowed on all devices.
|
||||
*/
|
||||
if (!vlan->port->passthru && is_unicast_ether_addr(addr))
|
||||
if (!macvlan_passthru(vlan->port) && is_unicast_ether_addr(addr))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (is_unicast_ether_addr(addr))
|
||||
|
@ -1120,8 +1165,8 @@ static int macvlan_port_create(struct net_device *dev)
|
|||
if (port == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
port->passthru = false;
|
||||
port->dev = dev;
|
||||
ether_addr_copy(port->perm_addr, dev->dev_addr);
|
||||
INIT_LIST_HEAD(&port->vlans);
|
||||
for (i = 0; i < MACVLAN_HASH_SIZE; i++)
|
||||
INIT_HLIST_HEAD(&port->vlan_hash[i]);
|
||||
|
@ -1161,6 +1206,18 @@ static void macvlan_port_destroy(struct net_device *dev)
|
|||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* If the lower device address has been changed by passthru
|
||||
* macvlan, put it back.
|
||||
*/
|
||||
if (macvlan_passthru(port) &&
|
||||
!ether_addr_equal(port->dev->dev_addr, port->perm_addr)) {
|
||||
struct sockaddr sa;
|
||||
|
||||
sa.sa_family = port->dev->type;
|
||||
memcpy(&sa.sa_data, port->perm_addr, port->dev->addr_len);
|
||||
dev_set_mac_address(port->dev, &sa);
|
||||
}
|
||||
|
||||
kfree(port);
|
||||
}
|
||||
|
||||
|
@ -1326,7 +1383,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|||
port = macvlan_port_get_rtnl(lowerdev);
|
||||
|
||||
/* Only 1 macvlan device can be created in passthru mode */
|
||||
if (port->passthru) {
|
||||
if (macvlan_passthru(port)) {
|
||||
/* The macvlan port must be not created this time,
|
||||
* still goto destroy_macvlan_port for readability.
|
||||
*/
|
||||
|
@ -1352,7 +1409,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
|||
err = -EINVAL;
|
||||
goto destroy_macvlan_port;
|
||||
}
|
||||
port->passthru = true;
|
||||
macvlan_set_passthru(port);
|
||||
eth_hw_addr_inherit(dev, lowerdev);
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1491,7 @@ static int macvlan_changelink(struct net_device *dev,
|
|||
if (data && data[IFLA_MACVLAN_FLAGS]) {
|
||||
__u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
|
||||
bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC;
|
||||
if (vlan->port->passthru && promisc) {
|
||||
if (macvlan_passthru(vlan->port) && promisc) {
|
||||
int err;
|
||||
|
||||
if (flags & MACVLAN_FLAG_NOPROMISC)
|
||||
|
@ -1597,7 +1654,7 @@ static int macvlan_device_event(struct notifier_block *unused,
|
|||
}
|
||||
break;
|
||||
case NETDEV_CHANGEADDR:
|
||||
if (!port->passthru)
|
||||
if (!macvlan_passthru(port))
|
||||
return NOTIFY_DONE;
|
||||
|
||||
vlan = list_first_entry_or_null(&port->vlans,
|
||||
|
|
|
@ -908,7 +908,7 @@ static void decode_txts(struct dp83640_private *dp83640,
|
|||
if (overflow) {
|
||||
pr_debug("tx timestamp queue overflow, count %d\n", overflow);
|
||||
while (skb) {
|
||||
skb_complete_tx_timestamp(skb, NULL);
|
||||
kfree_skb(skb);
|
||||
skb = skb_dequeue(&dp83640->tx_queue);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -619,6 +619,8 @@ static int ksz9031_read_status(struct phy_device *phydev)
|
|||
if ((regval & 0xFF) == 0xFF) {
|
||||
phy_init_hw(phydev);
|
||||
phydev->link = 0;
|
||||
if (phydev->drv->config_intr && phy_interrupt_is_valid(phydev))
|
||||
phydev->drv->config_intr(phydev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1722,6 +1722,18 @@ static const struct driver_info lenovo_info = {
|
|||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
||||
static const struct driver_info belkin_info = {
|
||||
.description = "Belkin USB Ethernet Adapter",
|
||||
.bind = ax88179_bind,
|
||||
.unbind = ax88179_unbind,
|
||||
.status = ax88179_status,
|
||||
.link_reset = ax88179_link_reset,
|
||||
.reset = ax88179_reset,
|
||||
.flags = FLAG_ETHER | FLAG_FRAMING_AX,
|
||||
.rx_fixup = ax88179_rx_fixup,
|
||||
.tx_fixup = ax88179_tx_fixup,
|
||||
};
|
||||
|
||||
static const struct usb_device_id products[] = {
|
||||
{
|
||||
/* ASIX AX88179 10/100/1000 */
|
||||
|
@ -1751,6 +1763,10 @@ static const struct usb_device_id products[] = {
|
|||
/* Lenovo OneLinkDock Gigabit LAN */
|
||||
USB_DEVICE(0x17ef, 0x304b),
|
||||
.driver_info = (unsigned long)&lenovo_info,
|
||||
}, {
|
||||
/* Belkin B2B128 USB 3.0 Hub + Gigabit Ethernet Adapter */
|
||||
USB_DEVICE(0x050d, 0x0128),
|
||||
.driver_info = (unsigned long)&belkin_info,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
|
|
@ -383,7 +383,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
|
|||
tbp = tb;
|
||||
}
|
||||
|
||||
if (tbp[IFLA_IFNAME]) {
|
||||
if (ifmp && tbp[IFLA_IFNAME]) {
|
||||
nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
|
||||
name_assign_type = NET_NAME_USER;
|
||||
} else {
|
||||
|
@ -402,7 +402,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
|
|||
return PTR_ERR(peer);
|
||||
}
|
||||
|
||||
if (tbp[IFLA_ADDRESS] == NULL)
|
||||
if (!ifmp || !tbp[IFLA_ADDRESS])
|
||||
eth_hw_addr_random(peer);
|
||||
|
||||
if (ifmp && (dev->ifindex != 0))
|
||||
|
|
|
@ -1797,6 +1797,7 @@ static void virtnet_freeze_down(struct virtio_device *vdev)
|
|||
flush_work(&vi->config_work);
|
||||
|
||||
netif_device_detach(vi->dev);
|
||||
netif_tx_disable(vi->dev);
|
||||
cancel_delayed_work_sync(&vi->refill);
|
||||
|
||||
if (netif_running(vi->dev)) {
|
||||
|
|
|
@ -199,6 +199,7 @@ struct xenvif_queue { /* Per-queue data for xenvif */
|
|||
unsigned long remaining_credit;
|
||||
struct timer_list credit_timeout;
|
||||
u64 credit_window_start;
|
||||
bool rate_limited;
|
||||
|
||||
/* Statistics */
|
||||
struct xenvif_stats stats;
|
||||
|
|
|
@ -106,7 +106,11 @@ static int xenvif_poll(struct napi_struct *napi, int budget)
|
|||
|
||||
if (work_done < budget) {
|
||||
napi_complete_done(napi, work_done);
|
||||
xenvif_napi_schedule_or_enable_events(queue);
|
||||
/* If the queue is rate-limited, it shall be
|
||||
* rescheduled in the timer callback.
|
||||
*/
|
||||
if (likely(!queue->rate_limited))
|
||||
xenvif_napi_schedule_or_enable_events(queue);
|
||||
}
|
||||
|
||||
return work_done;
|
||||
|
|
|
@ -180,6 +180,7 @@ static void tx_add_credit(struct xenvif_queue *queue)
|
|||
max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
|
||||
|
||||
queue->remaining_credit = min(max_credit, max_burst);
|
||||
queue->rate_limited = false;
|
||||
}
|
||||
|
||||
void xenvif_tx_credit_callback(unsigned long data)
|
||||
|
@ -686,8 +687,10 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)
|
|||
msecs_to_jiffies(queue->credit_usec / 1000);
|
||||
|
||||
/* Timer could already be pending in rare cases. */
|
||||
if (timer_pending(&queue->credit_timeout))
|
||||
if (timer_pending(&queue->credit_timeout)) {
|
||||
queue->rate_limited = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Passed the point where we can replenish credit? */
|
||||
if (time_after_eq64(now, next_credit)) {
|
||||
|
@ -702,6 +705,7 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size)
|
|||
mod_timer(&queue->credit_timeout,
|
||||
next_credit);
|
||||
queue->credit_window_start = next_credit;
|
||||
queue->rate_limited = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1850,8 +1850,9 @@ static inline struct xfrm_offload *xfrm_offload(struct sk_buff *skb)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_XFRM_OFFLOAD
|
||||
void __net_init xfrm_dev_init(void);
|
||||
|
||||
#ifdef CONFIG_XFRM_OFFLOAD
|
||||
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features);
|
||||
int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
|
||||
struct xfrm_user_offload *xuo);
|
||||
|
@ -1877,10 +1878,6 @@ static inline void xfrm_dev_state_free(struct xfrm_state *x)
|
|||
}
|
||||
}
|
||||
#else
|
||||
static inline void __net_init xfrm_dev_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -989,6 +989,11 @@ static int check_xadd(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (is_pointer_value(env, insn->src_reg)) {
|
||||
verbose("R%d leaks addr into mem\n", insn->src_reg);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
/* check whether atomic_add can read the memory */
|
||||
err = check_mem_access(env, insn->dst_reg, insn->off,
|
||||
BPF_SIZE(insn->code), BPF_READ, -1);
|
||||
|
|
|
@ -4767,6 +4767,13 @@ struct packet_offload *gro_find_complete_by_type(__be16 type)
|
|||
}
|
||||
EXPORT_SYMBOL(gro_find_complete_by_type);
|
||||
|
||||
static void napi_skb_free_stolen_head(struct sk_buff *skb)
|
||||
{
|
||||
skb_dst_drop(skb);
|
||||
secpath_reset(skb);
|
||||
kmem_cache_free(skbuff_head_cache, skb);
|
||||
}
|
||||
|
||||
static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
|
||||
{
|
||||
switch (ret) {
|
||||
|
@ -4780,13 +4787,10 @@ static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
|
|||
break;
|
||||
|
||||
case GRO_MERGED_FREE:
|
||||
if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD) {
|
||||
skb_dst_drop(skb);
|
||||
secpath_reset(skb);
|
||||
kmem_cache_free(skbuff_head_cache, skb);
|
||||
} else {
|
||||
if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
|
||||
napi_skb_free_stolen_head(skb);
|
||||
else
|
||||
__kfree_skb(skb);
|
||||
}
|
||||
break;
|
||||
|
||||
case GRO_HELD:
|
||||
|
@ -4858,10 +4862,16 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi,
|
|||
break;
|
||||
|
||||
case GRO_DROP:
|
||||
case GRO_MERGED_FREE:
|
||||
napi_reuse_skb(napi, skb);
|
||||
break;
|
||||
|
||||
case GRO_MERGED_FREE:
|
||||
if (NAPI_GRO_CB(skb)->free == NAPI_GRO_FREE_STOLEN_HEAD)
|
||||
napi_skb_free_stolen_head(skb);
|
||||
else
|
||||
napi_reuse_skb(napi, skb);
|
||||
break;
|
||||
|
||||
case GRO_MERGED:
|
||||
case GRO_CONSUMED:
|
||||
break;
|
||||
|
@ -7783,9 +7793,9 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
|
|||
} else {
|
||||
netdev_stats_to_stats64(storage, &dev->stats);
|
||||
}
|
||||
storage->rx_dropped += atomic_long_read(&dev->rx_dropped);
|
||||
storage->tx_dropped += atomic_long_read(&dev->tx_dropped);
|
||||
storage->rx_nohandler += atomic_long_read(&dev->rx_nohandler);
|
||||
storage->rx_dropped += (unsigned long)atomic_long_read(&dev->rx_dropped);
|
||||
storage->tx_dropped += (unsigned long)atomic_long_read(&dev->tx_dropped);
|
||||
storage->rx_nohandler += (unsigned long)atomic_long_read(&dev->rx_nohandler);
|
||||
return storage;
|
||||
}
|
||||
EXPORT_SYMBOL(dev_get_stats);
|
||||
|
|
|
@ -964,7 +964,8 @@ static int __ip_append_data(struct sock *sk,
|
|||
csummode = CHECKSUM_PARTIAL;
|
||||
|
||||
cork->length += length;
|
||||
if ((((length + fragheaderlen) > mtu) || (skb && skb_is_gso(skb))) &&
|
||||
if ((((length + (skb ? skb->len : fragheaderlen)) > mtu) ||
|
||||
(skb && skb_is_gso(skb))) &&
|
||||
(sk->sk_protocol == IPPROTO_UDP) &&
|
||||
(rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
|
||||
(sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) {
|
||||
|
|
|
@ -2330,6 +2330,8 @@ int tcp_disconnect(struct sock *sk, int flags)
|
|||
tcp_init_send_head(sk);
|
||||
memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
|
||||
__sk_dst_reset(sk);
|
||||
dst_release(sk->sk_rx_dst);
|
||||
sk->sk_rx_dst = NULL;
|
||||
tcp_saved_syn_free(tp);
|
||||
|
||||
/* Clean up fastopen related fields */
|
||||
|
|
|
@ -3369,6 +3369,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
|
|||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct netdev_notifier_changeupper_info *info;
|
||||
struct inet6_dev *idev = __in6_dev_get(dev);
|
||||
struct net *net = dev_net(dev);
|
||||
int run_pending = 0;
|
||||
int err;
|
||||
|
||||
|
@ -3384,7 +3385,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
|
|||
case NETDEV_CHANGEMTU:
|
||||
/* if MTU under IPV6_MIN_MTU stop IPv6 on this interface. */
|
||||
if (dev->mtu < IPV6_MIN_MTU) {
|
||||
addrconf_ifdown(dev, 1);
|
||||
addrconf_ifdown(dev, dev != net->loopback_dev);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3500,7 +3501,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
|
|||
* IPV6_MIN_MTU stop IPv6 on this interface.
|
||||
*/
|
||||
if (dev->mtu < IPV6_MIN_MTU)
|
||||
addrconf_ifdown(dev, 1);
|
||||
addrconf_ifdown(dev, dev != net->loopback_dev);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -250,8 +250,14 @@ ipv4_connected:
|
|||
*/
|
||||
|
||||
err = ip6_datagram_dst_update(sk, true);
|
||||
if (err)
|
||||
if (err) {
|
||||
/* Reset daddr and dport so that udp_v6_early_demux()
|
||||
* fails to find this socket
|
||||
*/
|
||||
memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr));
|
||||
inet->inet_dport = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
sk_set_txhash(sk);
|
||||
|
|
|
@ -30,6 +30,25 @@
|
|||
#include <net/ipv6.h>
|
||||
#include <linux/icmpv6.h>
|
||||
|
||||
static __u16 esp6_nexthdr_esp_offset(struct ipv6hdr *ipv6_hdr, int nhlen)
|
||||
{
|
||||
int off = sizeof(struct ipv6hdr);
|
||||
struct ipv6_opt_hdr *exthdr;
|
||||
|
||||
if (likely(ipv6_hdr->nexthdr == NEXTHDR_ESP))
|
||||
return offsetof(struct ipv6hdr, nexthdr);
|
||||
|
||||
while (off < nhlen) {
|
||||
exthdr = (void *)ipv6_hdr + off;
|
||||
if (exthdr->nexthdr == NEXTHDR_ESP)
|
||||
return off;
|
||||
|
||||
off += ipv6_optlen(exthdr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
@ -38,6 +57,7 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
|
|||
struct xfrm_state *x;
|
||||
__be32 seq;
|
||||
__be32 spi;
|
||||
int nhoff;
|
||||
int err;
|
||||
|
||||
skb_pull(skb, offset);
|
||||
|
@ -72,6 +92,11 @@ static struct sk_buff **esp6_gro_receive(struct sk_buff **head,
|
|||
|
||||
xo->flags |= XFRM_GRO;
|
||||
|
||||
nhoff = esp6_nexthdr_esp_offset(ipv6_hdr(skb), offset);
|
||||
if (!nhoff)
|
||||
goto out;
|
||||
|
||||
IP6CB(skb)->nhoff = nhoff;
|
||||
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
|
||||
XFRM_SPI_SKB_CB(skb)->family = AF_INET6;
|
||||
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
|
||||
|
|
|
@ -1390,7 +1390,7 @@ emsgsize:
|
|||
*/
|
||||
|
||||
cork->length += length;
|
||||
if ((((length + fragheaderlen) > mtu) ||
|
||||
if ((((length + (skb ? skb->len : headersize)) > mtu) ||
|
||||
(skb && skb_is_gso(skb))) &&
|
||||
(sk->sk_protocol == IPPROTO_UDP) &&
|
||||
(rt->dst.dev->features & NETIF_F_UFO) && !dst_xfrm(&rt->dst) &&
|
||||
|
|
|
@ -3722,7 +3722,11 @@ static int ip6_route_dev_notify(struct notifier_block *this,
|
|||
net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
|
||||
net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
|
||||
#endif
|
||||
} else if (event == NETDEV_UNREGISTER) {
|
||||
} else if (event == NETDEV_UNREGISTER &&
|
||||
dev->reg_state != NETREG_UNREGISTERED) {
|
||||
/* NETDEV_UNREGISTER could be fired for multiple times by
|
||||
* netdev_wait_allrefs(). Make sure we only call this once.
|
||||
*/
|
||||
in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
|
||||
|
|
|
@ -305,7 +305,7 @@ static int ipip6_tunnel_get_prl(struct ip_tunnel *t,
|
|||
* we try harder to allocate.
|
||||
*/
|
||||
kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ?
|
||||
kcalloc(cmax, sizeof(*kp), GFP_KERNEL) :
|
||||
kcalloc(cmax, sizeof(*kp), GFP_KERNEL | __GFP_NOWARN) :
|
||||
NULL;
|
||||
|
||||
rcu_read_lock();
|
||||
|
|
|
@ -879,7 +879,8 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net,
|
|||
struct sock *sk;
|
||||
|
||||
udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
|
||||
if (INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif))
|
||||
if (sk->sk_state == TCP_ESTABLISHED &&
|
||||
INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif))
|
||||
return sk;
|
||||
/* Only check first socket in chain */
|
||||
break;
|
||||
|
|
|
@ -43,8 +43,8 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
|
|||
return 1;
|
||||
#endif
|
||||
|
||||
ipv6_hdr(skb)->payload_len = htons(skb->len);
|
||||
__skb_push(skb, skb->data - skb_network_header(skb));
|
||||
ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
|
||||
|
||||
if (xo && (xo->flags & XFRM_GRO)) {
|
||||
skb_mac_header_rebuild(skb);
|
||||
|
|
|
@ -1157,6 +1157,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
goto out;
|
||||
}
|
||||
|
||||
err = -ENOBUFS;
|
||||
key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
|
||||
if (sa->sadb_sa_auth) {
|
||||
int keysize = 0;
|
||||
|
@ -1168,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
if (key)
|
||||
keysize = (key->sadb_key_bits + 7) / 8;
|
||||
x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
|
||||
if (!x->aalg)
|
||||
if (!x->aalg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->aalg->alg_name, a->name);
|
||||
x->aalg->alg_key_len = 0;
|
||||
if (key) {
|
||||
|
@ -1188,8 +1191,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
goto out;
|
||||
}
|
||||
x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
|
||||
if (!x->calg)
|
||||
if (!x->calg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->calg->alg_name, a->name);
|
||||
x->props.calgo = sa->sadb_sa_encrypt;
|
||||
} else {
|
||||
|
@ -1203,8 +1208,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
if (key)
|
||||
keysize = (key->sadb_key_bits + 7) / 8;
|
||||
x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
|
||||
if (!x->ealg)
|
||||
if (!x->ealg) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strcpy(x->ealg->alg_name, a->name);
|
||||
x->ealg->alg_key_len = 0;
|
||||
if (key) {
|
||||
|
@ -1249,8 +1256,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
|
|||
struct xfrm_encap_tmpl *natt;
|
||||
|
||||
x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
|
||||
if (!x->encap)
|
||||
if (!x->encap) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
natt = x->encap;
|
||||
n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
|
||||
|
@ -2755,6 +2764,8 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sad
|
|||
int err, err2;
|
||||
|
||||
err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
|
||||
if (!err)
|
||||
xfrm_garbage_collect(net);
|
||||
err2 = unicast_flush_resp(sk, hdr);
|
||||
if (err || err2) {
|
||||
if (err == -ESRCH) /* empty table - old silent behavior */
|
||||
|
|
|
@ -1019,7 +1019,8 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
|
|||
return sch;
|
||||
}
|
||||
/* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
|
||||
ops->destroy(sch);
|
||||
if (ops->destroy)
|
||||
ops->destroy(sch);
|
||||
err_out3:
|
||||
dev_put(dev);
|
||||
kfree((char *) sch - sch->padded);
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
|
||||
xfrm_input.o xfrm_output.o \
|
||||
xfrm_sysctl.o xfrm_replay.o
|
||||
obj-$(CONFIG_XFRM_OFFLOAD) += xfrm_device.o
|
||||
xfrm_sysctl.o xfrm_replay.o xfrm_device.o
|
||||
obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
|
||||
obj-$(CONFIG_XFRM_ALGO) += xfrm_algo.o
|
||||
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <net/xfrm.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#ifdef CONFIG_XFRM_OFFLOAD
|
||||
int validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features)
|
||||
{
|
||||
int err;
|
||||
|
@ -137,6 +138,7 @@ ok:
|
|||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok);
|
||||
#endif
|
||||
|
||||
int xfrm_dev_register(struct net_device *dev)
|
||||
{
|
||||
|
|
|
@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
|
|||
err = -ESRCH;
|
||||
out:
|
||||
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
|
||||
|
||||
if (cnt)
|
||||
xfrm_garbage_collect(net);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(xfrm_policy_flush);
|
||||
|
|
|
@ -2027,6 +2027,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
return 0;
|
||||
return err;
|
||||
}
|
||||
xfrm_garbage_collect(net);
|
||||
|
||||
c.data.type = type;
|
||||
c.event = nlh->nlmsg_type;
|
||||
|
|
|
@ -3748,6 +3748,72 @@ static struct bpf_test tests[] = {
|
|||
.result = REJECT,
|
||||
.errstr = "invalid bpf_context access",
|
||||
},
|
||||
{
|
||||
"leak pointer into ctx 1",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_2,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_map1 = { 2 },
|
||||
.errstr_unpriv = "R2 leaks addr into mem",
|
||||
.result_unpriv = REJECT,
|
||||
.result = ACCEPT,
|
||||
},
|
||||
{
|
||||
"leak pointer into ctx 2",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_STX_XADD(BPF_DW, BPF_REG_1, BPF_REG_10,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.errstr_unpriv = "R10 leaks addr into mem",
|
||||
.result_unpriv = REJECT,
|
||||
.result = ACCEPT,
|
||||
},
|
||||
{
|
||||
"leak pointer into ctx 3",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_map1 = { 1 },
|
||||
.errstr_unpriv = "R2 leaks addr into ctx",
|
||||
.result_unpriv = REJECT,
|
||||
.result = ACCEPT,
|
||||
},
|
||||
{
|
||||
"leak pointer into map val",
|
||||
.insns = {
|
||||
BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
|
||||
BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
|
||||
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
|
||||
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
|
||||
BPF_LD_MAP_FD(BPF_REG_1, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
|
||||
BPF_FUNC_map_lookup_elem),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_3, 0),
|
||||
BPF_STX_XADD(BPF_DW, BPF_REG_0, BPF_REG_6, 0),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 0),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_map1 = { 4 },
|
||||
.errstr_unpriv = "R6 leaks addr into mem",
|
||||
.result_unpriv = REJECT,
|
||||
.result = ACCEPT,
|
||||
},
|
||||
{
|
||||
"helper access to map: full range",
|
||||
.insns = {
|
||||
|
|
Loading…
Reference in New Issue