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

Pull networking fixes from David Miller:

 1) Unbreak zebra and other netlink apps, from Eric W Biederman.

 2) Some new qmi_wwan device IDs, from Aleksander Morgado.

 3) Fix info leak in DCB netlink handler of qlcnic driver, from Dan
    Carpenter.

 4) inet_getid() and ipv6_select_ident() do not generate monotonically
    increasing ID numbers, fix from Eric Dumazet.

 5) Fix memory leak in __sk_prepare_filter(), from Leon Yu.

 6) Netlink leftover bytes warning message is user triggerable, rate
    limit it.  From Michal Schmidt.

 7) Fix non-linear SKB panic in ipvs, from Peter Christensen.

 8) Congestion window undo needs to be performed even if only never
    retransmitted data is SACK'd, fix from Yuching Cheng.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (24 commits)
  net: filter: fix possible memory leak in __sk_prepare_filter()
  net: ec_bhf: Add runtime dependencies
  tcp: fix cwnd undo on DSACK in F-RTO
  netlink: Only check file credentials for implicit destinations
  ipheth: Add support for iPad 2 and iPad 3
  team: fix mtu setting
  net: fix inet_getid() and ipv6_select_ident() bugs
  net: qmi_wwan: interface #11 in Sierra Wireless MC73xx is not QMI
  net: qmi_wwan: add additional Sierra Wireless QMI devices
  bridge: Prevent insertion of FDB entry with disallowed vlan
  netlink: rate-limit leftover bytes warning and print process name
  bridge: notify user space after fdb update
  net: qmi_wwan: add Netgear AirCard 341U
  net: fix wrong mac_len calculation for vlans
  batman-adv: fix NULL pointer dereferences
  net/mlx4_core: Reset RoCE VF gids when guest driver goes down
  emac: aggregation of v1-2 PLB errors for IER register
  emac: add missing support of 10mbit in emac/rgmii
  can: only rename enabled led triggers when changing the netdev name
  ipvs: Fix panic due to non-linear skb
  ...
This commit is contained in:
Linus Torvalds 2014-06-02 18:16:41 -07:00
commit cae61ba37b
31 changed files with 276 additions and 84 deletions

View File

@ -3153,10 +3153,9 @@ S: Maintained
F: drivers/scsi/eata_pio.* F: drivers/scsi/eata_pio.*
EBTABLES EBTABLES
M: Bart De Schuymer <bart.de.schuymer@pandora.be>
L: netfilter-devel@vger.kernel.org L: netfilter-devel@vger.kernel.org
W: http://ebtables.sourceforge.net/ W: http://ebtables.sourceforge.net/
S: Maintained S: Orphan
F: include/linux/netfilter_bridge/ebt_*.h F: include/linux/netfilter_bridge/ebt_*.h
F: include/uapi/linux/netfilter_bridge/ebt_*.h F: include/uapi/linux/netfilter_bridge/ebt_*.h
F: net/bridge/netfilter/ebt*.c F: net/bridge/netfilter/ebt*.c

View File

@ -97,6 +97,9 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
if (!priv) if (!priv)
return NOTIFY_DONE; return NOTIFY_DONE;
if (!priv->tx_led_trig || !priv->rx_led_trig)
return NOTIFY_DONE;
if (msg == NETDEV_CHANGENAME) { if (msg == NETDEV_CHANGENAME) {
snprintf(name, sizeof(name), "%s-tx", netdev->name); snprintf(name, sizeof(name), "%s-tx", netdev->name);
led_trigger_rename_static(name, priv->tx_led_trig); led_trigger_rename_static(name, priv->tx_led_trig);

View File

@ -39,6 +39,7 @@ source "drivers/net/ethernet/cisco/Kconfig"
config CX_ECAT config CX_ECAT
tristate "Beckhoff CX5020 EtherCAT master support" tristate "Beckhoff CX5020 EtherCAT master support"
depends on PCI depends on PCI
depends on X86 || COMPILE_TEST
---help--- ---help---
Driver for EtherCAT master module located on CCAT FPGA Driver for EtherCAT master module located on CCAT FPGA
that can be found on Beckhoff CX5020, and possibly other of CX that can be found on Beckhoff CX5020, and possibly other of CX

View File

@ -682,10 +682,7 @@ static int mal_probe(struct platform_device *ofdev)
goto fail6; goto fail6;
/* Enable all MAL SERR interrupt sources */ /* Enable all MAL SERR interrupt sources */
if (mal->version == 2) set_mal_dcrn(mal, MAL_IER, MAL_IER_EVENTS);
set_mal_dcrn(mal, MAL_IER, MAL2_IER_EVENTS);
else
set_mal_dcrn(mal, MAL_IER, MAL1_IER_EVENTS);
/* Enable EOB interrupt */ /* Enable EOB interrupt */
mal_enable_eob_irq(mal); mal_enable_eob_irq(mal);

View File

@ -95,24 +95,20 @@
#define MAL_IER 0x02 #define MAL_IER 0x02
/* MAL IER bits */
#define MAL_IER_DE 0x00000010 #define MAL_IER_DE 0x00000010
#define MAL_IER_OTE 0x00000004 #define MAL_IER_OTE 0x00000004
#define MAL_IER_OE 0x00000002 #define MAL_IER_OE 0x00000002
#define MAL_IER_PE 0x00000001 #define MAL_IER_PE 0x00000001
/* MAL V1 IER bits */
#define MAL1_IER_NWE 0x00000008
#define MAL1_IER_SOC_EVENTS MAL1_IER_NWE
#define MAL1_IER_EVENTS (MAL1_IER_SOC_EVENTS | MAL_IER_DE | \
MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
/* MAL V2 IER bits */ /* PLB read/write/timeout errors */
#define MAL2_IER_PT 0x00000080 #define MAL_IER_PTE 0x00000080
#define MAL2_IER_PRE 0x00000040 #define MAL_IER_PRE 0x00000040
#define MAL2_IER_PWE 0x00000020 #define MAL_IER_PWE 0x00000020
#define MAL2_IER_SOC_EVENTS (MAL2_IER_PT | MAL2_IER_PRE | MAL2_IER_PWE)
#define MAL2_IER_EVENTS (MAL2_IER_SOC_EVENTS | MAL_IER_DE | \
MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
#define MAL_IER_SOC_EVENTS (MAL_IER_PTE | MAL_IER_PRE | MAL_IER_PWE)
#define MAL_IER_EVENTS (MAL_IER_SOC_EVENTS | MAL_IER_DE | \
MAL_IER_OTE | MAL_IER_OE | MAL_IER_PE)
#define MAL_TXCASR 0x04 #define MAL_TXCASR 0x04
#define MAL_TXCARR 0x05 #define MAL_TXCARR 0x05

View File

@ -45,6 +45,7 @@
/* RGMIIx_SSR */ /* RGMIIx_SSR */
#define RGMII_SSR_MASK(idx) (0x7 << ((idx) * 8)) #define RGMII_SSR_MASK(idx) (0x7 << ((idx) * 8))
#define RGMII_SSR_10(idx) (0x1 << ((idx) * 8))
#define RGMII_SSR_100(idx) (0x2 << ((idx) * 8)) #define RGMII_SSR_100(idx) (0x2 << ((idx) * 8))
#define RGMII_SSR_1000(idx) (0x4 << ((idx) * 8)) #define RGMII_SSR_1000(idx) (0x4 << ((idx) * 8))
@ -139,6 +140,8 @@ void rgmii_set_speed(struct platform_device *ofdev, int input, int speed)
ssr |= RGMII_SSR_1000(input); ssr |= RGMII_SSR_1000(input);
else if (speed == SPEED_100) else if (speed == SPEED_100)
ssr |= RGMII_SSR_100(input); ssr |= RGMII_SSR_100(input);
else if (speed == SPEED_10)
ssr |= RGMII_SSR_10(input);
out_be32(&p->ssr, ssr); out_be32(&p->ssr, ssr);

View File

@ -2044,6 +2044,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
if (!mlx4_is_slave(dev)) { if (!mlx4_is_slave(dev)) {
mlx4_init_mac_table(dev, &info->mac_table); mlx4_init_mac_table(dev, &info->mac_table);
mlx4_init_vlan_table(dev, &info->vlan_table); mlx4_init_vlan_table(dev, &info->vlan_table);
mlx4_init_roce_gid_table(dev, &info->gid_table);
info->base_qpn = mlx4_get_base_qpn(dev, port); info->base_qpn = mlx4_get_base_qpn(dev, port);
} }

View File

@ -695,6 +695,17 @@ struct mlx4_mac_table {
int max; int max;
}; };
#define MLX4_ROCE_GID_ENTRY_SIZE 16
struct mlx4_roce_gid_entry {
u8 raw[MLX4_ROCE_GID_ENTRY_SIZE];
};
struct mlx4_roce_gid_table {
struct mlx4_roce_gid_entry roce_gids[MLX4_ROCE_MAX_GIDS];
struct mutex mutex;
};
#define MLX4_MAX_VLAN_NUM 128 #define MLX4_MAX_VLAN_NUM 128
#define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2) #define MLX4_VLAN_TABLE_SIZE (MLX4_MAX_VLAN_NUM << 2)
@ -758,6 +769,7 @@ struct mlx4_port_info {
struct device_attribute port_mtu_attr; struct device_attribute port_mtu_attr;
struct mlx4_mac_table mac_table; struct mlx4_mac_table mac_table;
struct mlx4_vlan_table vlan_table; struct mlx4_vlan_table vlan_table;
struct mlx4_roce_gid_table gid_table;
int base_qpn; int base_qpn;
}; };
@ -788,10 +800,6 @@ enum {
MLX4_USE_RR = 1, MLX4_USE_RR = 1,
}; };
struct mlx4_roce_gid_entry {
u8 raw[16];
};
struct mlx4_priv { struct mlx4_priv {
struct mlx4_dev dev; struct mlx4_dev dev;
@ -839,7 +847,6 @@ struct mlx4_priv {
int fs_hash_mode; int fs_hash_mode;
u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS]; u8 virt2phys_pkey[MLX4_MFUNC_MAX][MLX4_MAX_PORTS][MLX4_MAX_PORT_PKEYS];
__be64 slave_node_guids[MLX4_MFUNC_MAX]; __be64 slave_node_guids[MLX4_MFUNC_MAX];
struct mlx4_roce_gid_entry roce_gids[MLX4_MAX_PORTS][MLX4_ROCE_MAX_GIDS];
atomic_t opreq_count; atomic_t opreq_count;
struct work_struct opreq_task; struct work_struct opreq_task;
@ -1140,6 +1147,8 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table); void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table);
void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table); void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table);
void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
struct mlx4_roce_gid_table *table);
void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan); void __mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, u16 vlan);
int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index); int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
@ -1149,6 +1158,7 @@ int mlx4_get_slave_from_resource_id(struct mlx4_dev *dev,
enum mlx4_resource resource_type, enum mlx4_resource resource_type,
u64 resource_id, int *slave); u64 resource_id, int *slave);
void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id); void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave_id);
void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave);
int mlx4_init_resource_tracker(struct mlx4_dev *dev); int mlx4_init_resource_tracker(struct mlx4_dev *dev);
void mlx4_free_resource_tracker(struct mlx4_dev *dev, void mlx4_free_resource_tracker(struct mlx4_dev *dev,

View File

@ -75,6 +75,16 @@ void mlx4_init_vlan_table(struct mlx4_dev *dev, struct mlx4_vlan_table *table)
table->total = 0; table->total = 0;
} }
void mlx4_init_roce_gid_table(struct mlx4_dev *dev,
struct mlx4_roce_gid_table *table)
{
int i;
mutex_init(&table->mutex);
for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++)
memset(table->roce_gids[i].raw, 0, MLX4_ROCE_GID_ENTRY_SIZE);
}
static int validate_index(struct mlx4_dev *dev, static int validate_index(struct mlx4_dev *dev,
struct mlx4_mac_table *table, int index) struct mlx4_mac_table *table, int index)
{ {
@ -584,6 +594,84 @@ int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave, int port)
} }
EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix); EXPORT_SYMBOL_GPL(mlx4_get_base_gid_ix);
static int mlx4_reset_roce_port_gids(struct mlx4_dev *dev, int slave,
int port, struct mlx4_cmd_mailbox *mailbox)
{
struct mlx4_roce_gid_entry *gid_entry_mbox;
struct mlx4_priv *priv = mlx4_priv(dev);
int num_gids, base, offset;
int i, err;
num_gids = mlx4_get_slave_num_gids(dev, slave, port);
base = mlx4_get_base_gid_ix(dev, slave, port);
memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
mutex_lock(&(priv->port[port].gid_table.mutex));
/* Zero-out gids belonging to that slave in the port GID table */
for (i = 0, offset = base; i < num_gids; offset++, i++)
memcpy(priv->port[port].gid_table.roce_gids[offset].raw,
zgid_entry.raw, MLX4_ROCE_GID_ENTRY_SIZE);
/* Now, copy roce port gids table to mailbox for passing to FW */
gid_entry_mbox = (struct mlx4_roce_gid_entry *)mailbox->buf;
for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
memcpy(gid_entry_mbox->raw,
priv->port[port].gid_table.roce_gids[i].raw,
MLX4_ROCE_GID_ENTRY_SIZE);
err = mlx4_cmd(dev, mailbox->dma,
((u32)port) | (MLX4_SET_PORT_GID_TABLE << 8), 1,
MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
mutex_unlock(&(priv->port[port].gid_table.mutex));
return err;
}
void mlx4_reset_roce_gids(struct mlx4_dev *dev, int slave)
{
struct mlx4_active_ports actv_ports;
struct mlx4_cmd_mailbox *mailbox;
int num_eth_ports, err;
int i;
if (slave < 0 || slave > dev->num_vfs)
return;
actv_ports = mlx4_get_active_ports(dev, slave);
for (i = 0, num_eth_ports = 0; i < dev->caps.num_ports; i++) {
if (test_bit(i, actv_ports.ports)) {
if (dev->caps.port_type[i + 1] != MLX4_PORT_TYPE_ETH)
continue;
num_eth_ports++;
}
}
if (!num_eth_ports)
return;
/* have ETH ports. Alloc mailbox for SET_PORT command */
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
return;
for (i = 0; i < dev->caps.num_ports; i++) {
if (test_bit(i, actv_ports.ports)) {
if (dev->caps.port_type[i + 1] != MLX4_PORT_TYPE_ETH)
continue;
err = mlx4_reset_roce_port_gids(dev, slave, i + 1, mailbox);
if (err)
mlx4_warn(dev, "Could not reset ETH port GID table for slave %d, port %d (%d)\n",
slave, i + 1, err);
}
}
mlx4_free_cmd_mailbox(dev, mailbox);
return;
}
static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod, static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
u8 op_mod, struct mlx4_cmd_mailbox *inbox) u8 op_mod, struct mlx4_cmd_mailbox *inbox)
{ {
@ -692,10 +780,12 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
/* 2. Check that do not have duplicates in OTHER /* 2. Check that do not have duplicates in OTHER
* entries in the port GID table * entries in the port GID table
*/ */
mutex_lock(&(priv->port[port].gid_table.mutex));
for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
if (i >= base && i < base + num_gids) if (i >= base && i < base + num_gids)
continue; /* don't compare to slave's current gids */ continue; /* don't compare to slave's current gids */
gid_entry_tbl = &priv->roce_gids[port - 1][i]; gid_entry_tbl = &priv->port[port].gid_table.roce_gids[i];
if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry))) if (!memcmp(gid_entry_tbl->raw, zgid_entry.raw, sizeof(zgid_entry)))
continue; continue;
gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
@ -709,6 +799,7 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
mlx4_warn(dev, "requested gid entry for slave:%d " mlx4_warn(dev, "requested gid entry for slave:%d "
"is a duplicate of gid at index %d\n", "is a duplicate of gid at index %d\n",
slave, i); slave, i);
mutex_unlock(&(priv->port[port].gid_table.mutex));
return -EINVAL; return -EINVAL;
} }
} }
@ -717,16 +808,24 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
/* insert slave GIDs with memcpy, starting at slave's base index */ /* insert slave GIDs with memcpy, starting at slave's base index */
gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++) for (i = 0, offset = base; i < num_gids; gid_entry_mbox++, offset++, i++)
memcpy(priv->roce_gids[port - 1][offset].raw, gid_entry_mbox->raw, 16); memcpy(priv->port[port].gid_table.roce_gids[offset].raw,
gid_entry_mbox->raw, MLX4_ROCE_GID_ENTRY_SIZE);
/* Now, copy roce port gids table to current mailbox for passing to FW */ /* Now, copy roce port gids table to current mailbox for passing to FW */
gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf); gid_entry_mbox = (struct mlx4_roce_gid_entry *)(inbox->buf);
for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++) for (i = 0; i < MLX4_ROCE_MAX_GIDS; gid_entry_mbox++, i++)
memcpy(gid_entry_mbox->raw, priv->roce_gids[port - 1][i].raw, 16); memcpy(gid_entry_mbox->raw,
priv->port[port].gid_table.roce_gids[i].raw,
MLX4_ROCE_GID_ENTRY_SIZE);
break; err = mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
mutex_unlock(&(priv->port[port].gid_table.mutex));
return err;
} }
return mlx4_cmd(dev, inbox->dma, in_mod, op_mod,
return mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE); MLX4_CMD_NATIVE);
} }
@ -1099,7 +1198,8 @@ int mlx4_get_slave_from_roce_gid(struct mlx4_dev *dev, int port, u8 *gid,
num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1; num_vfs = bitmap_weight(slaves_pport.slaves, dev->num_vfs + 1) - 1;
for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) { for (i = 0; i < MLX4_ROCE_MAX_GIDS; i++) {
if (!memcmp(priv->roce_gids[port - 1][i].raw, gid, 16)) { if (!memcmp(priv->port[port].gid_table.roce_gids[i].raw, gid,
MLX4_ROCE_GID_ENTRY_SIZE)) {
found_ix = i; found_ix = i;
break; break;
} }
@ -1187,7 +1287,8 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id,
if (!mlx4_is_master(dev)) if (!mlx4_is_master(dev))
return -EINVAL; return -EINVAL;
memcpy(gid, priv->roce_gids[port - 1][slave_id].raw, 16); memcpy(gid, priv->port[port].gid_table.roce_gids[slave_id].raw,
MLX4_ROCE_GID_ENTRY_SIZE);
return 0; return 0;
} }
EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave); EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);

View File

@ -586,6 +586,7 @@ void mlx4_free_resource_tracker(struct mlx4_dev *dev,
} }
/* free master's vlans */ /* free master's vlans */
i = dev->caps.function; i = dev->caps.function;
mlx4_reset_roce_gids(dev, i);
mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); mutex_lock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
rem_slave_vlans(dev, i); rem_slave_vlans(dev, i);
mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex); mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[i].mutex);
@ -4681,7 +4682,7 @@ static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
{ {
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
mlx4_reset_roce_gids(dev, slave);
mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
rem_slave_vlans(dev, slave); rem_slave_vlans(dev, slave);
rem_slave_macs(dev, slave); rem_slave_macs(dev, slave);

View File

@ -1020,6 +1020,7 @@ static int qlcnic_dcb_peer_app_info(struct net_device *netdev,
struct qlcnic_dcb_cee *peer; struct qlcnic_dcb_cee *peer;
int i; int i;
memset(info, 0, sizeof(*info));
*app_count = 0; *app_count = 0;
if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state)) if (!test_bit(QLCNIC_DCB_STATE, &adapter->dcb->state))

View File

@ -1724,6 +1724,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
* to traverse list in reverse under rcu_read_lock * to traverse list in reverse under rcu_read_lock
*/ */
mutex_lock(&team->lock); mutex_lock(&team->lock);
team->port_mtu_change_allowed = true;
list_for_each_entry(port, &team->port_list, list) { list_for_each_entry(port, &team->port_list, list) {
err = dev_set_mtu(port->dev, new_mtu); err = dev_set_mtu(port->dev, new_mtu);
if (err) { if (err) {
@ -1732,6 +1733,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
goto unwind; goto unwind;
} }
} }
team->port_mtu_change_allowed = false;
mutex_unlock(&team->lock); mutex_unlock(&team->lock);
dev->mtu = new_mtu; dev->mtu = new_mtu;
@ -1741,6 +1743,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
unwind: unwind:
list_for_each_entry_continue_reverse(port, &team->port_list, list) list_for_each_entry_continue_reverse(port, &team->port_list, list)
dev_set_mtu(port->dev, dev->mtu); dev_set_mtu(port->dev, dev->mtu);
team->port_mtu_change_allowed = false;
mutex_unlock(&team->lock); mutex_unlock(&team->lock);
return err; return err;
@ -2851,7 +2854,9 @@ static int team_device_event(struct notifier_block *unused,
break; break;
case NETDEV_PRECHANGEMTU: case NETDEV_PRECHANGEMTU:
/* Forbid to change mtu of underlaying device */ /* Forbid to change mtu of underlaying device */
return NOTIFY_BAD; if (!port->team->port_mtu_change_allowed)
return NOTIFY_BAD;
break;
case NETDEV_PRE_TYPE_CHANGE: case NETDEV_PRE_TYPE_CHANGE:
/* Forbid to change type of underlaying device */ /* Forbid to change type of underlaying device */
return NOTIFY_BAD; return NOTIFY_BAD;

View File

@ -59,6 +59,8 @@
#define USB_PRODUCT_IPHONE_3GS 0x1294 #define USB_PRODUCT_IPHONE_3GS 0x1294
#define USB_PRODUCT_IPHONE_4 0x1297 #define USB_PRODUCT_IPHONE_4 0x1297
#define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPAD 0x129a
#define USB_PRODUCT_IPAD_2 0x12a2
#define USB_PRODUCT_IPAD_3 0x12a6
#define USB_PRODUCT_IPAD_MINI 0x12ab #define USB_PRODUCT_IPAD_MINI 0x12ab
#define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4_VZW 0x129c
#define USB_PRODUCT_IPHONE_4S 0x12a0 #define USB_PRODUCT_IPHONE_4S 0x12a0
@ -106,6 +108,14 @@ static struct usb_device_id ipheth_table[] = {
USB_VENDOR_APPLE, USB_PRODUCT_IPAD, USB_VENDOR_APPLE, USB_PRODUCT_IPAD,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) }, IPHETH_USBINTF_PROTO) },
{ USB_DEVICE_AND_INTERFACE_INFO(
USB_VENDOR_APPLE, USB_PRODUCT_IPAD_2,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) },
{ USB_DEVICE_AND_INTERFACE_INFO(
USB_VENDOR_APPLE, USB_PRODUCT_IPAD_3,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) },
{ USB_DEVICE_AND_INTERFACE_INFO( { USB_DEVICE_AND_INTERFACE_INFO(
USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI, USB_VENDOR_APPLE, USB_PRODUCT_IPAD_MINI,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,

View File

@ -748,11 +748,15 @@ static const struct usb_device_id products[] = {
{QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */
{QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC73xx */ {QMI_FIXED_INTF(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC73xx */
{QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC73xx */ {QMI_FIXED_INTF(0x1199, 0x68c0, 10)}, /* Sierra Wireless MC73xx */
{QMI_FIXED_INTF(0x1199, 0x68c0, 11)}, /* Sierra Wireless MC73xx */
{QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */
{QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */ {QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */
{QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */ {QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */
{QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */ {QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */
{QMI_FIXED_INTF(0x1199, 0x9053, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9054, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9055, 8)}, /* Netgear AirCard 341U */
{QMI_FIXED_INTF(0x1199, 0x9056, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9061, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */ {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)}, /* Alcatel L800MA */
{QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */

View File

@ -826,7 +826,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
if (ret) if (ret)
goto out_remove_mac; goto out_remove_mac;
if (!mvm->bf_allowed_vif && if (!mvm->bf_allowed_vif && false &&
vif->type == NL80211_IFTYPE_STATION && !vif->p2p && vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){ mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BF_UPDATED){
mvm->bf_allowed_vif = mvmvif; mvm->bf_allowed_vif = mvmvif;

View File

@ -194,6 +194,7 @@ struct team {
bool user_carrier_enabled; bool user_carrier_enabled;
bool queue_override_enabled; bool queue_override_enabled;
struct list_head *qom_lists; /* array of queue override mapping lists */ struct list_head *qom_lists; /* array of queue override mapping lists */
bool port_mtu_change_allowed;
struct { struct {
unsigned int count; unsigned int count;
unsigned int interval; /* in ms */ unsigned int interval; /* in ms */

View File

@ -16,9 +16,10 @@ static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb)
} }
enum netlink_skb_flags { enum netlink_skb_flags {
NETLINK_SKB_MMAPED = 0x1, /* Packet data is mmaped */ NETLINK_SKB_MMAPED = 0x1, /* Packet data is mmaped */
NETLINK_SKB_TX = 0x2, /* Packet was sent by userspace */ NETLINK_SKB_TX = 0x2, /* Packet was sent by userspace */
NETLINK_SKB_DELIVERED = 0x4, /* Packet was delivered */ NETLINK_SKB_DELIVERED = 0x4, /* Packet was delivered */
NETLINK_SKB_DST = 0x8, /* Dst set in sendto or sendmsg */
}; };
struct netlink_skb_parms { struct netlink_skb_parms {

View File

@ -177,16 +177,9 @@ static inline void inet_peer_refcheck(const struct inet_peer *p)
/* can be called with or without local BH being disabled */ /* can be called with or without local BH being disabled */
static inline int inet_getid(struct inet_peer *p, int more) static inline int inet_getid(struct inet_peer *p, int more)
{ {
int old, new;
more++; more++;
inet_peer_refcheck(p); inet_peer_refcheck(p);
do { return atomic_add_return(more, &p->ip_id_count) - more;
old = atomic_read(&p->ip_id_count);
new = old + more;
if (!new)
new = 1;
} while (atomic_cmpxchg(&p->ip_id_count, old, new) != old);
return new;
} }
#endif /* _NET_INETPEER_H */ #endif /* _NET_INETPEER_H */

View File

@ -201,8 +201,8 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
} }
if (unlikely(rem > 0)) if (unlikely(rem > 0))
printk(KERN_WARNING "netlink: %d bytes leftover after parsing " pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
"attributes.\n", rem); rem, current->comm);
err = 0; err = 0;
errout: errout:

View File

@ -415,7 +415,7 @@ batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv)
hlist_for_each_entry_rcu(tmp_orig_node, hlist_for_each_entry_rcu(tmp_orig_node,
&bat_priv->mcast.want_all_ipv4_list, &bat_priv->mcast.want_all_ipv4_list,
mcast_want_all_ipv4_node) { mcast_want_all_ipv4_node) {
if (!atomic_inc_not_zero(&orig_node->refcount)) if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
continue; continue;
orig_node = tmp_orig_node; orig_node = tmp_orig_node;
@ -442,7 +442,7 @@ batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv)
hlist_for_each_entry_rcu(tmp_orig_node, hlist_for_each_entry_rcu(tmp_orig_node,
&bat_priv->mcast.want_all_ipv6_list, &bat_priv->mcast.want_all_ipv6_list,
mcast_want_all_ipv6_node) { mcast_want_all_ipv6_node) {
if (!atomic_inc_not_zero(&orig_node->refcount)) if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
continue; continue;
orig_node = tmp_orig_node; orig_node = tmp_orig_node;
@ -493,7 +493,7 @@ batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv)
hlist_for_each_entry_rcu(tmp_orig_node, hlist_for_each_entry_rcu(tmp_orig_node,
&bat_priv->mcast.want_all_unsnoopables_list, &bat_priv->mcast.want_all_unsnoopables_list,
mcast_want_all_unsnoopables_node) { mcast_want_all_unsnoopables_node) {
if (!atomic_inc_not_zero(&orig_node->refcount)) if (!atomic_inc_not_zero(&tmp_orig_node->refcount))
continue; continue;
orig_node = tmp_orig_node; orig_node = tmp_orig_node;

View File

@ -7519,9 +7519,9 @@ int __init l2cap_init(void)
l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
NULL, &l2cap_debugfs_fops); NULL, &l2cap_debugfs_fops);
debugfs_create_u16("l2cap_le_max_credits", 0466, bt_debugfs, debugfs_create_u16("l2cap_le_max_credits", 0644, bt_debugfs,
&le_max_credits); &le_max_credits);
debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs, debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs,
&le_default_mps); &le_default_mps);
bt_6lowpan_init(); bt_6lowpan_init();

View File

@ -487,6 +487,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
{ {
struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)]; struct hlist_head *head = &br->hash[br_mac_hash(addr, vid)];
struct net_bridge_fdb_entry *fdb; struct net_bridge_fdb_entry *fdb;
bool fdb_modified = false;
/* some users want to always flood. */ /* some users want to always flood. */
if (hold_time(br) == 0) if (hold_time(br) == 0)
@ -507,10 +508,15 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
source->dev->name); source->dev->name);
} else { } else {
/* fastpath: update of existing entry */ /* fastpath: update of existing entry */
fdb->dst = source; if (unlikely(source != fdb->dst)) {
fdb->dst = source;
fdb_modified = true;
}
fdb->updated = jiffies; fdb->updated = jiffies;
if (unlikely(added_by_user)) if (unlikely(added_by_user))
fdb->added_by_user = 1; fdb->added_by_user = 1;
if (unlikely(fdb_modified))
fdb_notify(br, fdb, RTM_NEWNEIGH);
} }
} else { } else {
spin_lock(&br->hash_lock); spin_lock(&br->hash_lock);

View File

@ -147,8 +147,8 @@ static int br_handle_local_finish(struct sk_buff *skb)
struct net_bridge_port *p = br_port_get_rcu(skb->dev); struct net_bridge_port *p = br_port_get_rcu(skb->dev);
u16 vid = 0; u16 vid = 0;
br_vlan_get_tag(skb, &vid); /* check if vlan is allowed, to avoid spoofing */
if (p->flags & BR_LEARNING) if (p->flags & BR_LEARNING && br_should_learn(p, skb, &vid))
br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false); br_fdb_update(p->br, p, eth_hdr(skb)->h_source, vid, false);
return 0; /* process further */ return 0; /* process further */
} }

View File

@ -581,6 +581,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
struct sk_buff *skb, u16 *vid); struct sk_buff *skb, u16 *vid);
bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v, bool br_allowed_egress(struct net_bridge *br, const struct net_port_vlans *v,
const struct sk_buff *skb); const struct sk_buff *skb);
bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid);
struct sk_buff *br_handle_vlan(struct net_bridge *br, struct sk_buff *br_handle_vlan(struct net_bridge *br,
const struct net_port_vlans *v, const struct net_port_vlans *v,
struct sk_buff *skb); struct sk_buff *skb);
@ -648,6 +649,12 @@ static inline bool br_allowed_egress(struct net_bridge *br,
return true; return true;
} }
static inline bool br_should_learn(struct net_bridge_port *p,
struct sk_buff *skb, u16 *vid)
{
return true;
}
static inline struct sk_buff *br_handle_vlan(struct net_bridge *br, static inline struct sk_buff *br_handle_vlan(struct net_bridge *br,
const struct net_port_vlans *v, const struct net_port_vlans *v,
struct sk_buff *skb) struct sk_buff *skb)

View File

@ -241,6 +241,34 @@ bool br_allowed_egress(struct net_bridge *br,
return false; return false;
} }
/* Called under RCU */
bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
{
struct net_bridge *br = p->br;
struct net_port_vlans *v;
if (!br->vlan_enabled)
return true;
v = rcu_dereference(p->vlan_info);
if (!v)
return false;
br_vlan_get_tag(skb, vid);
if (!*vid) {
*vid = br_get_pvid(v);
if (*vid == VLAN_N_VID)
return false;
return true;
}
if (test_bit(*vid, v->vlan_bitmap))
return true;
return false;
}
/* Must be protected by RTNL. /* Must be protected by RTNL.
* Must be called with vid in range from 1 to 4094 inclusive. * Must be called with vid in range from 1 to 4094 inclusive.
*/ */

View File

@ -2283,8 +2283,8 @@ EXPORT_SYMBOL(skb_checksum_help);
__be16 skb_network_protocol(struct sk_buff *skb, int *depth) __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
{ {
unsigned int vlan_depth = skb->mac_len;
__be16 type = skb->protocol; __be16 type = skb->protocol;
int vlan_depth = skb->mac_len;
/* Tunnel gso handlers can set protocol to ethernet. */ /* Tunnel gso handlers can set protocol to ethernet. */
if (type == htons(ETH_P_TEB)) { if (type == htons(ETH_P_TEB)) {
@ -2297,15 +2297,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
type = eth->h_proto; type = eth->h_proto;
} }
while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { /* if skb->protocol is 802.1Q/AD then the header should already be
struct vlan_hdr *vh; * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
* ETH_HLEN otherwise
*/
if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
if (vlan_depth) {
if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN)))
return 0;
vlan_depth -= VLAN_HLEN;
} else {
vlan_depth = ETH_HLEN;
}
do {
struct vlan_hdr *vh;
if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) if (unlikely(!pskb_may_pull(skb,
return 0; vlan_depth + VLAN_HLEN)))
return 0;
vh = (struct vlan_hdr *)(skb->data + vlan_depth); vh = (struct vlan_hdr *)(skb->data + vlan_depth);
type = vh->h_vlan_encapsulated_proto; type = vh->h_vlan_encapsulated_proto;
vlan_depth += VLAN_HLEN; vlan_depth += VLAN_HLEN;
} while (type == htons(ETH_P_8021Q) ||
type == htons(ETH_P_8021AD));
} }
*depth = vlan_depth; *depth = vlan_depth;

View File

@ -1559,8 +1559,13 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp,
fp->jited = 0; fp->jited = 0;
err = sk_chk_filter(fp->insns, fp->len); err = sk_chk_filter(fp->insns, fp->len);
if (err) if (err) {
if (sk != NULL)
sk_filter_uncharge(sk, fp);
else
kfree(fp);
return ERR_PTR(err); return ERR_PTR(err);
}
/* Probe if we can JIT compile the filter and if so, do /* Probe if we can JIT compile the filter and if so, do
* the compilation of the filter. * the compilation of the filter.

View File

@ -2684,13 +2684,12 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack)
bool recovered = !before(tp->snd_una, tp->high_seq); bool recovered = !before(tp->snd_una, tp->high_seq);
if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */ if (tp->frto) { /* F-RTO RFC5682 sec 3.1 (sack enhanced version). */
if (flag & FLAG_ORIG_SACK_ACKED) { /* Step 3.b. A timeout is spurious if not all data are
/* Step 3.b. A timeout is spurious if not all data are * lost, i.e., never-retransmitted data are (s)acked.
* lost, i.e., never-retransmitted data are (s)acked. */
*/ if (tcp_try_undo_loss(sk, flag & FLAG_ORIG_SACK_ACKED))
tcp_try_undo_loss(sk, true);
return; return;
}
if (after(tp->snd_nxt, tp->high_seq) && if (after(tp->snd_nxt, tp->high_seq) &&
(flag & FLAG_DATA_SACKED || is_dupack)) { (flag & FLAG_DATA_SACKED || is_dupack)) {
tp->frto = 0; /* Loss was real: 2nd part of step 3.a */ tp->frto = 0; /* Loss was real: 2nd part of step 3.a */

View File

@ -12,7 +12,7 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
{ {
static atomic_t ipv6_fragmentation_id; static atomic_t ipv6_fragmentation_id;
struct in6_addr addr; struct in6_addr addr;
int old, new; int ident;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
struct inet_peer *peer; struct inet_peer *peer;
@ -26,15 +26,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
return; return;
} }
#endif #endif
do { ident = atomic_inc_return(&ipv6_fragmentation_id);
old = atomic_read(&ipv6_fragmentation_id);
new = old + 1;
if (!new)
new = 1;
} while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
addr = rt->rt6i_dst.addr; addr = rt->rt6i_dst.addr;
addr.s6_addr32[0] ^= (__force __be32)new; addr.s6_addr32[0] ^= (__force __be32)ident;
fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32)); fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32));
} }
EXPORT_SYMBOL(ipv6_select_ident); EXPORT_SYMBOL(ipv6_select_ident);

View File

@ -1392,15 +1392,19 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
if (ipip) { if (ipip) {
__be32 info = ic->un.gateway; __be32 info = ic->un.gateway;
__u8 type = ic->type;
__u8 code = ic->code;
/* Update the MTU */ /* Update the MTU */
if (ic->type == ICMP_DEST_UNREACH && if (ic->type == ICMP_DEST_UNREACH &&
ic->code == ICMP_FRAG_NEEDED) { ic->code == ICMP_FRAG_NEEDED) {
struct ip_vs_dest *dest = cp->dest; struct ip_vs_dest *dest = cp->dest;
u32 mtu = ntohs(ic->un.frag.mtu); u32 mtu = ntohs(ic->un.frag.mtu);
__be16 frag_off = cih->frag_off;
/* Strip outer IP and ICMP, go to IPIP header */ /* Strip outer IP and ICMP, go to IPIP header */
__skb_pull(skb, ihl + sizeof(_icmph)); if (pskb_pull(skb, ihl + sizeof(_icmph)) == NULL)
goto ignore_ipip;
offset2 -= ihl + sizeof(_icmph); offset2 -= ihl + sizeof(_icmph);
skb_reset_network_header(skb); skb_reset_network_header(skb);
IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n",
@ -1408,7 +1412,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
ipv4_update_pmtu(skb, dev_net(skb->dev), ipv4_update_pmtu(skb, dev_net(skb->dev),
mtu, 0, 0, 0, 0); mtu, 0, 0, 0, 0);
/* Client uses PMTUD? */ /* Client uses PMTUD? */
if (!(cih->frag_off & htons(IP_DF))) if (!(frag_off & htons(IP_DF)))
goto ignore_ipip; goto ignore_ipip;
/* Prefer the resulting PMTU */ /* Prefer the resulting PMTU */
if (dest) { if (dest) {
@ -1427,12 +1431,13 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
/* Strip outer IP, ICMP and IPIP, go to IP header of /* Strip outer IP, ICMP and IPIP, go to IP header of
* original request. * original request.
*/ */
__skb_pull(skb, offset2); if (pskb_pull(skb, offset2) == NULL)
goto ignore_ipip;
skb_reset_network_header(skb); skb_reset_network_header(skb);
IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n",
&ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr,
ic->type, ic->code, ntohl(info)); type, code, ntohl(info));
icmp_send(skb, ic->type, ic->code, info); icmp_send(skb, type, code, info);
/* ICMP can be shorter but anyways, account it */ /* ICMP can be shorter but anyways, account it */
ip_vs_out_stats(cp, skb); ip_vs_out_stats(cp, skb);

View File

@ -1373,7 +1373,9 @@ retry:
bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
struct user_namespace *user_ns, int cap) struct user_namespace *user_ns, int cap)
{ {
return sk_ns_capable(nsp->sk, user_ns, cap); return ((nsp->flags & NETLINK_SKB_DST) ||
file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) &&
ns_capable(user_ns, cap);
} }
EXPORT_SYMBOL(__netlink_ns_capable); EXPORT_SYMBOL(__netlink_ns_capable);
@ -2293,6 +2295,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
struct scm_cookie scm; struct scm_cookie scm;
u32 netlink_skb_flags = 0;
if (msg->msg_flags&MSG_OOB) if (msg->msg_flags&MSG_OOB)
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -2314,6 +2317,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if ((dst_group || dst_portid) && if ((dst_group || dst_portid) &&
!netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND))
goto out; goto out;
netlink_skb_flags |= NETLINK_SKB_DST;
} else { } else {
dst_portid = nlk->dst_portid; dst_portid = nlk->dst_portid;
dst_group = nlk->dst_group; dst_group = nlk->dst_group;
@ -2343,6 +2347,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).portid = nlk->portid; NETLINK_CB(skb).portid = nlk->portid;
NETLINK_CB(skb).dst_group = dst_group; NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).creds = siocb->scm->creds; NETLINK_CB(skb).creds = siocb->scm->creds;
NETLINK_CB(skb).flags = netlink_skb_flags;
err = -EFAULT; err = -EFAULT;
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {