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

Merge in late fixes in preparation for the net-next PR.

Conflicts:

drivers/dpll/dpll_core.c
drivers/dpll/dpll_netlink.c
  33f016b23a ("dpll: fix NULL deref in dpll_device_ops() during teardown race")
  b1d0c41208 ("dpll: add STATE_CONNECTED_OVERRIDE pin capability")
https://lore.kernel.org/aoR9YYY2P5--3x0N@sirena.org.uk
https://lore.kernel.org/aoR9VmKllVGwmQn_@sirena.org.uk

No adjacent changes.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2026-08-18 10:42:15 -07:00
68 changed files with 710 additions and 383 deletions

View File

@@ -876,14 +876,12 @@ int
dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv)
{
const struct dpll_device_ops *dev_ops;
int ret;
if (WARN_ON(!ops) ||
WARN_ON(!ops->state_on_dpll_get) ||
WARN_ON(!ops->direction_get) ||
WARN_ON(ops->measured_freq_get &&
(!dpll_device_ops(dpll)->freq_monitor_get ||
!dpll_device_ops(dpll)->freq_monitor_set)) ||
WARN_ON(ops->supported_ffo && !ops->ffo_get) ||
WARN_ON((pin->prop.capabilities &
DPLL_PIN_CAPABILITIES_STATE_CONNECTED_OVERRIDE) &&
@@ -893,6 +891,14 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
mutex_lock(&dpll_lock);
dev_ops = dpll_device_ops(dpll);
if (WARN_ON(ops->measured_freq_get &&
(!dev_ops || !dev_ops->freq_monitor_get ||
!dev_ops->freq_monitor_set))) {
ret = -EINVAL;
goto out_unlock;
}
/*
* For pins identified via firmware (pin->fwnode), allow registration
* even if the pin's (module, clock_id) differs from the target DPLL.
@@ -1085,12 +1091,8 @@ EXPORT_SYMBOL_GPL(dpll_pin_ref_sync_pair_add);
static struct dpll_device_registration *
dpll_device_registration_first(struct dpll_device *dpll)
{
struct dpll_device_registration *reg;
reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list,
struct dpll_device_registration, list);
WARN_ON(!reg);
return reg;
return list_first_entry_or_null((struct list_head *)&dpll->registration_list,
struct dpll_device_registration, list);
}
void *dpll_priv(struct dpll_device *dpll)
@@ -1098,6 +1100,8 @@ void *dpll_priv(struct dpll_device *dpll)
struct dpll_device_registration *reg;
reg = dpll_device_registration_first(dpll);
if (!reg)
return NULL;
return reg->priv;
}
@@ -1106,6 +1110,8 @@ const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll)
struct dpll_device_registration *reg;
reg = dpll_device_registration_first(dpll);
if (!reg)
return NULL;
return reg->ops;
}

View File

@@ -66,6 +66,22 @@ static bool dpll_pin_available(struct dpll_pin *pin)
return false;
}
static bool dpll_device_registered(struct dpll_device *dpll)
{
return dpll_device_ops(dpll);
}
static struct dpll_pin_ref *dpll_pin_first_registered_ref(struct dpll_pin *pin)
{
struct dpll_pin_ref *ref;
unsigned long i;
xa_for_each(&pin->dpll_refs, i, ref)
if (dpll_device_registered(ref->dpll))
return ref;
return NULL;
}
/**
* dpll_msg_add_pin_handle - attach pin handle attribute to a given message
* @msg: pointer to sk_buff message to attach a pin handle
@@ -656,6 +672,8 @@ dpll_msg_add_pin_dplls(struct sk_buff *msg, struct dpll_pin *pin,
int ret;
xa_for_each(&pin->dpll_refs, index, ref) {
if (!dpll_device_registered(ref->dpll))
continue;
attr = nla_nest_start(msg, DPLL_A_PIN_PARENT_DEVICE);
if (!attr)
return -EMSGSIZE;
@@ -700,9 +718,10 @@ dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin,
int ret;
ref = dpll_pin_own_dpll_ref_first(pin);
if (!ref || !dpll_device_registered(ref->dpll))
ref = dpll_pin_first_registered_ref(pin);
if (!ref)
ref = dpll_xa_ref_dpll_first(&pin->dpll_refs);
ASSERT_NOT_NULL(ref);
return -ENODEV;
ret = dpll_msg_add_pin_handle(msg, pin);
if (ret)
@@ -1090,7 +1109,7 @@ dpll_pin_freq_set(struct dpll_pin *pin, struct nlattr *a,
}
ref = dpll_pin_own_dpll_ref_first(pin);
if (!ref) {
if (!ref || !dpll_device_registered(ref->dpll)) {
NL_SET_ERR_MSG(extack, "pin owner dpll not found");
return -ENODEV;
}
@@ -1136,7 +1155,7 @@ dpll_pin_esync_set(struct dpll_pin *pin, struct nlattr *a,
int ret, i;
ref = dpll_pin_own_dpll_ref_first(pin);
if (!ref) {
if (!ref || !dpll_device_registered(ref->dpll)) {
NL_SET_ERR_MSG(extack, "pin owner dpll not found");
return -ENODEV;
}
@@ -1201,7 +1220,7 @@ dpll_pin_ref_sync_state_set(struct dpll_pin *pin,
return -EINVAL;
}
ref = dpll_pin_own_dpll_ref_first(pin);
if (!ref) {
if (!ref || !dpll_device_registered(ref->dpll)) {
NL_SET_ERR_MSG(extack, "pin owner dpll not found");
return -ENODEV;
}
@@ -1416,7 +1435,7 @@ dpll_pin_phase_adj_set(struct dpll_pin *pin, struct nlattr *phase_adj_attr,
}
ref = dpll_pin_own_dpll_ref_first(pin);
if (!ref) {
if (!ref || !dpll_device_registered(ref->dpll)) {
NL_SET_ERR_MSG(extack, "pin owner dpll not found");
return -ENODEV;
}
@@ -1468,7 +1487,7 @@ dpll_pin_parent_device_set(struct dpll_pin *pin, struct nlattr *parent_nest,
return -EINVAL;
}
pdpll_idx = nla_get_u32(tb[DPLL_A_PIN_PARENT_ID]);
dpll = xa_load(&dpll_device_xa, pdpll_idx);
dpll = dpll_device_get_by_id(pdpll_idx);
if (!dpll) {
NL_SET_ERR_MSG(extack, "parent device not found");
return -EINVAL;
@@ -1760,6 +1779,10 @@ int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
ret = dpll_cmd_pin_get_one(skb, pin, cb->extack);
if (ret) {
genlmsg_cancel(skb, hdr);
if (ret == -ENODEV) {
ret = 0;
continue;
}
break;
}
genlmsg_end(skb, hdr);

View File

@@ -220,7 +220,7 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
struct bonding *bond = netdev_priv(bond_dev);
struct bond_opt_value newval;
int miimon = 0;
int err;
int err = 0;
if (!data)
return 0;

View File

@@ -2219,7 +2219,7 @@ int b53_fdb_dump(struct dsa_switch *ds, int port,
mutex_unlock(&priv->arl_mutex);
return 0;
return ret;
}
EXPORT_SYMBOL(b53_fdb_dump);

View File

@@ -305,13 +305,16 @@ static bool mv88e6352_pcs_link_check(struct marvell_c22_pcs *mpcs)
struct mv88e6xxx_port *port = mpcs->port;
struct mv88e6xxx_chip *chip = port->chip;
u8 cmode;
int err;
/* Port 4 can be in auto-media mode. Check that the port is
* associated with the mpcs.
*/
mv88e6xxx_reg_lock(chip);
chip->info->ops->port_get_cmode(chip, port->port, &cmode);
err = chip->info->ops->port_get_cmode(chip, port->port, &cmode);
mv88e6xxx_reg_unlock(chip);
if (err)
return false;
return cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX ||
cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||

View File

@@ -321,7 +321,7 @@ void rtl83xx_reset_assert(struct realtek_priv *priv)
"Failed to assert the switch reset control: %pe\n",
ERR_PTR(ret));
gpiod_set_value(priv->reset, true);
gpiod_set_value_cansleep(priv->reset, true);
}
void rtl83xx_reset_deassert(struct realtek_priv *priv)
@@ -334,7 +334,7 @@ void rtl83xx_reset_deassert(struct realtek_priv *priv)
"Failed to deassert the switch reset control: %pe\n",
ERR_PTR(ret));
gpiod_set_value(priv->reset, false);
gpiod_set_value_cansleep(priv->reset, false);
}
/**

View File

@@ -261,8 +261,7 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct hinic3_sq_task *task,
((struct udphdr *)skb_transport_header(skb))->dest !=
VXLAN_OFFLOAD_PORT_LE) {
/* Unsupported tunnel packet, disable csum offload */
skb_checksum_help(skb);
return 0;
return skb_checksum_help(skb);
}
}
@@ -412,6 +411,10 @@ static u32 hinic3_tx_offload(struct sk_buff *skb, struct hinic3_sq_task *task,
offload |= HINIC3_TX_OFFLOAD_TSO;
} else {
tso_cs_en = hinic3_tx_csum(txq, task, skb);
if (tso_cs_en < 0) {
offload = HINIC3_TX_OFFLOAD_INVALID;
return offload;
}
if (tso_cs_en)
offload |= HINIC3_TX_OFFLOAD_CSUM;
}
@@ -545,6 +548,7 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
skb->len = MIN_SKB_LEN;
}
offload = hinic3_tx_offload(skb, &task, &queue_info, txq);
num_sge = skb_shinfo(skb)->nr_frags + 1;
/* assume normal wqe format + 1 wqebb for task info */
wqebb_cnt = num_sge + 1;
@@ -560,7 +564,6 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
offload = hinic3_tx_offload(skb, &task, &queue_info, txq);
if (unlikely(offload == HINIC3_TX_OFFLOAD_INVALID)) {
goto err_drop_pkt;
} else if (!offload) {

View File

@@ -35,6 +35,7 @@ int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
{
unsigned long flags;
netdev_lock(mal->napi.dev);
spin_lock_irqsave(&mal->lock, flags);
MAL_DBG(mal, "reg(%08x, %08x)" NL,
@@ -44,18 +45,20 @@ int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
if ((mal->tx_chan_mask & commac->tx_chan_mask) ||
(mal->rx_chan_mask & commac->rx_chan_mask)) {
spin_unlock_irqrestore(&mal->lock, flags);
netdev_unlock(mal->napi.dev);
printk(KERN_WARNING "mal%d: COMMAC channels conflict!\n",
mal->index);
return -EBUSY;
}
if (list_empty(&mal->list))
napi_enable(&mal->napi);
napi_enable_locked(&mal->napi);
mal->tx_chan_mask |= commac->tx_chan_mask;
mal->rx_chan_mask |= commac->rx_chan_mask;
list_add(&commac->list, &mal->list);
spin_unlock_irqrestore(&mal->lock, flags);
netdev_unlock(mal->napi.dev);
return 0;
}
@@ -64,7 +67,9 @@ void mal_unregister_commac(struct mal_instance *mal,
struct mal_commac *commac)
{
unsigned long flags;
bool disable_napi;
netdev_lock(mal->napi.dev);
spin_lock_irqsave(&mal->lock, flags);
MAL_DBG(mal, "unreg(%08x, %08x)" NL,
@@ -73,10 +78,12 @@ void mal_unregister_commac(struct mal_instance *mal,
mal->tx_chan_mask &= ~commac->tx_chan_mask;
mal->rx_chan_mask &= ~commac->rx_chan_mask;
list_del_init(&commac->list);
if (list_empty(&mal->list))
napi_disable(&mal->napi);
disable_napi = list_empty(&mal->list);
spin_unlock_irqrestore(&mal->lock, flags);
if (disable_napi)
napi_disable_locked(&mal->napi);
netdev_unlock(mal->napi.dev);
}
int mal_set_rcbs(struct mal_instance *mal, int channel, unsigned long size)

View File

@@ -1890,27 +1890,18 @@ static int ice_devlink_nvm_snapshot(struct devlink *devlink,
*/
for (i = 0; i < num_blks; i++) {
u32 read_sz = min_t(u32, ICE_DEVLINK_READ_BLK_SIZE, left);
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status) {
dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
status, hw->adminq.sq_last_status);
NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
vfree(nvm_data);
return -EIO;
}
enum libie_aq_err read_aq_err = LIBIE_AQ_RC_OK;
status = ice_read_flat_nvm(hw, i * ICE_DEVLINK_READ_BLK_SIZE,
&read_sz, tmp, read_shadow_ram);
&read_sz, tmp, read_shadow_ram,
&read_aq_err);
if (status) {
dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
read_sz, status, hw->adminq.sq_last_status);
read_sz, status, read_aq_err);
NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
ice_release_nvm(hw);
vfree(nvm_data);
return -EIO;
}
ice_release_nvm(hw);
tmp += read_sz;
left -= read_sz;
@@ -1943,6 +1934,7 @@ static int ice_devlink_nvm_read(struct devlink *devlink,
struct netlink_ext_ack *extack,
u64 offset, u32 size, u8 *data)
{
enum libie_aq_err read_aq_err = LIBIE_AQ_RC_OK;
struct ice_pf *pf = devlink_priv(devlink);
struct device *dev = ice_pf_to_dev(pf);
struct ice_hw *hw = &pf->hw;
@@ -1966,24 +1958,14 @@ static int ice_devlink_nvm_read(struct devlink *devlink,
return -ERANGE;
}
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status) {
dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
status, hw->adminq.sq_last_status);
NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
return -EIO;
}
status = ice_read_flat_nvm(hw, (u32)offset, &size, data,
read_shadow_ram);
read_shadow_ram, &read_aq_err);
if (status) {
dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n",
size, status, hw->adminq.sq_last_status);
size, status, read_aq_err);
NL_SET_ERR_MSG_MOD(extack, "Failed to read NVM contents");
ice_release_nvm(hw);
return -EIO;
}
ice_release_nvm(hw);
return 0;
}

View File

@@ -853,6 +853,7 @@ static int
ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
u8 *bytes)
{
enum libie_aq_err read_aq_err = LIBIE_AQ_RC_OK;
struct ice_pf *pf = ice_netdev_to_pf(netdev);
struct ice_hw *hw = &pf->hw;
struct device *dev;
@@ -869,24 +870,15 @@ ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
if (!buf)
return -ENOMEM;
ret = ice_acquire_nvm(hw, ICE_RES_READ);
ret = ice_read_flat_nvm(hw, eeprom->offset, &eeprom->len, buf,
false, &read_aq_err);
if (ret) {
dev_err(dev, "ice_acquire_nvm failed, err %d aq_err %s\n",
ret, libie_aq_str(hw->adminq.sq_last_status));
dev_err(dev, "ice_read_flat_nvm failed, err %d aq_err %s\n",
ret, libie_aq_str(read_aq_err));
goto out;
}
ret = ice_read_flat_nvm(hw, eeprom->offset, &eeprom->len, buf,
false);
if (ret) {
dev_err(dev, "ice_read_flat_nvm failed, err %d aq_err %s\n",
ret, libie_aq_str(hw->adminq.sq_last_status));
goto release;
}
memcpy(bytes, buf, eeprom->len);
release:
ice_release_nvm(hw);
out:
kfree(buf);
return ret;

View File

@@ -2871,6 +2871,9 @@ int ice_vsi_release(struct ice_vsi *vsi)
return -ENODEV;
pf = vsi->back;
if (ice_is_vsi_dflt_vsi(vsi))
ice_clear_dflt_vsi(vsi);
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
ice_rss_clean(vsi);

View File

@@ -53,17 +53,27 @@ int ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
* @length: (in) number of bytes to read; (out) number of bytes actually read
* @data: buffer to return data in (sized to fit the specified length)
* @read_shadow_ram: if true, read from shadow RAM instead of NVM
* @read_aq_err: if non-NULL, receives the AQ error status of the failing read
*
* Reads a portion of the NVM, as a flat memory space. This function correctly
* breaks read requests across Shadow RAM sectors and ensures that no single
* read request exceeds the maximum 4KB read for a single AdminQ command.
*
* FW caps the read lock at a maximum of 3000ms, so a read spanning multiple
* 4KB sectors cannot be done under a single lock without FW reclaiming it
* mid-read. The NVM lock is therefore acquired and released around each AQ
* read, so this function must be called without the lock held.
*
* Since ice_release_nvm() issues an AQ command that overwrites
* hw->adminq.sq_last_status, callers that need the failing read's AQ error
* must use @read_aq_err rather than inspecting sq_last_status afterwards.
*
* Returns a status code on failure. Note that the data pointer may be
* partially updated if some reads succeed before a failure.
*/
int
ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
bool read_shadow_ram)
bool read_shadow_ram, enum libie_aq_err *read_aq_err)
{
u32 inlen = *length;
u32 bytes_read = 0;
@@ -92,12 +102,30 @@ ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
last_cmd = !(bytes_read + read_size < inlen);
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status) {
ice_debug(hw, ICE_DBG_NVM, "Failed to acquire NVM lock, err %d aq_err %s\n",
status, libie_aq_str(hw->adminq.sq_last_status));
break;
}
status = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT,
offset, read_size,
data + bytes_read, last_cmd,
read_shadow_ram, NULL);
if (status)
if (status) {
/* Capture the read's AQ error before ice_release_nvm()
* issues its own AQ command and overwrites
* sq_last_status.
*/
if (read_aq_err)
*read_aq_err = hw->adminq.sq_last_status;
ice_release_nvm(hw);
break;
}
ice_release_nvm(hw);
bytes_read += read_size;
offset += read_size;
@@ -177,14 +205,19 @@ int ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd)
}
/**
* ice_read_sr_word_aq - Reads Shadow RAM via AQ
* ice_read_sr_word - Reads Shadow RAM word
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
* @data: word read from the Shadow RAM
*
* Reads one 16 bit word from the Shadow RAM using ice_read_flat_nvm.
*
* The NVM lock is acquired and released internally by ice_read_flat_nvm()
* around the FW read, so this function must be called without the lock held.
*
* Return: zero on success, or a negative error code on failure.
*/
static int ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
int ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
{
u32 bytes = sizeof(u16);
__le16 data_local;
@@ -194,7 +227,7 @@ static int ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
* Shadow RAM sector restrictions necessary when reading from the NVM.
*/
status = ice_read_flat_nvm(hw, offset * sizeof(u16), &bytes,
(__force u8 *)&data_local, true);
(__force u8 *)&data_local, true, NULL);
if (status)
return status;
@@ -330,13 +363,8 @@ ice_read_flash_module(struct ice_hw *hw, enum ice_bank_select bank, u16 module,
return -EINVAL;
}
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status)
return status;
status = ice_read_flat_nvm(hw, start + offset, &length, data, false);
ice_release_nvm(hw);
status = ice_read_flat_nvm(hw, start + offset, &length, data, false,
NULL);
return status;
}
@@ -418,27 +446,6 @@ ice_read_netlist_module(struct ice_hw *hw, enum ice_bank_select bank, u32 offset
return status;
}
/**
* ice_read_sr_word - Reads Shadow RAM word and acquire NVM if necessary
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
* @data: word read from the Shadow RAM
*
* Reads one 16 bit word from the Shadow RAM using the ice_read_sr_word_aq.
*/
int ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
{
int status;
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (!status) {
status = ice_read_sr_word_aq(hw, offset, data);
ice_release_nvm(hw);
}
return status;
}
/**
* ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA
* @hw: pointer to hardware structure
@@ -856,20 +863,18 @@ int ice_get_inactive_netlist_ver(struct ice_hw *hw, struct ice_netlist_info *net
static int ice_discover_flash_size(struct ice_hw *hw)
{
u32 min_size = 0, max_size = ICE_AQC_NVM_MAX_OFFSET + 1;
int status;
status = ice_acquire_nvm(hw, ICE_RES_READ);
if (status)
return status;
int status = 0;
while ((max_size - min_size) > 1) {
enum libie_aq_err read_aq_err = LIBIE_AQ_RC_OK;
u32 offset = (max_size + min_size) / 2;
u32 len = 1;
u8 data;
status = ice_read_flat_nvm(hw, offset, &len, &data, false);
status = ice_read_flat_nvm(hw, offset, &len, &data, false,
&read_aq_err);
if (status == -EIO &&
hw->adminq.sq_last_status == LIBIE_AQ_RC_EINVAL) {
read_aq_err == LIBIE_AQ_RC_EINVAL) {
ice_debug(hw, ICE_DBG_NVM, "%s: New upper bound of %u bytes\n",
__func__, offset);
status = 0;
@@ -880,7 +885,7 @@ static int ice_discover_flash_size(struct ice_hw *hw)
min_size = offset;
} else {
/* an unexpected error occurred */
goto err_read_flat_nvm;
return status;
}
}
@@ -888,9 +893,6 @@ static int ice_discover_flash_size(struct ice_hw *hw)
hw->flash.flash_size = max_size;
err_read_flat_nvm:
ice_release_nvm(hw);
return status;
}

View File

@@ -19,7 +19,7 @@ int ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
bool read_shadow_ram, struct ice_sq_cd *cd);
int
ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
bool read_shadow_ram);
bool read_shadow_ram, enum libie_aq_err *read_aq_err);
int
ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
u16 module_type);

View File

@@ -4808,15 +4808,12 @@ static int ice_ptp_prep_phy_adj_ll_e810(struct ice_hw *hw, s32 adj)
!FIELD_GET(REG_LL_PROXY_H_EXEC, val),
10, REG_LL_PROXY_H_TIMEOUT_US, false, hw,
REG_LL_PROXY_H);
if (err) {
ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY timer adjustment using low latency interface\n");
spin_unlock_irq(&params->atqbal_wq.lock);
return err;
}
spin_unlock_irq(&params->atqbal_wq.lock);
return 0;
if (err)
ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY timer adjustment using low latency interface\n");
return err;
}
/**
@@ -4837,8 +4834,12 @@ static int ice_ptp_prep_phy_adj_e810(struct ice_hw *hw, s32 adj)
u8 tmr_idx;
int err;
if (hw->dev_caps.ts_dev_info.ll_phy_tmr_update)
return ice_ptp_prep_phy_adj_ll_e810(hw, adj);
if (hw->dev_caps.ts_dev_info.ll_phy_tmr_update) {
err = ice_ptp_prep_phy_adj_ll_e810(hw, adj);
if (err != -ETIMEDOUT)
return err;
ice_debug(hw, ICE_DBG_PTP, "LL adj timed out, falling back to SBQ\n");
}
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
@@ -4901,15 +4902,12 @@ static int ice_ptp_prep_phy_incval_ll_e810(struct ice_hw *hw, u64 incval)
!FIELD_GET(REG_LL_PROXY_H_EXEC, val),
10, REG_LL_PROXY_H_TIMEOUT_US, false, hw,
REG_LL_PROXY_H);
if (err) {
ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY timer increment using low latency interface\n");
spin_unlock_irq(&params->atqbal_wq.lock);
return err;
}
spin_unlock_irq(&params->atqbal_wq.lock);
return 0;
if (err)
ice_debug(hw, ICE_DBG_PTP, "Failed to prepare PHY timer increment using low latency interface\n");
return err;
}
/**
@@ -4927,8 +4925,12 @@ static int ice_ptp_prep_phy_incval_e810(struct ice_hw *hw, u64 incval)
u8 tmr_idx;
int err;
if (hw->dev_caps.ts_dev_info.ll_phy_tmr_update)
return ice_ptp_prep_phy_incval_ll_e810(hw, incval);
if (hw->dev_caps.ts_dev_info.ll_phy_tmr_update) {
err = ice_ptp_prep_phy_incval_ll_e810(hw, incval);
if (err != -ETIMEDOUT)
return err;
ice_debug(hw, ICE_DBG_PTP, "LL incval timed out, falling back to SBQ\n");
}
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
low = lower_32_bits(incval);

View File

@@ -2408,7 +2408,7 @@ void idpf_tx_splitq_build_flow_desc(union idpf_tx_flex_desc *desc,
struct idpf_tx_splitq_params *params,
u16 td_cmd, u16 size)
{
*(u32 *)&desc->flow.qw1.cmd_dtype = (u8)(params->dtype | td_cmd);
*(__le32 *)&desc->flow.qw1.cmd_dtype = cpu_to_le32((u8)(params->dtype | td_cmd));
desc->flow.qw1.rxr_bufsize = cpu_to_le16((u16)size);
desc->flow.qw1.compl_tag = cpu_to_le16(params->compl_tag);
}

View File

@@ -856,7 +856,7 @@ int rvu_mbox_handler_mcs_ctrl_pkt_rule_write(struct rvu *rvu,
static void rvu_mcs_set_lmac_bmap(struct rvu *rvu)
{
struct mcs *mcs = mcs_get_pdata(0);
unsigned long lmac_bmap;
unsigned long lmac_bmap = 0;
int cgx, lmac, port;
for (port = 0; port < mcs->hw->lmac_cnt; port++) {

View File

@@ -2257,6 +2257,11 @@ static void mlx5e_handle_rx_cqe_mpwrq_shampo(struct mlx5e_rq *rq, struct mlx5_cq
data_offset = wqe_offset & (page_size - 1);
page_idx = wqe_offset >> rq->mpwqe.page_shift;
if (unlikely(cqe_bcnt <= ETH_ZLEN + 2 * VLAN_HLEN)) {
match = false;
flush = true;
}
if (*skb &&
!(match && mlx5e_hw_gro_skb_has_enough_space(*skb, data_bcnt,
page_size))) {

View File

@@ -269,6 +269,8 @@ bool ionic_notifyq_service(struct ionic_cq *cq)
if ((s64)(eid - lif->last_eid) <= 0)
return false;
dma_rmb();
lif->last_eid = eid;
dev_dbg(lif->ionic->dev, "notifyq event:\n");
@@ -314,6 +316,8 @@ bool ionic_adminq_service(struct ionic_cq *cq)
if (!color_match(comp->color, cq->done_color))
return false;
dma_rmb();
/* check for empty queue */
if (q->tail_idx == q->head_idx)
return false;

View File

@@ -706,11 +706,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
__le64 *cq_desc_hwstamp;
u64 hwstamp;
cq_desc_hwstamp =
(void *)comp +
qcq->cq.desc_size -
sizeof(struct ionic_rxq_comp) -
IONIC_HWSTAMP_CQ_NEGOFFSET;
cq_desc_hwstamp = (void *)comp - IONIC_HWSTAMP_CQ_NEGOFFSET;
hwstamp = le64_to_cpu(*cq_desc_hwstamp);
@@ -734,11 +730,18 @@ static bool __ionic_rx_service(struct ionic_cq *cq, struct bpf_prog *xdp_prog)
struct ionic_queue *q = cq->bound_q;
struct ionic_rxq_comp *comp;
comp = &((struct ionic_rxq_comp *)cq->base)[cq->tail_idx];
if (likely(cq->desc_size == sizeof(*comp)))
comp = &((struct ionic_rxq_comp *)cq->base)[cq->tail_idx];
else
comp = cq->base +
cq->desc_size * cq->tail_idx +
cq->desc_size - sizeof(*comp);
if (!color_match(comp->pkt_type_color, cq->done_color))
return false;
dma_rmb();
/* check for empty queue */
if (q->tail_idx == q->head_idx)
return false;
@@ -1185,7 +1188,6 @@ static void ionic_tx_clean(struct ionic_queue *q,
bool in_napi)
{
struct ionic_tx_stats *stats = q_to_tx_stats(q);
struct ionic_qcq *qcq = q_to_qcq(q);
struct sk_buff *skb;
if (desc_info->xdpf) {
@@ -1210,11 +1212,7 @@ static void ionic_tx_clean(struct ionic_queue *q,
__le64 *cq_desc_hwstamp;
u64 hwstamp;
cq_desc_hwstamp =
(void *)comp +
qcq->cq.desc_size -
sizeof(struct ionic_txq_comp) -
IONIC_HWSTAMP_CQ_NEGOFFSET;
cq_desc_hwstamp = (void *)comp - IONIC_HWSTAMP_CQ_NEGOFFSET;
hwstamp = le64_to_cpu(*cq_desc_hwstamp);
@@ -1249,11 +1247,18 @@ static bool ionic_tx_service(struct ionic_cq *cq,
unsigned int pkts = 0;
u16 index;
comp = &((struct ionic_txq_comp *)cq->base)[cq->tail_idx];
if (likely(cq->desc_size == sizeof(*comp)))
comp = &((struct ionic_txq_comp *)cq->base)[cq->tail_idx];
else
comp = cq->base +
cq->desc_size * cq->tail_idx +
cq->desc_size - sizeof(*comp);
if (!color_match(comp->color, cq->done_color))
return false;
dma_rmb();
/* clean the related q entries, there could be
* several q entries completed for each cq completion
*/

View File

@@ -2066,7 +2066,7 @@ static int __maybe_unused cp_suspend(struct device *device)
/* Disable Rx and Tx */
cpw16 (IntrMask, 0);
cpw8 (Cmd, cpr8 (Cmd) & (~RxOn | ~TxOn));
cpw8 (Cmd, cpr8 (Cmd) & ~(RxOn | TxOn));
spin_unlock_irqrestore (&cp->lock, flags);

View File

@@ -1028,6 +1028,7 @@ struct ravb_ptp_perout {
struct ravb_ptp {
struct ptp_clock *clock;
struct ptp_clock_info info;
int phc_index;
u32 default_addend;
u32 current_addend;
int extts[N_EXT_TS];
@@ -1123,6 +1124,8 @@ struct ravb_private {
int msg_enable;
int speed;
int emac_irq;
int err_irq;
int mgmt_irq;
unsigned no_avb_link:1;
unsigned avb_link_active_low:1;

View File

@@ -1779,7 +1779,7 @@ static int ravb_get_ts_info(struct net_device *ndev,
(1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
(1 << HWTSTAMP_FILTER_ALL);
info->phc_index = ptp_clock_index(priv->ptp.clock);
info->phc_index = READ_ONCE(priv->ptp.phc_index);
}
return 0;
@@ -2885,11 +2885,13 @@ static int ravb_setup_irqs(struct ravb_private *priv)
return error;
if (info->err_mgmt_irqs) {
error = ravb_setup_irq(priv, "err_a", "err_a", NULL, ravb_multi_interrupt);
error = ravb_setup_irq(priv, "err_a", "err_a", &priv->err_irq,
ravb_multi_interrupt);
if (error)
return error;
error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", NULL, ravb_multi_interrupt);
error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", &priv->mgmt_irq,
ravb_multi_interrupt);
if (error)
return error;
}
@@ -2953,6 +2955,7 @@ static int ravb_probe(struct platform_device *pdev)
priv->rstc = rstc;
priv->ndev = ndev;
priv->pdev = pdev;
priv->ptp.phc_index = -1;
priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE;
if (info->nc_queues) {

View File

@@ -289,16 +289,17 @@ static const struct ptp_clock_info ravb_ptp_info = {
void ravb_ptp_interrupt(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
struct ptp_clock *clock = READ_ONCE(priv->ptp.clock);
u32 gis = ravb_read(ndev, GIS);
gis &= ravb_read(ndev, GIC);
if (gis & GIS_PTCF) {
if ((gis & GIS_PTCF) && clock) {
struct ptp_clock_event event;
event.type = PTP_CLOCK_EXTTS;
event.index = 0;
event.timestamp = ravb_read(ndev, GCPT);
ptp_clock_event(priv->ptp.clock, &event);
ptp_clock_event(clock, &event);
}
if (gis & GIS_PTMF) {
struct ravb_ptp_perout *perout = priv->ptp.perout;
@@ -315,6 +316,7 @@ void ravb_ptp_interrupt(struct net_device *ndev)
void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
{
struct ravb_private *priv = netdev_priv(ndev);
struct ptp_clock *clock;
unsigned long flags;
priv->ptp.info = ravb_ptp_info;
@@ -327,15 +329,45 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
ravb_modify(ndev, GCCR, GCCR_TCSS, GCCR_TCSS_ADJGPTP);
spin_unlock_irqrestore(&priv->lock, flags);
priv->ptp.clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
if (IS_ERR(clock)) {
netdev_err(ndev, "failed to register PTP clock: %pe\n", clock);
clock = NULL;
}
WRITE_ONCE(priv->ptp.clock, clock);
if (clock)
WRITE_ONCE(priv->ptp.phc_index, ptp_clock_index(clock));
}
static void ravb_ptp_disable(struct net_device *ndev)
{
ravb_write(ndev, 0, GIC);
ravb_write(ndev, 0, GIS);
}
static void ravb_ptp_sync_irqs(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
synchronize_irq(ndev->irq);
if (priv->info->err_mgmt_irqs) {
synchronize_irq(priv->err_irq);
synchronize_irq(priv->mgmt_irq);
}
}
void ravb_ptp_stop(struct net_device *ndev)
{
struct ravb_private *priv = netdev_priv(ndev);
struct ptp_clock *clock;
ravb_write(ndev, 0, GIC);
ravb_write(ndev, 0, GIS);
WRITE_ONCE(priv->ptp.phc_index, -1);
clock = xchg(&priv->ptp.clock, NULL);
ptp_clock_unregister(priv->ptp.clock);
ravb_ptp_disable(ndev);
ravb_ptp_sync_irqs(ndev);
if (clock)
ptp_clock_unregister(clock);
}

View File

@@ -74,7 +74,9 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
switch (cmd) {
case PPPIOCGCHAN: {
struct sk_buff *skb;
int index;
rc = -ENOTCONN;
if (!(sk->sk_state & PPPOX_CONNECTED))
break;
@@ -85,7 +87,22 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
rc = 0;
/* PPPIOCGCHAN historically marks the userspace handoff to
* generic PPP; pppd then attaches the returned channel to
* /dev/ppp.
*/
sk->sk_state |= PPPOX_BOUND;
/* Let lockless receive paths finish queueing against the old
* state.
*/
synchronize_net();
/* Drain packets queued before the handoff because a bound
* socket is no longer readable.
*/
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
skb_orphan(skb);
ppp_input(&po->chan, skb);
}
break;
}
default:

View File

@@ -626,6 +626,14 @@ static int tbnet_alloc_tx_buffers(struct tbnet *net)
return 0;
}
static void tbnet_connect_failed(struct tbnet *net)
{
/* Leave login_received set: only the peer can make it true again. */
mutex_lock(&net->connection_lock);
net->login_sent = false;
mutex_unlock(&net->connection_lock);
}
static void tbnet_connected_work(struct work_struct *work)
{
struct tbnet *net = container_of(work, typeof(*net), connected_work);
@@ -647,6 +655,9 @@ static void tbnet_connected_work(struct work_struct *work)
ret = tb_xdomain_alloc_in_hopid(net->xd, net->remote_transmit_path);
if (ret != net->remote_transmit_path) {
netdev_err(net->dev, "failed to allocate Rx HopID\n");
if (ret >= 0)
tb_xdomain_release_in_hopid(net->xd, ret);
tbnet_connect_failed(net);
return;
}
@@ -691,6 +702,7 @@ static void tbnet_connected_work(struct work_struct *work)
tb_ring_stop(net->rx_ring.ring);
tb_ring_stop(net->tx_ring.ring);
tb_xdomain_release_in_hopid(net->xd, net->remote_transmit_path);
tbnet_connect_failed(net);
}
static void tbnet_login_work(struct work_struct *work)

View File

@@ -1186,11 +1186,16 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
static void tun_set_headroom(struct net_device *dev, int new_hr)
{
struct tun_struct *tun = netdev_priv(dev);
size_t max_headroom;
if (new_hr < NET_SKB_PAD)
new_hr = NET_SKB_PAD;
max_headroom = min_t(size_t, SKB_MAX_HEAD(0), U16_MAX - 1);
tun->align = new_hr;
if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
max_headroom -= ETH_HLEN + NET_IP_ALIGN;
else
max_headroom -= 1;
tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
}
static void
@@ -1901,7 +1906,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
switch (tun->flags & TUN_TYPE_MASK) {
case IFF_TUN:
if (tun->flags & IFF_NO_PI) {
u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0;
u8 ip_version;
if (!pskb_may_pull(skb, 1)) {
err = -EINVAL;
goto drop;
}
ip_version = skb->data[0] >> 4;
switch (ip_version) {
case 4:
@@ -1921,7 +1932,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
skb->dev = tun->dev;
break;
case IFF_TAP:
if (frags && !pskb_may_pull(skb, ETH_HLEN)) {
if (!pskb_may_pull(skb, ETH_HLEN)) {
err = -ENOMEM;
drop_reason = SKB_DROP_REASON_HDR_TRUNC;
goto drop;

View File

@@ -3444,17 +3444,31 @@ static void virtnet_rx_resume_all(struct virtnet_info *vi)
static int virtnet_rx_resize(struct virtnet_info *vi,
struct receive_queue *rq, u32 ring_num)
{
unsigned int old_ring_num = virtqueue_get_vring_size(rq->vq);
struct xdp_buff **tmp_xsk_buffs = NULL;
int err, qindex;
qindex = rq - vi->rq;
if (rq->xsk_pool && ring_num > old_ring_num) {
tmp_xsk_buffs = kvzalloc_objs(*tmp_xsk_buffs, ring_num);
if (!tmp_xsk_buffs)
return -ENOMEM;
}
virtnet_rx_pause(vi, rq);
err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf, NULL);
/* virtqueue_resize may have changed the size even if err != 0 */
if (tmp_xsk_buffs && virtqueue_get_vring_size(rq->vq) > old_ring_num)
swap(rq->xsk_buffs, tmp_xsk_buffs);
if (err)
netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err);
virtnet_rx_resume(vi, rq, true);
kvfree(tmp_xsk_buffs);
return err;
}

View File

@@ -3058,18 +3058,19 @@ vxlan_fdb_flush_match_remotes(struct vxlan_fdb *f, struct vxlan_dev *vxlan,
const struct vxlan_fdb_flush_desc *desc,
bool *p_destroy_fdb)
{
bool remotes_flushed = false;
struct vxlan_rdst *rd, *tmp;
list_for_each_entry_safe(rd, tmp, &f->remotes, list) {
if (!vxlan_fdb_flush_remote_matches(desc, rd))
continue;
vxlan_fdb_dst_destroy(vxlan, f, rd, true);
remotes_flushed = true;
}
if (list_is_singular(&f->remotes)) {
*p_destroy_fdb = true;
return;
}
*p_destroy_fdb = remotes_flushed && list_empty(&f->remotes);
vxlan_fdb_dst_destroy(vxlan, f, rd, true);
}
}
/* Purge the forwarding table */

View File

@@ -1428,14 +1428,17 @@ static void vxlan_mdb_flush(struct vxlan_dev *vxlan,
struct vxlan_mdb_entry *mdb_entry;
struct hlist_node *tmp;
/* The removal of an entry cannot trigger the removal of another entry
* since entries are always added to the head of the list.
*/
hlist_for_each_entry_safe(mdb_entry, tmp, &vxlan->mdb_list, mdb_node) {
if (desc->src_vni && desc->src_vni != mdb_entry->key.vni)
continue;
vxlan_mdb_remotes_flush(vxlan, mdb_entry, desc);
/* The flush can remove the (S, G) entries created for the
* source list of this entry, including the one saved by
* hlist_for_each_entry_safe(), so re-read it while this entry
* is still linked.
*/
tmp = mdb_entry->mdb_node.next;
/* Entry will only be removed if its remotes list is empty. */
vxlan_mdb_entry_put(vxlan, mdb_entry);
}

View File

@@ -462,10 +462,8 @@ static int vxlan_vnifilter_dump(struct sk_buff *skb, struct netlink_callback *cb
static const struct nla_policy vni_filter_entry_policy[VXLAN_VNIFILTER_ENTRY_MAX + 1] = {
[VXLAN_VNIFILTER_ENTRY_START] = { .type = NLA_U32 },
[VXLAN_VNIFILTER_ENTRY_END] = { .type = NLA_U32 },
[VXLAN_VNIFILTER_ENTRY_GROUP] = { .type = NLA_BINARY,
.len = sizeof_field(struct iphdr, daddr) },
[VXLAN_VNIFILTER_ENTRY_GROUP6] = { .type = NLA_BINARY,
.len = sizeof(struct in6_addr) },
[VXLAN_VNIFILTER_ENTRY_GROUP] = NLA_POLICY_EXACT_LEN(sizeof_field(struct iphdr, daddr)),
[VXLAN_VNIFILTER_ENTRY_GROUP6] = NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
};
static const struct nla_policy vni_filter_policy[VXLAN_VNIFILTER_MAX + 1] = {

View File

@@ -166,9 +166,36 @@ static int fdp_nci_i2c_read(struct fdp_i2c_phy *phy, struct sk_buff **skb)
/* Packet that contains a length */
if (tmp[0] == 0 && tmp[1] == 0) {
phy->next_read_size = (tmp[2] << 8) + tmp[3] + 3;
/*
* next_read_size is taken from the device and is used
* as the i2c_master_recv() count for the next packet
* and as the data skb size. A value above the receive
* buffer overflows tmp[]; one below the minimum frame
* size runs the header/LRC strip and the length-field
* read past a short receive. Either way the packet is
* corrupt: drop it and force resynchronization.
*/
if (phy->next_read_size < FDP_NCI_I2C_MIN_PAYLOAD ||
phy->next_read_size > FDP_NCI_I2C_MAX_PAYLOAD) {
dev_dbg(&client->dev, "%s: corrupted packet\n",
__func__);
phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;
goto flush;
}
} else {
phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD;
/*
* Only one data packet is delivered per call; if the
* device sends another, do not overwrite and leak the
* skb allocated for the previous one.
*/
if (*skb) {
kfree_skb(*skb);
*skb = NULL;
}
*skb = alloc_skb(len, GFP_KERNEL);
if (*skb == NULL) {
r = -ENOMEM;

View File

@@ -483,13 +483,19 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
switch (gate) {
case MICROREAD_GATE_ID_MREAD_ISO_A:
if (skb->len <= MICROREAD_EMCF_A_LEN) {
r = -EINVAL;
goto exit_free;
}
targets->supported_protocols =
nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A_SAK]);
targets->sens_res =
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]);
targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK];
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN];
if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
if (targets->nfcid1_len > sizeof(targets->nfcid1) ||
targets->nfcid1_len > skb->len - MICROREAD_EMCF_A_UID) {
r = -EINVAL;
goto exit_free;
}
@@ -497,13 +503,19 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
targets->nfcid1_len);
break;
case MICROREAD_GATE_ID_MREAD_ISO_A_3:
if (skb->len <= MICROREAD_EMCF_A3_LEN) {
r = -EINVAL;
goto exit_free;
}
targets->supported_protocols =
nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A3_SAK]);
targets->sens_res =
be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]);
targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK];
targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN];
if (targets->nfcid1_len > sizeof(targets->nfcid1)) {
if (targets->nfcid1_len > sizeof(targets->nfcid1) ||
targets->nfcid1_len > skb->len - MICROREAD_EMCF_A3_UID) {
r = -EINVAL;
goto exit_free;
}
@@ -511,11 +523,21 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
targets->nfcid1_len);
break;
case MICROREAD_GATE_ID_MREAD_ISO_B:
if (skb->len < MICROREAD_EMCF_B_UID + 4) {
r = -EINVAL;
goto exit_free;
}
targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_B_UID], 4);
targets->nfcid1_len = 4;
break;
case MICROREAD_GATE_ID_MREAD_NFC_T1:
if (skb->len < MICROREAD_EMCF_T1_UID + 4) {
r = -EINVAL;
goto exit_free;
}
targets->supported_protocols = NFC_PROTO_JEWEL_MASK;
targets->sens_res =
le16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_T1_ATQA]);
@@ -523,6 +545,11 @@ static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate,
targets->nfcid1_len = 4;
break;
case MICROREAD_GATE_ID_MREAD_NFC_T3:
if (skb->len < MICROREAD_EMCF_T3_UID + 8) {
r = -EINVAL;
goto exit_free;
}
targets->supported_protocols = NFC_PROTO_FELICA_MASK;
memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T3_UID], 8);
targets->nfcid1_len = 8;

View File

@@ -434,6 +434,18 @@ static int pn533_send_async_complete(struct pn533 *dev)
return rc;
}
static int pn533_send_cmd_frame(struct pn533 *dev, struct pn533_cmd *cmd)
{
struct sk_buff *req = cmd->req;
int rc;
skb_get(req);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req);
dev_kfree_skb(req);
return rc;
}
static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
struct sk_buff *req,
pn533_send_async_complete_t complete_cb,
@@ -458,8 +470,7 @@ static int __pn533_send_async(struct pn533 *dev, u8 cmd_code,
mutex_lock(&dev->cmd_lock);
if (!dev->cmd_pending) {
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req);
rc = pn533_send_cmd_frame(dev, cmd);
if (rc) {
dev->cmd = NULL;
goto error;
@@ -529,8 +540,7 @@ static int pn533_send_cmd_direct_async(struct pn533 *dev, u8 cmd_code,
pn533_build_cmd_frame(dev, cmd_code, req);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, req);
rc = pn533_send_cmd_frame(dev, cmd);
if (rc < 0) {
dev->cmd = NULL;
kfree(cmd);
@@ -569,8 +579,7 @@ static void pn533_wq_cmd(struct work_struct *work)
mutex_unlock(&dev->cmd_lock);
dev->cmd = cmd;
rc = dev->phy_ops->send_frame(dev, cmd->req);
rc = pn533_send_cmd_frame(dev, cmd);
if (rc < 0) {
dev->cmd = NULL;
dev_kfree_skb(cmd->req);
@@ -2801,6 +2810,7 @@ void pn53x_common_clean(struct pn533 *priv)
destroy_workqueue(priv->wq);
skb_queue_purge(&priv->resp_q);
skb_queue_purge(&priv->fragment_skb);
list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) {
list_del(&cmd->queue);

View File

@@ -205,6 +205,9 @@ static int st21nfca_tm_recv_atr_req(struct nfc_hci_dev *hdev,
if (atr_req->length < sizeof(struct st21nfca_atr_req))
return -EPROTO;
if (atr_req->length > skb->len)
return -EPROTO;
r = st21nfca_tm_send_atr_res(hdev, atr_req);
if (r)
return r;

View File

@@ -482,6 +482,9 @@ static int net_timer_enable_perout(struct netc_timer *priv,
netc_timer_enable_periodic_pulse(priv, channel);
} else {
if (!pp->enabled)
goto unlock_spinlock;
netc_timer_disable_periodic_pulse(priv, channel);
priv->fs_alarm_bitmap &= ~BIT(pp->alarm_id);
memset(pp, 0, sizeof(*pp));

View File

@@ -372,6 +372,12 @@ static int vmclock_miscdev_mmap(struct file *fp, struct vm_area_struct *vma)
if ((vma->vm_flags & (VM_READ|VM_WRITE)) != VM_READ)
return -EROFS;
/*
* Restrict the read-only mapping so it cannot be upgraded to
* writable later with mprotect().
*/
vm_flags_clear(vma, VM_MAYWRITE);
if (vma->vm_end - vma->vm_start != PAGE_SIZE || vma->vm_pgoff)
return -EINVAL;

View File

@@ -52,13 +52,10 @@ struct vsock_sock {
* The listening socket is the head for both lists. Sockets created
* for connection requests are placed in the pending list until they
* are connected, at which point they are put in the accept queue list
* so they can be accepted in accept(). If accept() cannot accept the
* connection, it is marked as rejected so the cleanup function knows
* to clean up the socket.
* so they can be accepted in accept().
*/
struct list_head pending_links;
struct list_head accept_queue;
bool rejected;
struct delayed_work connect_work;
struct delayed_work pending_work;
struct delayed_work close_work;

View File

@@ -628,8 +628,7 @@ struct metadata_dst *iptunnel_metadata_reply(struct metadata_dst *md,
int skb_tunnel_check_pmtu(struct sk_buff *skb, struct dst_entry *encap_dst,
int headroom, bool reply);
static inline void ip_tunnel_adj_headroom(struct net_device *dev,
unsigned int headroom)
static inline unsigned int ip_tunnel_limit_headroom(unsigned int headroom)
{
/* we must cap headroom to some upperlimit, else pskb_expand_head
* will overflow header offsets in skb_headers_offset_update().
@@ -639,6 +638,14 @@ static inline void ip_tunnel_adj_headroom(struct net_device *dev,
if (headroom > max_allowed)
headroom = max_allowed;
return headroom;
}
static inline void ip_tunnel_adj_headroom(struct net_device *dev,
unsigned int headroom)
{
headroom = ip_tunnel_limit_headroom(headroom);
if (headroom > READ_ONCE(dev->needed_headroom))
WRITE_ONCE(dev->needed_headroom, headroom);
}

View File

@@ -1136,7 +1136,7 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,
if (err)
goto out;
if (br_vlan_delete(br, old_pvid))
if (!br_vlan_delete(br, old_pvid))
br_vlan_notify(br, NULL, old_pvid, 0, RTM_DELVLAN);
br_vlan_notify(br, NULL, pvid, 0, RTM_NEWVLAN);
__set_bit(0, changed);
@@ -1158,7 +1158,7 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,
&vlchange, extack);
if (err)
goto err_port;
if (nbp_vlan_delete(p, old_pvid))
if (!nbp_vlan_delete(p, old_pvid))
br_vlan_notify(br, p, old_pvid, 0, RTM_DELVLAN);
br_vlan_notify(p->br, p, pvid, 0, RTM_NEWVLAN);
__set_bit(p->port_no, changed);

View File

@@ -10383,6 +10383,37 @@ static int dev_xdp_install(struct net_device *dev, enum bpf_xdp_mode mode,
netdev_assert_locked_ops_compat(dev);
if (prog) {
enum bpf_xdp_mode other_mode = mode == XDP_MODE_SKB
? XDP_MODE_DRV : XDP_MODE_SKB;
bool offload = mode == XDP_MODE_HW;
if (!offload && dev_xdp_prog(dev, other_mode)) {
NL_SET_ERR_MSG(extack, "Native and generic XDP can't be active at the same time");
return -EEXIST;
}
if (!offload && bpf_prog_is_offloaded(prog->aux)) {
NL_SET_ERR_MSG(extack, "Using offloaded program without HW_MODE flag is not supported");
return -EINVAL;
}
if (bpf_prog_is_dev_bound(prog->aux) && !bpf_offload_dev_match(prog, dev)) {
NL_SET_ERR_MSG(extack, "Program bound to different device");
return -EINVAL;
}
if (bpf_prog_is_dev_bound(prog->aux) && mode == XDP_MODE_SKB) {
NL_SET_ERR_MSG(extack, "Can't attach device-bound programs in generic mode");
return -EINVAL;
}
if (prog->expected_attach_type == BPF_XDP_DEVMAP) {
NL_SET_ERR_MSG(extack, "BPF_XDP_DEVMAP programs can not be attached to a device");
return -EINVAL;
}
if (prog->expected_attach_type == BPF_XDP_CPUMAP) {
NL_SET_ERR_MSG(extack, "BPF_XDP_CPUMAP programs can not be attached to a device");
return -EINVAL;
}
}
if (dev->cfg->hds_config == ETHTOOL_TCP_DATA_SPLIT_ENABLED &&
prog && !prog->aux->xdp_has_frags) {
NL_SET_ERR_MSG(extack, "unable to install XDP to device using tcp-data-split");
@@ -10522,38 +10553,10 @@ static int dev_xdp_attach(struct net_device *dev, struct netlink_ext_ack *extack
new_prog = link->link.prog;
if (new_prog) {
bool offload = mode == XDP_MODE_HW;
enum bpf_xdp_mode other_mode = mode == XDP_MODE_SKB
? XDP_MODE_DRV : XDP_MODE_SKB;
if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) && cur_prog) {
NL_SET_ERR_MSG(extack, "XDP program already attached");
return -EBUSY;
}
if (!offload && dev_xdp_prog(dev, other_mode)) {
NL_SET_ERR_MSG(extack, "Native and generic XDP can't be active at the same time");
return -EEXIST;
}
if (!offload && bpf_prog_is_offloaded(new_prog->aux)) {
NL_SET_ERR_MSG(extack, "Using offloaded program without HW_MODE flag is not supported");
return -EINVAL;
}
if (bpf_prog_is_dev_bound(new_prog->aux) && !bpf_offload_dev_match(new_prog, dev)) {
NL_SET_ERR_MSG(extack, "Program bound to different device");
return -EINVAL;
}
if (bpf_prog_is_dev_bound(new_prog->aux) && mode == XDP_MODE_SKB) {
NL_SET_ERR_MSG(extack, "Can't attach device-bound programs in generic mode");
return -EINVAL;
}
if (new_prog->expected_attach_type == BPF_XDP_DEVMAP) {
NL_SET_ERR_MSG(extack, "BPF_XDP_DEVMAP programs can not be attached to a device");
return -EINVAL;
}
if (new_prog->expected_attach_type == BPF_XDP_CPUMAP) {
NL_SET_ERR_MSG(extack, "BPF_XDP_CPUMAP programs can not be attached to a device");
return -EINVAL;
}
}
/* don't call drivers if the effective program didn't change */
@@ -12222,6 +12225,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
free_percpu(dev->pcpu_refcnt);
free_dev:
#endif
ref_tracker_dir_exit(&dev->refcnt_tracker);
kvfree(dev);
return NULL;
}

View File

@@ -500,29 +500,40 @@ static int page_pool_register_dma_index(struct page_pool *pool,
return err;
}
static int page_pool_release_dma_index(struct page_pool *pool,
netmem_ref netmem)
static void __page_pool_unmap_netmem_dma(struct page_pool *pool,
netmem_ref netmem)
{
struct page *old, *page = netmem_to_page(netmem);
unsigned long id;
dma_addr_t dma;
if (unlikely(!PP_DMA_INDEX_BITS))
return 0;
if (!pool->dma_map)
return;
id = netmem_get_dma_index(netmem);
if (!id)
return -1;
/* Cache dma_addr before xa_cmpxchg. The scrub path holds no page ref;
* the unref path calls put_page() regardless of cmpxchg outcome, so
* after the cmpxchg we cannot safely touch netmem fields.
*/
dma = page_pool_get_dma_addr_netmem(netmem);
if (in_softirq())
old = xa_cmpxchg(&pool->dma_mapped, id, page, NULL, 0);
else
old = xa_cmpxchg_bh(&pool->dma_mapped, id, page, NULL, 0);
if (old != page)
return -1;
if (likely(PP_DMA_INDEX_BITS)) {
id = netmem_get_dma_index(netmem);
if (!id)
return;
netmem_set_dma_index(netmem, 0);
if (in_softirq())
old = xa_cmpxchg(&pool->dma_mapped,
id, page, NULL, 0);
else
old = xa_cmpxchg_bh(&pool->dma_mapped,
id, page, NULL, 0);
if (old != page)
return;
}
return 0;
dma_unmap_page_attrs(pool->p.dev, dma,
PAGE_SIZE << pool->p.order, pool->p.dma_dir,
DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING);
}
static bool page_pool_dma_map(struct page_pool *pool, netmem_ref netmem, gfp_t gfp)
@@ -728,24 +739,16 @@ void page_pool_clear_pp_info(netmem_ref netmem)
static __always_inline void __page_pool_release_netmem_dma(struct page_pool *pool,
netmem_ref netmem)
{
dma_addr_t dma;
/* Caller must hold a page ref: __page_pool_unmap_netmem_dma() is
* safe without a ref, but the field clears below require it.
*/
if (!pool->dma_map)
/* Always account for inflight pages, even if we didn't
* map them
*/
return;
if (page_pool_release_dma_index(pool, netmem))
return;
dma = page_pool_get_dma_addr_netmem(netmem);
/* When page is unmapped, it cannot be returned to our pool */
dma_unmap_page_attrs(pool->p.dev, dma,
PAGE_SIZE << pool->p.order, pool->p.dma_dir,
DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING);
__page_pool_unmap_netmem_dma(pool, netmem);
page_pool_set_dma_addr_netmem(netmem, 0);
if (likely(PP_DMA_INDEX_BITS))
netmem_set_dma_index(netmem, 0);
}
/* Disconnects a page (from a page_pool). API users can have a need
@@ -1171,8 +1174,9 @@ static void page_pool_scrub(struct page_pool *pool)
synchronize_net();
}
/* No page ref, dma-unmap only. */
xa_for_each(&pool->dma_mapped, id, ptr)
__page_pool_release_netmem_dma(pool, page_to_netmem((struct page *)ptr));
__page_pool_unmap_netmem_dma(pool, page_to_netmem((struct page *)ptr));
}
/* No more consumers should exist, but producers could still

View File

@@ -854,6 +854,8 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
hsr_del_ports(hsr);
err_add_master:
hsr_del_self_node(hsr);
hsr_del_nodes(&hsr->node_db);
hsr_del_nodes(&hsr->proxy_node_db);
if (unregister)
unregister_netdevice(hsr_dev);

View File

@@ -790,6 +790,10 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
*/
hlen = iph->ihl * 4;
if (mtu < hlen + 8) {
err = -EMSGSIZE;
goto fail;
}
mtu = mtu - hlen; /* Size of data space */
IPCB(skb)->flags |= IPSKB_FRAG_COMPLETE;
ll_rs = LL_RESERVED_SPACE(rt->dst.dev);

View File

@@ -317,7 +317,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
mtu = min(tdev->mtu, IP_MAX_MTU);
}
dev->needed_headroom = t_hlen + hlen;
dev->needed_headroom = ip_tunnel_limit_headroom(t_hlen + hlen);
mtu -= t_hlen + (dev->type == ARPHRD_ETHER ? dev->hard_header_len : 0);
if (mtu < IPV4_MIN_MTU)

View File

@@ -2213,6 +2213,9 @@ int ip_mr_input(struct sk_buff *skb)
if (IPCB(skb)->flags & IPSKB_FORWARDED)
goto dont_forward;
if (!local)
skb_orphan(skb);
mrt = ipmr_rt_fib_lookup(net, skb);
if (IS_ERR(mrt)) {
kfree_skb(skb);

View File

@@ -1136,13 +1136,11 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
return;
if (rt->dst.dev) {
unsigned short dst_len = rt->dst.dev->hard_header_len +
t_hlen;
unsigned int headroom;
if (t->dev->header_ops)
dev->hard_header_len = dst_len;
else
dev->needed_headroom = dst_len;
headroom = rt->dst.dev->hard_header_len + t_hlen;
headroom = ip_tunnel_limit_headroom(headroom);
dev->needed_headroom = headroom;
if (set_mtu) {
int mtu = rt->dst.dev->mtu - t_hlen;
@@ -1170,8 +1168,8 @@ static int ip6gre_calc_hlen(struct ip6_tnl *tunnel)
t_hlen = tunnel->hlen + sizeof(struct ipv6hdr);
if (tunnel->dev->header_ops)
tunnel->dev->hard_header_len = LL_MAX_HEADER + t_hlen;
if (tunnel->dev->header_ops && tunnel->dev->type == ARPHRD_IP6GRE)
tunnel->dev->hard_header_len = t_hlen;
else
tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen;

View File

@@ -622,6 +622,7 @@ int ip6_mc_input(struct sk_buff *skb)
if (deliver) {
skb2 = skb_clone(skb, GFP_ATOMIC);
} else {
skb_orphan(skb);
skb2 = skb;
skb = NULL;
}

View File

@@ -116,6 +116,8 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
if (res != LWTUNNEL_XMIT_CONTINUE)
return res;
hdr = ipv6_hdr(skb);
daddr = &hdr->daddr;
}
IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);

View File

@@ -1236,19 +1236,8 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
*/
max_headroom += LL_RESERVED_SPACE(tdev);
if (skb_headroom(skb) < max_headroom || skb_shared(skb) ||
(skb_cloned(skb) && !skb_clone_writable(skb, 0))) {
struct sk_buff *new_skb;
new_skb = skb_realloc_headroom(skb, max_headroom);
if (!new_skb)
goto tx_err_dst_release;
if (skb->sk)
skb_set_owner_w(new_skb, skb->sk);
consume_skb(skb);
skb = new_skb;
}
if (skb_cow_head(skb, max_headroom))
goto tx_err_dst_release;
if (t->parms.collect_md) {
if (t->encap.type != TUNNEL_ENCAP_NONE)
@@ -1525,8 +1514,11 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
tdev = __dev_get_by_index(t->net, p->link);
if (tdev) {
dev->needed_headroom = tdev->hard_header_len +
tdev->needed_headroom + t_hlen;
unsigned int headroom;
headroom = tdev->hard_header_len + tdev->needed_headroom;
headroom += t_hlen;
dev->needed_headroom = ip_tunnel_limit_headroom(headroom);
mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU);
mtu = mtu - t_hlen;

View File

@@ -1131,7 +1131,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
WRITE_ONCE(dev->mtu, mtu);
hlen = tdev->hard_header_len + tdev->needed_headroom;
}
dev->needed_headroom = t_hlen + hlen;
dev->needed_headroom = ip_tunnel_limit_headroom(t_hlen + hlen);
}
static void ipip6_tunnel_update(struct ip_tunnel *t,

View File

@@ -5,6 +5,7 @@
* Copyright (c) 2016 Tom Herbert <tom@herbertland.com>
*/
#include <linux/rcupdate.h>
#include <linux/bpf.h>
#include <linux/errno.h>
#include <linux/errqueue.h>
@@ -391,7 +392,9 @@ static int kcm_parse_func_strparser(struct strparser *strp, struct sk_buff *skb)
struct bpf_prog *prog = psock->bpf_prog;
int res;
rcu_read_lock();
res = bpf_prog_run_pin_on_cpu(prog, skb);
rcu_read_unlock();
return res;
}

View File

@@ -221,6 +221,7 @@ static u32 mpls_multipath_hash(struct mpls_route *rt, struct sk_buff *skb)
if (pskb_may_pull(skb, mpls_hdr_len + sizeof(struct iphdr))) {
const struct iphdr *v4hdr;
hdr = mpls_hdr(skb) + label_index;
v4hdr = (const struct iphdr *)(hdr + 1);
if (v4hdr->version == 4) {
hash = jhash_3words(ntohl(v4hdr->saddr),
@@ -231,6 +232,7 @@ static u32 mpls_multipath_hash(struct mpls_route *rt, struct sk_buff *skb)
sizeof(struct ipv6hdr))) {
const struct ipv6hdr *v6hdr;
hdr = mpls_hdr(skb) + label_index;
v6hdr = (const struct ipv6hdr *)(hdr + 1);
hash = __ipv6_addr_jhash(&v6hdr->saddr, hash);
hash = __ipv6_addr_jhash(&v6hdr->daddr, hash);

View File

@@ -127,7 +127,7 @@ static void digital_wq_cmd_complete(struct work_struct *work)
mutex_unlock(&ddev->cmd_lock);
if (!IS_ERR(cmd->resp))
if (!IS_ERR_OR_NULL(cmd->resp))
print_hex_dump_debug("DIGITAL RX: ", DUMP_PREFIX_NONE, 16, 1,
cmd->resp->data, cmd->resp->len, false);

View File

@@ -778,6 +778,8 @@ static void digital_in_recv_sensf_res(struct nfc_digital_dev *ddev, void *arg,
sensf_res = (struct digital_sensf_res *)resp->data;
resp->len = min_t(unsigned int, resp->len, NFC_SENSF_RES_MAXSIZE);
memcpy(target.sensf_res, sensf_res, resp->len);
target.sensf_res_len = resp->len;

View File

@@ -193,7 +193,8 @@ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
const u8 *tlv_array, u16 tlv_array_len)
{
const u8 *tlv = tlv_array;
u8 type, length, offset = 0;
u8 type, length;
u16 offset = 0;
pr_debug("TLV array length %d\n", tlv_array_len);
@@ -201,9 +202,15 @@ int nfc_llcp_parse_gb_tlv(struct nfc_llcp_local *local,
return -ENODEV;
while (offset < tlv_array_len) {
if (offset + 2 > tlv_array_len)
return -EINVAL;
type = tlv[0];
length = tlv[1];
if (offset + 2 + length > tlv_array_len)
return -EINVAL;
pr_debug("type 0x%x length %d\n", type, length);
switch (type) {
@@ -243,7 +250,8 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
const u8 *tlv_array, u16 tlv_array_len)
{
const u8 *tlv = tlv_array;
u8 type, length, offset = 0;
u8 type, length;
u16 offset = 0;
pr_debug("TLV array length %d\n", tlv_array_len);
@@ -251,9 +259,15 @@ int nfc_llcp_parse_connection_tlv(struct nfc_llcp_sock *sock,
return -ENOTCONN;
while (offset < tlv_array_len) {
if (offset + 2 > tlv_array_len)
return -EINVAL;
type = tlv[0];
length = tlv[1];
if (offset + 2 + length > tlv_array_len)
return -EINVAL;
pr_debug("type 0x%x length %d\n", type, length);
switch (type) {

View File

@@ -849,13 +849,16 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len)
{
u8 type, length;
const u8 *tlv = &skb->data[2];
size_t tlv_array_len = skb->len - LLCP_HEADER_SIZE, offset = 0;
const u8 *tlv = &skb->data[LLCP_HEADER_SIZE];
const u8 *tlv_end = skb_tail_pointer(skb);
while (offset < tlv_array_len) {
while (tlv + 2 < tlv_end) {
type = tlv[0];
length = tlv[1];
if (tlv + 2 + length > tlv_end)
break;
pr_debug("type 0x%x length %d\n", type, length);
if (type == LLCP_TLV_SN) {
@@ -863,7 +866,6 @@ static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len)
return &tlv[2];
}
offset += length + 2;
tlv += length + 2;
}
@@ -1286,10 +1288,9 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
{
struct nfc_llcp_sock *llcp_sock;
u8 dsap, ssap, type, length, tid, sap;
const u8 *tlv;
u16 tlv_len, offset;
const u8 *tlv, *tlv_end;
const char *service_name;
size_t service_name_len;
int service_name_len;
struct nfc_llcp_sdp_tlv *sdp;
HLIST_HEAD(llc_sdres_list);
size_t sdres_tlvs_len;
@@ -1305,22 +1306,34 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
return;
}
/*
* Walk the SNL TLV list in the linear part of the skb only,
* bounded by skb_tail_pointer(). Each TLV needs a two-byte
* header (type, length) and its declared length must fit before
* the end; this also keeps the walk safe for very short frames.
*/
tlv = &skb->data[LLCP_HEADER_SIZE];
tlv_len = skb->len - LLCP_HEADER_SIZE;
offset = 0;
tlv_end = skb_tail_pointer(skb);
sdres_tlvs_len = 0;
while (offset < tlv_len) {
while (tlv + 2 < tlv_end) {
type = tlv[0];
length = tlv[1];
if (tlv + 2 + length > tlv_end)
break;
switch (type) {
case LLCP_TLV_SDREQ:
if (length < 1)
break;
tid = tlv[2];
service_name = (char *) &tlv[3];
service_name_len = length - 1;
pr_debug("Looking for %.16s\n", service_name);
pr_debug("Looking for %.*s\n", service_name_len,
service_name);
if (service_name_len == strlen("urn:nfc:sn:sdp") &&
!strncmp(service_name, "urn:nfc:sn:sdp",
@@ -1380,6 +1393,9 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
break;
case LLCP_TLV_SDRES:
if (length != 2)
break;
mutex_lock(&local->sdreq_lock);
pr_debug("LLCP_TLV_SDRES: searching tid %d\n", tlv[2]);
@@ -1408,7 +1424,6 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
break;
}
offset += length + 2;
tlv += length + 2;
}
@@ -1552,6 +1567,11 @@ static void nfc_llcp_rx_work(struct work_struct *work)
static void __nfc_llcp_recv(struct nfc_llcp_local *local, struct sk_buff *skb)
{
if (!pskb_may_pull(skb, LLCP_HEADER_SIZE)) {
kfree_skb(skb);
return;
}
local->rx_pending = skb;
timer_delete(&local->link_timer);
schedule_work(&local->rx_work);

View File

@@ -319,14 +319,22 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
if (get_user(len, optlen))
return -EFAULT;
local = llcp_sock->local;
if (!local)
return -ENODEV;
if (len < 0)
return -EINVAL;
if (len < sizeof(u32))
return -EINVAL;
len = min_t(u32, len, sizeof(u32));
lock_sock(sk);
local = llcp_sock->local;
if (!local) {
release_sock(sk);
return -ENODEV;
}
switch (optname) {
case NFC_LLCP_RW:
rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw;

View File

@@ -46,11 +46,11 @@ void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
timer_delete_sync(&ndev->data_timer);
clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
/* Mark the exchange as done before calling the callback.
* The callback (e.g. rawsock_data_exchange_complete) may
* want to immediately queue another data exchange.
*/
clear_bit(NCI_DATA_EXCHANGE, &ndev->flags);
/* Claim completion atomically -- both close and rx_work may race here */
if (!test_and_clear_bit(NCI_DATA_EXCHANGE, &ndev->flags)) {
kfree_skb(skb);
return;
}
if (cb) {
/* forward skb to nfc core */

View File

@@ -440,7 +440,7 @@ void nci_clear_target_list(struct nci_dev *ndev)
static int nci_rf_discover_ntf_packet(struct nci_dev *ndev,
const struct sk_buff *skb)
{
struct nci_rf_discover_ntf ntf;
struct nci_rf_discover_ntf ntf = {};
const __u8 *data;
bool add_target = true;
@@ -525,15 +525,19 @@ static int nci_rf_discover_ntf_packet(struct nci_dev *ndev,
static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
struct nci_rf_intf_activated_ntf *ntf,
const __u8 *data)
const __u8 *data, __u8 data_len)
{
struct activation_params_nfca_poll_iso_dep *nfca_poll;
struct activation_params_nfcb_poll_iso_dep *nfcb_poll;
switch (ntf->activation_rf_tech_and_mode) {
case NCI_NFC_A_PASSIVE_POLL_MODE:
if (data_len < 1)
return NCI_STATUS_RF_PROTOCOL_ERROR;
nfca_poll = &ntf->activation_params.nfca_poll_iso_dep;
nfca_poll->rats_res_len = min_t(__u8, *data++, NFC_ATS_MAXSIZE);
data_len--;
nfca_poll->rats_res_len = min_t(__u8, nfca_poll->rats_res_len, data_len);
pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len);
if (nfca_poll->rats_res_len > 0) {
memcpy(nfca_poll->rats_res,
@@ -542,8 +546,12 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
break;
case NCI_NFC_B_PASSIVE_POLL_MODE:
if (data_len < 1)
return NCI_STATUS_RF_PROTOCOL_ERROR;
nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep;
nfcb_poll->attrib_res_len = min_t(__u8, *data++, 50);
data_len--;
nfcb_poll->attrib_res_len = min_t(__u8, nfcb_poll->attrib_res_len, data_len);
pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len);
if (nfcb_poll->attrib_res_len > 0) {
memcpy(nfcb_poll->attrib_res,
@@ -562,7 +570,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev,
static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev,
struct nci_rf_intf_activated_ntf *ntf,
const __u8 *data)
const __u8 *data, __u8 data_len)
{
struct activation_params_poll_nfc_dep *poll;
struct activation_params_listen_nfc_dep *listen;
@@ -570,9 +578,13 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev,
switch (ntf->activation_rf_tech_and_mode) {
case NCI_NFC_A_PASSIVE_POLL_MODE:
case NCI_NFC_F_PASSIVE_POLL_MODE:
if (data_len < 1)
return NCI_STATUS_RF_PROTOCOL_ERROR;
poll = &ntf->activation_params.poll_nfc_dep;
poll->atr_res_len = min_t(__u8, *data++,
NFC_ATR_RES_MAXSIZE - 2);
data_len--;
poll->atr_res_len = min_t(__u8, poll->atr_res_len, data_len);
pr_debug("atr_res_len %d\n", poll->atr_res_len);
if (poll->atr_res_len > 0)
memcpy(poll->atr_res, data, poll->atr_res_len);
@@ -580,9 +592,13 @@ static int nci_extract_activation_params_nfc_dep(struct nci_dev *ndev,
case NCI_NFC_A_PASSIVE_LISTEN_MODE:
case NCI_NFC_F_PASSIVE_LISTEN_MODE:
if (data_len < 1)
return NCI_STATUS_RF_PROTOCOL_ERROR;
listen = &ntf->activation_params.listen_nfc_dep;
listen->atr_req_len = min_t(__u8, *data++,
NFC_ATR_REQ_MAXSIZE - 2);
data_len--;
listen->atr_req_len = min_t(__u8, listen->atr_req_len, data_len);
pr_debug("atr_req_len %d\n", listen->atr_req_len);
if (listen->atr_req_len > 0)
memcpy(listen->atr_req, data, listen->atr_req_len);
@@ -603,6 +619,12 @@ static void nci_target_auto_activated(struct nci_dev *ndev,
struct nfc_target *target;
int rc;
/* This is a new target, check if we've enough room */
if (ndev->n_targets == NCI_MAX_DISCOVERED_TARGETS) {
pr_debug("not enough room, ignoring new target...\n");
return;
}
target = &ndev->targets[ndev->n_targets];
rc = nci_add_new_protocol(ndev, target, ntf->rf_protocol,
@@ -688,7 +710,7 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
const struct sk_buff *skb)
{
struct nci_conn_info *conn_info;
struct nci_rf_intf_activated_ntf ntf;
struct nci_rf_intf_activated_ntf ntf = {};
const __u8 *data;
int err = NCI_STATUS_OK;
@@ -806,12 +828,14 @@ static int nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
switch (ntf.rf_interface) {
case NCI_RF_INTERFACE_ISO_DEP:
err = nci_extract_activation_params_iso_dep(ndev,
&ntf, data);
&ntf, data,
ntf.activation_params_len);
break;
case NCI_RF_INTERFACE_NFC_DEP:
err = nci_extract_activation_params_nfc_dep(ndev,
&ntf, data);
&ntf, data,
ntf.activation_params_len);
break;
case NCI_RF_INTERFACE_FRAME:

View File

@@ -50,11 +50,27 @@ static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev,
const struct nci_core_init_rsp_1 *rsp_1 = (void *)skb->data;
const struct nci_core_init_rsp_2 *rsp_2;
/* Ensure that the status field can be accessed. */
if (skb_headlen(skb) < 1)
return NCI_STATUS_SYNTAX_ERROR;
pr_debug("status 0x%x\n", rsp_1->status);
if (rsp_1->status != NCI_STATUS_OK)
return rsp_1->status;
/* Success response must contain the full fixed-size header */
if (skb_headlen(skb) < sizeof(*rsp_1))
return NCI_STATUS_SYNTAX_ERROR;
/* Ensure the variable-length rf_interfaces array and trailing
* rsp_2 structure are fully contained within the skb.
*/
if (skb_headlen(skb) < sizeof(*rsp_1) +
rsp_1->num_supported_rf_interfaces +
sizeof(*rsp_2))
return NCI_STATUS_SYNTAX_ERROR;
ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
@@ -87,15 +103,25 @@ static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
const struct sk_buff *skb)
{
const struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
const u8 *supported_rf_interface = rsp->supported_rf_interfaces;
const u8 *supported_rf_interface;
u8 rf_interface_idx = 0;
u8 rf_extension_cnt = 0;
/* Ensure that the status field can be accessed. */
if (skb_headlen(skb) < 1)
return NCI_STATUS_SYNTAX_ERROR;
pr_debug("status %x\n", rsp->status);
if (rsp->status != NCI_STATUS_OK)
return rsp->status;
/* Success response must contain the full fixed-size header */
if (skb_headlen(skb) < sizeof(*rsp))
return NCI_STATUS_SYNTAX_ERROR;
supported_rf_interface = rsp->supported_rf_interfaces;
ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
@@ -104,13 +130,22 @@ static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev,
NCI_MAX_SUPPORTED_RF_INTERFACES);
while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
/* Each entry: [rf_interface_type (1B)] [ext_count (1B)] [ext...] */
if (supported_rf_interface + 2 > skb_tail_pointer(skb))
break;
ndev->supported_rf_interfaces[rf_interface_idx] = *supported_rf_interface++;
/* skip rf extension parameters */
rf_extension_cnt = *supported_rf_interface++;
if (supported_rf_interface + rf_extension_cnt > skb_tail_pointer(skb))
break;
/* Only count the entry after full validation */
rf_interface_idx++;
supported_rf_interface += rf_extension_cnt;
}
ndev->num_supported_rf_interfaces = rf_interface_idx;
ndev->max_logical_connections = rsp->max_logical_connections;
ndev->max_routing_table_size =
__le16_to_cpu(rsp->max_routing_table_size);
@@ -336,6 +371,7 @@ static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev,
list_del(&conn_info->list);
if (conn_info == ndev->rf_conn_info)
ndev->rf_conn_info = NULL;
devm_kfree(&ndev->nfc_dev->dev, conn_info->dest_params);
devm_kfree(&ndev->nfc_dev->dev, conn_info);
}
}

View File

@@ -1995,6 +1995,7 @@ int ovs_ct_init(struct net *net)
{
unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
int err = 0;
if (nf_connlabels_get(net, n_bits - 1)) {
ovs_net->xt_label = false;
@@ -2004,10 +2005,11 @@ int ovs_ct_init(struct net *net)
}
#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
return ovs_ct_limit_init(net, ovs_net);
#else
return 0;
err = ovs_ct_limit_init(net, ovs_net);
if (err && ovs_net->xt_label)
nf_connlabels_put(net);
#endif
return err;
}
void ovs_ct_exit(struct net *net)

View File

@@ -1473,33 +1473,34 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
goto unlock;
}
reply = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts),
&flow->id, info, false, ufid_flags);
if (IS_ERR(reply)) {
netlink_set_err(sock_net(skb->sk)->genl_sock, 0, 0,
PTR_ERR(reply));
reply = NULL;
}
if (likely(reply)) {
err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
OVS_FLOW_CMD_DEL, ufid_flags);
if (WARN_ON_ONCE(err < 0)) {
kfree_skb(reply);
reply = NULL;
}
}
/* Removal has to happen after ovs_flow_cmd_fill_info(), as it uses
* the flow->mask that can be scheduled to be freed by the
* ovs_flow_tbl_remove() and we're not holding the RCU read lock.
*/
ovs_flow_tbl_remove(&dp->table, flow);
ovs_unlock();
reply = ovs_flow_cmd_alloc_info((const struct sw_flow_actions __force *) flow->sf_acts,
&flow->id, info, false, ufid_flags);
if (likely(reply)) {
if (!IS_ERR(reply)) {
rcu_read_lock(); /*To keep RCU checker happy. */
err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
OVS_FLOW_CMD_DEL,
ufid_flags);
rcu_read_unlock();
if (WARN_ON_ONCE(err < 0)) {
kfree_skb(reply);
goto out_free;
}
if (likely(reply))
ovs_notify(&dp_flow_genl_family, reply, info);
ovs_notify(&dp_flow_genl_family, reply, info);
} else {
netlink_set_err(sock_net(skb->sk)->genl_sock, 0, 0,
PTR_ERR(reply));
}
}
out_free:
ovs_flow_free(flow, true);
return 0;
unlock:

View File

@@ -1332,6 +1332,10 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
sctp_outq_uncork(&asoc->outqueue, gfp);
local_cork = 0;
}
/* No chunk left in this packet may use this asoc. */
if (event_type == SCTP_EVENT_T_CHUNK &&
chunk->asoc == asoc)
chunk->pdiscard = 1;
/* Delete the current association. */
sctp_cmd_delete_tcb(commands, asoc);
asoc = NULL;

View File

@@ -409,13 +409,13 @@ void smc_sk_init(struct net *net, struct sock *sk, int protocol)
"sk_lock-AF_SMC", &smc_key);
spin_lock_init(&smc->accept_q_lock);
spin_lock_init(&smc->conn.send_lock);
sk->sk_prot->hash(sk);
mutex_init(&smc->clcsock_release_lock);
smc_init_saved_callbacks(smc);
smc->limit_smc_hs = net->smc.limit_smc_hs;
smc->use_fallback = false; /* assume rdma capability first */
smc->fallback_rsn = 0;
smc_close_init(smc);
sk->sk_prot->hash(sk);
}
static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
@@ -3233,7 +3233,8 @@ int smc_ioctl(struct socket *sock, unsigned int cmd,
return -EINVAL;
}
if (smc->sk.sk_state == SMC_INIT ||
smc->sk.sk_state == SMC_CLOSED)
smc->sk.sk_state == SMC_CLOSED ||
!READ_ONCE(smc->conn.sndbuf_desc))
answ = 0;
else
answ = smc->conn.sndbuf_desc->len -

View File

@@ -1209,14 +1209,16 @@ static void smcd_buf_detach(struct smc_connection *conn)
{
struct smcd_dev *smcd = conn->lgr->smcd;
u64 peer_token = conn->peer_token;
struct smc_buf_desc *buf_desc;
if (!conn->sndbuf_desc)
return;
smc_ism_detach_dmb(smcd, peer_token);
kfree(conn->sndbuf_desc);
buf_desc = conn->sndbuf_desc;
conn->sndbuf_desc = NULL;
kfree(buf_desc);
}
static void smc_buf_unuse(struct smc_connection *conn,
@@ -1268,11 +1270,10 @@ void smc_conn_free(struct smc_connection *conn)
goto lgr_put;
if (lgr->is_smcd) {
if (!list_empty(&lgr->list))
smc_ism_unset_conn(conn);
smc_ism_unset_conn(conn);
tasklet_kill(&conn->rx_tsklet);
if (smc_ism_support_dmb_nocopy(lgr->smcd))
smcd_buf_detach(conn);
tasklet_kill(&conn->rx_tsklet);
} else {
smc_cdc_wait_pend_tx_wr(conn);
if (current_work() != &conn->abort_work)
@@ -1525,12 +1526,12 @@ static void smc_conn_kill(struct smc_connection *conn, bool soft)
smc_sk_wake_ups(smc);
if (conn->lgr->is_smcd) {
smc_ism_unset_conn(conn);
if (smc_ism_support_dmb_nocopy(conn->lgr->smcd))
smcd_buf_detach(conn);
if (soft)
tasklet_kill(&conn->rx_tsklet);
else
tasklet_unlock_wait(&conn->rx_tsklet);
if (smc_ism_support_dmb_nocopy(conn->lgr->smcd))
smcd_buf_detach(conn);
} else {
smc_cdc_wait_pend_tx_wr(conn);
}

View File

@@ -20,11 +20,15 @@
static inline int smc_tx_prepared_sends(struct smc_connection *conn)
{
struct smc_buf_desc *sndbuf_desc = READ_ONCE(conn->sndbuf_desc);
union smc_host_cursor sent, prep;
if (!sndbuf_desc)
return 0;
smc_curs_copy(&sent, &conn->tx_curs_sent, conn);
smc_curs_copy(&prep, &conn->tx_curs_prep, conn);
return smc_curs_diff(conn->sndbuf_desc->len, &sent, &prep);
return smc_curs_diff(sndbuf_desc->len, &sent, &prep);
}
void smc_tx_pending(struct smc_connection *conn);

View File

@@ -430,9 +430,10 @@ static int tls_strp_read_copy(struct tls_strparser *strp, bool qshort)
return 0;
}
static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
static bool tls_strp_check_queue_ok(struct tls_strparser *strp,
unsigned int len)
{
unsigned int len = strp->stm.offset + strp->stm.full_len;
unsigned int remaining = strp->stm.offset + len;
struct sk_buff *first, *skb;
u32 seq;
@@ -443,9 +444,9 @@ static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
/* Make sure there's no duplicate data in the queue,
* and the decrypted status matches.
*/
while (skb->len < len) {
while (skb->len < remaining) {
seq += skb->len;
len -= skb->len;
remaining -= skb->len;
skb = skb->next;
if (TCP_SKB_CB(skb)->seq != seq)
@@ -525,6 +526,11 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
tls_strp_load_anchor_with_queue(strp, inq);
if (!strp->stm.full_len) {
if (inq < TLS_HEADER_SIZE)
return tls_strp_read_copy(strp, true);
if (!tls_strp_check_queue_ok(strp, TLS_HEADER_SIZE))
return tls_strp_read_copy(strp, false);
sz = tls_rx_msg_size(strp, strp->anchor);
if (sz < 0)
return sz;
@@ -535,7 +541,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
return tls_strp_read_copy(strp, true);
}
if (!tls_strp_check_queue_ok(strp))
if (!tls_strp_check_queue_ok(strp, strp->stm.full_len))
return tls_strp_read_copy(strp, false);
WRITE_ONCE(strp->msg_ready, 1);

View File

@@ -38,10 +38,9 @@
* pending socket. When that socket reaches the connected state, it is removed
* from the listener socket's pending list and enqueued in the listener
* socket's accept queue. Callers of accept(2) will accept connected sockets
* from the listener socket's accept queue. If the socket cannot be accepted
* for some reason then it is marked rejected. Once the connection is
* accepted, it is owned by the user process and the responsibility for cleanup
* falls with that user process.
* from the listener socket's accept queue. Once the connection is accepted,
* it is owned by the user process and the responsibility for cleanup falls
* with that user process.
*
* - It is possible that these pending sockets will never reach the connected
* state; in fact, we may never receive another packet after the connection
@@ -49,9 +48,7 @@
* future, after some amount of time passes where a connection should have been
* established. This function ensures that the socket is off all lists so it
* cannot be retrieved, then drops all references to the socket so it is cleaned
* up (sock_put() -> sk_free() -> our sk_destruct implementation). Note this
* function will also cleanup rejected sockets, those that reach the connected
* state but leave it before they have been accepted.
* up (sock_put() -> sk_free() -> our sk_destruct implementation).
*
* - Lock ordering for pending or accept queue sockets is:
*
@@ -774,11 +771,10 @@ static void vsock_pending_work(struct work_struct *work)
if (vsock_is_pending(sk)) {
vsock_remove_pending(listener, sk);
} else if (!vsk->rejected) {
/* We are not on the pending list and accept() did not reject
* us, so we must have been accepted by our user process. We
* just need to drop our references to the sockets and be on
* our way.
} else {
/* We are not on the pending list so we must have been accepted
* by our user process. We just need to drop our references to
* the sockets and be on our way.
*/
cleanup = false;
goto out;
@@ -942,7 +938,6 @@ static struct sock *__vsock_create(struct net *net,
vsk->listener = NULL;
INIT_LIST_HEAD(&vsk->pending_links);
INIT_LIST_HEAD(&vsk->accept_queue);
vsk->rejected = false;
vsk->sent_request = false;
vsk->ignore_connecting_rst = false;
WRITE_ONCE(vsk->peer_shutdown, 0);
@@ -1847,12 +1842,10 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
}
if (sk->sk_err) {
err = -sk->sk_err;
err = sock_error(sk);
if (err) {
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
} else {
err = 0;
}
out_wait:
@@ -1893,7 +1886,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK);
while ((connected = vsock_dequeue_accept(listener)) == NULL &&
listener->sk_err == 0 && timeout != 0) {
timeout != 0) {
prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE);
release_sock(listener);
timeout = schedule_timeout(timeout);
@@ -1906,39 +1899,24 @@ static int vsock_accept(struct socket *sock, struct socket *newsock,
}
}
if (listener->sk_err) {
err = -listener->sk_err;
} else if (!connected) {
if (!connected) {
err = -EAGAIN;
}
if (connected) {
} else {
sk_acceptq_removed(listener);
lock_sock_nested(connected, SINGLE_DEPTH_NESTING);
vconnected = vsock_sk(connected);
/* If the listener socket has received an error, then we should
* reject this socket and return. Note that we simply mark the
* socket rejected, drop our reference, and let the cleanup
* function handle the cleanup; the fact that we found it in
* the listener's accept queue guarantees that the cleanup
* function hasn't run yet.
*/
if (err) {
vconnected->rejected = true;
} else {
newsock->state = SS_CONNECTED;
sock_graft(connected, newsock);
newsock->state = SS_CONNECTED;
sock_graft(connected, newsock);
set_bit(SOCK_CUSTOM_SOCKOPT,
set_bit(SOCK_CUSTOM_SOCKOPT,
&connected->sk_socket->flags);
if (vsock_msgzerocopy_allow(vconnected->transport))
set_bit(SOCK_SUPPORT_ZC,
&connected->sk_socket->flags);
if (vsock_msgzerocopy_allow(vconnected->transport))
set_bit(SOCK_SUPPORT_ZC,
&connected->sk_socket->flags);
}
release_sock(connected);
sock_put(connected);
}