Commit b2798bf0 authored by Linus Torvalds's avatar Linus Torvalds

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

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  can: add sanity checks
  fs_enet: restore promiscuous and multicast settings in restart()
  ibm_newemac: Fixes entry of short packets
  ibm_newemac: Fixes kernel crashes when speed of cable connected changes
  pasemi_mac: Access iph->tot_len with correct endianness
  ehea: Access iph->tot_len with correct endianness
  ehea: fix race condition
  ehea: add MODULE_DEVICE_TABLE
  ehea: fix might sleep problem
  forcedeth: fix lockdep warning on ethtool -s
  Add missing skb->dev assignment in Frame Relay RX code
  bridge: fix use-after-free in br_cleanup_bridges()
  tcp: fix a size_t < 0 comparison in tcp_read_sock
  tcp: net/ipv4/tcp.c needs linux/scatterlist.h
  libertas: support USB persistence on suspend/resume (resend)
  iwlwifi: drop skb silently for Tx request in monitor mode
  iwlwifi: fix incorrect 5GHz rates reported in monitor mode
parents 3bc5ab9b 7f2d38eb
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "ehea" #define DRV_NAME "ehea"
#define DRV_VERSION "EHEA_0091" #define DRV_VERSION "EHEA_0092"
/* eHEA capability flags */ /* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1 #define DLPAR_PORT_ADD_REM 1
...@@ -452,7 +452,7 @@ struct ehea_bcmc_reg_entry { ...@@ -452,7 +452,7 @@ struct ehea_bcmc_reg_entry {
struct ehea_bcmc_reg_array { struct ehea_bcmc_reg_array {
struct ehea_bcmc_reg_entry *arr; struct ehea_bcmc_reg_entry *arr;
int num_entries; int num_entries;
struct mutex lock; spinlock_t lock;
}; };
#define EHEA_PORT_UP 1 #define EHEA_PORT_UP 1
...@@ -478,6 +478,7 @@ struct ehea_port { ...@@ -478,6 +478,7 @@ struct ehea_port {
int num_add_tx_qps; int num_add_tx_qps;
int num_mcs; int num_mcs;
int resets; int resets;
u64 flags;
u64 mac_addr; u64 mac_addr;
u32 logical_port_id; u32 logical_port_id;
u32 port_speed; u32 port_speed;
...@@ -501,7 +502,8 @@ struct port_res_cfg { ...@@ -501,7 +502,8 @@ struct port_res_cfg {
}; };
enum ehea_flag_bits { enum ehea_flag_bits {
__EHEA_STOP_XFER __EHEA_STOP_XFER,
__EHEA_DISABLE_PORT_RESET
}; };
void ehea_set_ethtool_ops(struct net_device *netdev); void ehea_set_ethtool_ops(struct net_device *netdev);
......
...@@ -118,6 +118,7 @@ static struct of_device_id ehea_device_table[] = { ...@@ -118,6 +118,7 @@ static struct of_device_id ehea_device_table[] = {
}, },
{}, {},
}; };
MODULE_DEVICE_TABLE(of, ehea_device_table);
static struct of_platform_driver ehea_driver = { static struct of_platform_driver ehea_driver = {
.name = "ehea", .name = "ehea",
...@@ -137,6 +138,12 @@ void ehea_dump(void *adr, int len, char *msg) ...@@ -137,6 +138,12 @@ void ehea_dump(void *adr, int len, char *msg)
} }
} }
void ehea_schedule_port_reset(struct ehea_port *port)
{
if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
schedule_work(&port->reset_task);
}
static void ehea_update_firmware_handles(void) static void ehea_update_firmware_handles(void)
{ {
struct ehea_fw_handle_entry *arr = NULL; struct ehea_fw_handle_entry *arr = NULL;
...@@ -241,7 +248,7 @@ static void ehea_update_bcmc_registrations(void) ...@@ -241,7 +248,7 @@ static void ehea_update_bcmc_registrations(void)
} }
if (num_registrations) { if (num_registrations) {
arr = kzalloc(num_registrations * sizeof(*arr), GFP_KERNEL); arr = kzalloc(num_registrations * sizeof(*arr), GFP_ATOMIC);
if (!arr) if (!arr)
return; /* Keep the existing array */ return; /* Keep the existing array */
} else } else
...@@ -301,7 +308,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) ...@@ -301,7 +308,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats));
cb2 = kzalloc(PAGE_SIZE, GFP_KERNEL); cb2 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
if (!cb2) { if (!cb2) {
ehea_error("no mem for cb2"); ehea_error("no mem for cb2");
goto out; goto out;
...@@ -587,7 +594,7 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq, ...@@ -587,7 +594,7 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
"Resetting port.", pr->qp->init_attr.qp_nr); "Resetting port.", pr->qp->init_attr.qp_nr);
ehea_dump(cqe, sizeof(*cqe), "CQE"); ehea_dump(cqe, sizeof(*cqe), "CQE");
} }
schedule_work(&pr->port->reset_task); ehea_schedule_port_reset(pr->port);
return 1; return 1;
} }
...@@ -616,7 +623,7 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr, ...@@ -616,7 +623,7 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
*tcph = tcp_hdr(skb); *tcph = tcp_hdr(skb);
/* check if ip header and tcp header are complete */ /* check if ip header and tcp header are complete */
if (iph->tot_len < ip_len + tcp_hdrlen(skb)) if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
return -1; return -1;
*hdr_flags = LRO_IPV4 | LRO_TCP; *hdr_flags = LRO_IPV4 | LRO_TCP;
...@@ -765,7 +772,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota) ...@@ -765,7 +772,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
ehea_error("Send Completion Error: Resetting port"); ehea_error("Send Completion Error: Resetting port");
if (netif_msg_tx_err(pr->port)) if (netif_msg_tx_err(pr->port))
ehea_dump(cqe, sizeof(*cqe), "Send CQE"); ehea_dump(cqe, sizeof(*cqe), "Send CQE");
schedule_work(&pr->port->reset_task); ehea_schedule_port_reset(pr->port);
break; break;
} }
...@@ -885,7 +892,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param) ...@@ -885,7 +892,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
eqe = ehea_poll_eq(port->qp_eq); eqe = ehea_poll_eq(port->qp_eq);
} }
schedule_work(&port->reset_task); ehea_schedule_port_reset(port);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1763,7 +1770,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) ...@@ -1763,7 +1770,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len); memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
mutex_lock(&ehea_bcmc_regs.lock); spin_lock(&ehea_bcmc_regs.lock);
/* Deregister old MAC in pHYP */ /* Deregister old MAC in pHYP */
if (port->state == EHEA_PORT_UP) { if (port->state == EHEA_PORT_UP) {
...@@ -1785,7 +1792,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) ...@@ -1785,7 +1792,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
out_upregs: out_upregs:
ehea_update_bcmc_registrations(); ehea_update_bcmc_registrations();
mutex_unlock(&ehea_bcmc_regs.lock); spin_unlock(&ehea_bcmc_regs.lock);
out_free: out_free:
kfree(cb0); kfree(cb0);
out: out:
...@@ -1947,7 +1954,7 @@ static void ehea_set_multicast_list(struct net_device *dev) ...@@ -1947,7 +1954,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
} }
ehea_promiscuous(dev, 0); ehea_promiscuous(dev, 0);
mutex_lock(&ehea_bcmc_regs.lock); spin_lock(&ehea_bcmc_regs.lock);
if (dev->flags & IFF_ALLMULTI) { if (dev->flags & IFF_ALLMULTI) {
ehea_allmulti(dev, 1); ehea_allmulti(dev, 1);
...@@ -1978,7 +1985,7 @@ static void ehea_set_multicast_list(struct net_device *dev) ...@@ -1978,7 +1985,7 @@ static void ehea_set_multicast_list(struct net_device *dev)
} }
out: out:
ehea_update_bcmc_registrations(); ehea_update_bcmc_registrations();
mutex_unlock(&ehea_bcmc_regs.lock); spin_unlock(&ehea_bcmc_regs.lock);
return; return;
} }
...@@ -2497,7 +2504,7 @@ static int ehea_up(struct net_device *dev) ...@@ -2497,7 +2504,7 @@ static int ehea_up(struct net_device *dev)
} }
} }
mutex_lock(&ehea_bcmc_regs.lock); spin_lock(&ehea_bcmc_regs.lock);
ret = ehea_broadcast_reg_helper(port, H_REG_BCMC); ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
if (ret) { if (ret) {
...@@ -2520,7 +2527,7 @@ static int ehea_up(struct net_device *dev) ...@@ -2520,7 +2527,7 @@ static int ehea_up(struct net_device *dev)
ehea_info("Failed starting %s. ret=%i", dev->name, ret); ehea_info("Failed starting %s. ret=%i", dev->name, ret);
ehea_update_bcmc_registrations(); ehea_update_bcmc_registrations();
mutex_unlock(&ehea_bcmc_regs.lock); spin_unlock(&ehea_bcmc_regs.lock);
ehea_update_firmware_handles(); ehea_update_firmware_handles();
mutex_unlock(&ehea_fw_handles.lock); mutex_unlock(&ehea_fw_handles.lock);
...@@ -2575,7 +2582,7 @@ static int ehea_down(struct net_device *dev) ...@@ -2575,7 +2582,7 @@ static int ehea_down(struct net_device *dev)
mutex_lock(&ehea_fw_handles.lock); mutex_lock(&ehea_fw_handles.lock);
mutex_lock(&ehea_bcmc_regs.lock); spin_lock(&ehea_bcmc_regs.lock);
ehea_drop_multicast_list(dev); ehea_drop_multicast_list(dev);
ehea_broadcast_reg_helper(port, H_DEREG_BCMC); ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
...@@ -2584,7 +2591,7 @@ static int ehea_down(struct net_device *dev) ...@@ -2584,7 +2591,7 @@ static int ehea_down(struct net_device *dev)
port->state = EHEA_PORT_DOWN; port->state = EHEA_PORT_DOWN;
ehea_update_bcmc_registrations(); ehea_update_bcmc_registrations();
mutex_unlock(&ehea_bcmc_regs.lock); spin_unlock(&ehea_bcmc_regs.lock);
ret = ehea_clean_all_portres(port); ret = ehea_clean_all_portres(port);
if (ret) if (ret)
...@@ -2605,13 +2612,14 @@ static int ehea_stop(struct net_device *dev) ...@@ -2605,13 +2612,14 @@ static int ehea_stop(struct net_device *dev)
if (netif_msg_ifdown(port)) if (netif_msg_ifdown(port))
ehea_info("disabling port %s", dev->name); ehea_info("disabling port %s", dev->name);
set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
cancel_work_sync(&port->reset_task); cancel_work_sync(&port->reset_task);
mutex_lock(&port->port_lock); mutex_lock(&port->port_lock);
netif_stop_queue(dev); netif_stop_queue(dev);
port_napi_disable(port); port_napi_disable(port);
ret = ehea_down(dev); ret = ehea_down(dev);
mutex_unlock(&port->port_lock); mutex_unlock(&port->port_lock);
clear_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
return ret; return ret;
} }
...@@ -2941,7 +2949,7 @@ static void ehea_tx_watchdog(struct net_device *dev) ...@@ -2941,7 +2949,7 @@ static void ehea_tx_watchdog(struct net_device *dev)
if (netif_carrier_ok(dev) && if (netif_carrier_ok(dev) &&
!test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)) !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
schedule_work(&port->reset_task); ehea_schedule_port_reset(port);
} }
int ehea_sense_adapter_attr(struct ehea_adapter *adapter) int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
...@@ -3590,7 +3598,7 @@ int __init ehea_module_init(void) ...@@ -3590,7 +3598,7 @@ int __init ehea_module_init(void)
memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs)); memset(&ehea_bcmc_regs, 0, sizeof(ehea_bcmc_regs));
mutex_init(&ehea_fw_handles.lock); mutex_init(&ehea_fw_handles.lock);
mutex_init(&ehea_bcmc_regs.lock); spin_lock_init(&ehea_bcmc_regs.lock);
ret = check_module_parm(); ret = check_module_parm();
if (ret) if (ret)
......
...@@ -4194,12 +4194,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ...@@ -4194,12 +4194,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
netif_carrier_off(dev); netif_carrier_off(dev);
if (netif_running(dev)) { if (netif_running(dev)) {
unsigned long flags;
nv_disable_irq(dev); nv_disable_irq(dev);
netif_tx_lock_bh(dev); netif_tx_lock_bh(dev);
spin_lock(&np->lock); /* with plain spinlock lockdep complains */
spin_lock_irqsave(&np->lock, flags);
/* stop engines */ /* stop engines */
/* FIXME:
* this can take some time, and interrupts are disabled
* due to spin_lock_irqsave, but let's hope no daemon
* is going to change the settings very often...
* Worst case:
* NV_RXSTOP_DELAY1MAX + NV_TXSTOP_DELAY1MAX
* + some minor delays, which is up to a second approximately
*/
nv_stop_rxtx(dev); nv_stop_rxtx(dev);
spin_unlock(&np->lock); spin_unlock_irqrestore(&np->lock, flags);
netif_tx_unlock_bh(dev); netif_tx_unlock_bh(dev);
} }
......
...@@ -463,6 +463,9 @@ static void restart(struct net_device *dev) ...@@ -463,6 +463,9 @@ static void restart(struct net_device *dev)
else else
C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB);
/* Restore multicast and promiscuous settings */
set_multicast_list(dev);
S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT); S32(fccp, fcc_gfmr, FCC_GFMR_ENR | FCC_GFMR_ENT);
} }
......
...@@ -1636,6 +1636,12 @@ static int emac_poll_rx(void *param, int budget) ...@@ -1636,6 +1636,12 @@ static int emac_poll_rx(void *param, int budget)
goto next; goto next;
} }
if (len < ETH_HLEN) {
++dev->estats.rx_dropped_stack;
emac_recycle_rx_skb(dev, slot, len);
goto next;
}
if (len && len < EMAC_RX_COPY_THRESH) { if (len && len < EMAC_RX_COPY_THRESH) {
struct sk_buff *copy_skb = struct sk_buff *copy_skb =
alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC); alloc_skb(len + EMAC_RX_SKB_HEADROOM + 2, GFP_ATOMIC);
...@@ -2719,6 +2725,8 @@ static int __devinit emac_probe(struct of_device *ofdev, ...@@ -2719,6 +2725,8 @@ static int __devinit emac_probe(struct of_device *ofdev,
/* Clean rings */ /* Clean rings */
memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor)); memset(dev->tx_desc, 0, NUM_TX_BUFF * sizeof(struct mal_descriptor));
memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor)); memset(dev->rx_desc, 0, NUM_RX_BUFF * sizeof(struct mal_descriptor));
memset(dev->tx_skb, 0, NUM_TX_BUFF * sizeof(struct sk_buff *));
memset(dev->rx_skb, 0, NUM_RX_BUFF * sizeof(struct sk_buff *));
/* Attach to ZMII, if needed */ /* Attach to ZMII, if needed */
if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII) && if (emac_has_feature(dev, EMAC_FTR_HAS_ZMII) &&
......
...@@ -277,7 +277,7 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr, ...@@ -277,7 +277,7 @@ static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
*tcph = tcp_hdr(skb); *tcph = tcp_hdr(skb);
/* check if ip header and tcp header are complete */ /* check if ip header and tcp header are complete */
if (iph->tot_len < ip_len + tcp_hdrlen(skb)) if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
return -1; return -1;
*hdr_flags = LRO_IPV4 | LRO_TCP; *hdr_flags = LRO_IPV4 | LRO_TCP;
......
...@@ -1008,6 +1008,7 @@ static int fr_rx(struct sk_buff *skb) ...@@ -1008,6 +1008,7 @@ static int fr_rx(struct sk_buff *skb)
stats->rx_bytes += skb->len; stats->rx_bytes += skb->len;
if (pvc->state.becn) if (pvc->state.becn)
stats->rx_compressed++; stats->rx_compressed++;
skb->dev = dev;
netif_rx(skb); netif_rx(skb);
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
} else { } else {
......
...@@ -588,8 +588,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, ...@@ -588,8 +588,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
if (rate == -1) if (rate == -1)
iwl3945_rt->rt_rate = 0; iwl3945_rt->rt_rate = 0;
else else {
if (stats->band == IEEE80211_BAND_5GHZ)
rate += IWL_FIRST_OFDM_RATE;
iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee; iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
}
/* antenna number */ /* antenna number */
antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK;
......
...@@ -3528,8 +3528,12 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv, ...@@ -3528,8 +3528,12 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv,
if (rate == -1) if (rate == -1)
iwl4965_rt->rt_rate = 0; iwl4965_rt->rt_rate = 0;
else else {
if (stats->band == IEEE80211_BAND_5GHZ)
rate += IWL_FIRST_OFDM_RATE;
iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee; iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee;
}
/* /*
* "antenna number" * "antenna number"
......
...@@ -6687,7 +6687,8 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -6687,7 +6687,8 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
IWL_DEBUG_MAC80211("leave - monitor\n"); IWL_DEBUG_MAC80211("leave - monitor\n");
return -1; dev_kfree_skb_any(skb);
return 0;
} }
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
......
...@@ -6237,7 +6237,8 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -6237,7 +6237,8 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
IWL_DEBUG_MAC80211("leave - monitor\n"); IWL_DEBUG_MAC80211("leave - monitor\n");
return -1; dev_kfree_skb_any(skb);
return 0;
} }
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
......
...@@ -925,6 +925,7 @@ static struct usb_driver if_usb_driver = { ...@@ -925,6 +925,7 @@ static struct usb_driver if_usb_driver = {
.id_table = if_usb_table, .id_table = if_usb_table,
.suspend = if_usb_suspend, .suspend = if_usb_suspend,
.resume = if_usb_resume, .resume = if_usb_resume,
.reset_resume = if_usb_resume,
}; };
static int __init if_usb_init_module(void) static int __init if_usb_init_module(void)
......
...@@ -442,12 +442,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) ...@@ -442,12 +442,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
void __exit br_cleanup_bridges(void) void __exit br_cleanup_bridges(void)
{ {
struct net_device *dev, *nxt; struct net_device *dev;
rtnl_lock(); rtnl_lock();
for_each_netdev_safe(&init_net, dev, nxt) restart:
if (dev->priv_flags & IFF_EBRIDGE) for_each_netdev(&init_net, dev) {
if (dev->priv_flags & IFF_EBRIDGE) {
del_br(dev->priv); del_br(dev->priv);
goto restart;
}
}
rtnl_unlock(); rtnl_unlock();
} }
...@@ -205,12 +205,19 @@ static int can_create(struct net *net, struct socket *sock, int protocol) ...@@ -205,12 +205,19 @@ static int can_create(struct net *net, struct socket *sock, int protocol)
* -ENOBUFS on full driver queue (see net_xmit_errno()) * -ENOBUFS on full driver queue (see net_xmit_errno())
* -ENOMEM when local loopback failed at calling skb_clone() * -ENOMEM when local loopback failed at calling skb_clone()
* -EPERM when trying to send on a non-CAN interface * -EPERM when trying to send on a non-CAN interface
* -EINVAL when the skb->data does not contain a valid CAN frame
*/ */
int can_send(struct sk_buff *skb, int loop) int can_send(struct sk_buff *skb, int loop)
{ {
struct sk_buff *newskb = NULL; struct sk_buff *newskb = NULL;
struct can_frame *cf = (struct can_frame *)skb->data;
int err; int err;
if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) {
kfree_skb(skb);
return -EINVAL;
}
if (skb->dev->type != ARPHRD_CAN) { if (skb->dev->type != ARPHRD_CAN) {
kfree_skb(skb); kfree_skb(skb);
return -EPERM; return -EPERM;
...@@ -605,6 +612,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -605,6 +612,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev) struct packet_type *pt, struct net_device *orig_dev)
{ {
struct dev_rcv_lists *d; struct dev_rcv_lists *d;
struct can_frame *cf = (struct can_frame *)skb->data;
int matches; int matches;
if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) { if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) {
...@@ -612,6 +620,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -612,6 +620,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
return 0; return 0;
} }
BUG_ON(skb->len != sizeof(struct can_frame) || cf->can_dlc > 8);
/* update statistics */ /* update statistics */
can_stats.rx_frames++; can_stats.rx_frames++;
can_stats.rx_frames_delta++; can_stats.rx_frames_delta++;
......
...@@ -298,7 +298,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head, ...@@ -298,7 +298,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
if (head->nframes) { if (head->nframes) {
/* can_frames starting here */ /* can_frames starting here */
firstframe = (struct can_frame *) skb_tail_pointer(skb); firstframe = (struct can_frame *)skb_tail_pointer(skb);
memcpy(skb_put(skb, datalen), frames, datalen); memcpy(skb_put(skb, datalen), frames, datalen);
...@@ -826,6 +826,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, ...@@ -826,6 +826,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
for (i = 0; i < msg_head->nframes; i++) { for (i = 0; i < msg_head->nframes; i++) {
err = memcpy_fromiovec((u8 *)&op->frames[i], err = memcpy_fromiovec((u8 *)&op->frames[i],
msg->msg_iov, CFSIZ); msg->msg_iov, CFSIZ);
if (op->frames[i].can_dlc > 8)
err = -EINVAL;
if (err < 0) if (err < 0)
return err; return err;
...@@ -858,6 +862,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, ...@@ -858,6 +862,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
for (i = 0; i < msg_head->nframes; i++) { for (i = 0; i < msg_head->nframes; i++) {
err = memcpy_fromiovec((u8 *)&op->frames[i], err = memcpy_fromiovec((u8 *)&op->frames[i],
msg->msg_iov, CFSIZ); msg->msg_iov, CFSIZ);
if (op->frames[i].can_dlc > 8)
err = -EINVAL;
if (err < 0) { if (err < 0) {
if (op->frames != &op->sframe) if (op->frames != &op->sframe)
kfree(op->frames); kfree(op->frames);
...@@ -1164,9 +1172,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk) ...@@ -1164,9 +1172,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
skb->dev = dev; skb->dev = dev;
skb->sk = sk; skb->sk = sk;
can_send(skb, 1); /* send with loopback */ err = can_send(skb, 1); /* send with loopback */
dev_put(dev); dev_put(dev);
if (err)
return err;
return CFSIZ + MHSIZ; return CFSIZ + MHSIZ;
} }
...@@ -1185,6 +1196,10 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1185,6 +1196,10 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
if (!bo->bound) if (!bo->bound)
return -ENOTCONN; return -ENOTCONN;
/* check for valid message length from userspace */
if (size < MHSIZ || (size - MHSIZ) % CFSIZ)
return -EINVAL;
/* check for alternative ifindex for this bcm_op */ /* check for alternative ifindex for this bcm_op */
if (!ifindex && msg->msg_name) { if (!ifindex && msg->msg_name) {
...@@ -1259,8 +1274,8 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1259,8 +1274,8 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
break; break;
case TX_SEND: case TX_SEND:
/* we need at least one can_frame */ /* we need exactly one can_frame behind the msg head */
if (msg_head.nframes < 1) if ((msg_head.nframes != 1) || (size != CFSIZ + MHSIZ))
ret = -EINVAL; ret = -EINVAL;
else else
ret = bcm_tx_send(msg, ifindex, sk); ret = bcm_tx_send(msg, ifindex, sk);
......
...@@ -632,6 +632,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -632,6 +632,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
} else } else
ifindex = ro->ifindex; ifindex = ro->ifindex;
if (size != sizeof(struct can_frame))
return -EINVAL;
dev = dev_get_by_index(&init_net, ifindex); dev = dev_get_by_index(&init_net, ifindex);
if (!dev) if (!dev)
return -ENXIO; return -ENXIO;
......
...@@ -255,6 +255,7 @@ ...@@ -255,6 +255,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/scatterlist.h>
#include <linux/splice.h> #include <linux/splice.h>
#include <linux/net.h> #include <linux/net.h>
#include <linux/socket.h> #include <linux/socket.h>
...@@ -1208,7 +1209,8 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, ...@@ -1208,7 +1209,8 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
return -ENOTCONN; return -ENOTCONN;
while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
if (offset < skb->len) { if (offset < skb->len) {
size_t used, len; int used;
size_t len;
len = skb->len - offset; len = skb->len - offset;
/* Stop reading if we hit a patch of urgent data */ /* Stop reading if we hit a patch of urgent data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment