Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking tree from David Miller: 1) ptp_pch driver build broke during this merge window due to missing slab.h header, fix from Geery Uytterhoeven. 2) If ipset passes in a bogus hash table size we crash because the size is not validated properly. Compounding this, gcc-4.7 can miscompile ipset such that even when the user specifies legitimate parameters the tool passes in an out-of-range size to the kernel. Fix from Jozsef Kadlecsik. 3) Users have reported that the netdev watchdog can trigger with pch_gbe devices, and it turns out this is happening because of races in the TX path of the driver leading to the transmitter hanging. Fix from Eric Dumazet, reported and tested by Andy Cress. 4) Novatel USB551L devices match the generic class entries for the cdc ethernet USB driver, but they don't work because they have generic descriptors and thus need FLAG_WWAN to function properly. Add the necessary ID table entry to fix this, from Dan Williams. 5) A recursive locking fix in the USBNET driver added a new problem, in that packet list traversal is now racy and we can thus access unlinked SKBs and crash. Avoid this situation by adding some extra state tracking, from Ming Lei. 6) The rtlwifi conversion to asynchronous firmware loading is racy, fix by reordering the probe procedure. From Larry Finger. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=43187 7) Fix regressions with bluetooth keyboards by notifying userland properly when the security level changes, from Gustavo Padovan. 8) Bluetooth needs to make sure device connected events are emitted before other kinds of events, otherwise userspace will think there is no baseband link yet and therefore abort the sockets associated with that connection. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: netfilter: ipset: fix hash size checking in kernel ptp_pch: Add missing #include <linux/slab.h> pch_gbe: fix transmit races cdc_ether: add Novatel USB551L device IDs for FLAG_WWAN usbnet: fix skb traversing races during unlink(v2) Bluetooth: mgmt: Fix device_connected sending order Bluetooth: notify userspace of security level change rtlwifi: fix for race condition when firmware is cached
This commit is contained in:
Коммит
8011652957
|
@ -584,7 +584,6 @@ struct pch_gbe_hw_stats {
|
|||
/**
|
||||
* struct pch_gbe_adapter - board specific private data structure
|
||||
* @stats_lock: Spinlock structure for status
|
||||
* @tx_queue_lock: Spinlock structure for transmit
|
||||
* @ethtool_lock: Spinlock structure for ethtool
|
||||
* @irq_sem: Semaphore for interrupt
|
||||
* @netdev: Pointer of network device structure
|
||||
|
@ -609,7 +608,6 @@ struct pch_gbe_hw_stats {
|
|||
|
||||
struct pch_gbe_adapter {
|
||||
spinlock_t stats_lock;
|
||||
spinlock_t tx_queue_lock;
|
||||
spinlock_t ethtool_lock;
|
||||
atomic_t irq_sem;
|
||||
struct net_device *netdev;
|
||||
|
|
|
@ -640,14 +640,11 @@ static void pch_gbe_mac_set_pause_packet(struct pch_gbe_hw *hw)
|
|||
*/
|
||||
static int pch_gbe_alloc_queues(struct pch_gbe_adapter *adapter)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = (int)sizeof(struct pch_gbe_tx_ring);
|
||||
adapter->tx_ring = kzalloc(size, GFP_KERNEL);
|
||||
adapter->tx_ring = kzalloc(sizeof(*adapter->tx_ring), GFP_KERNEL);
|
||||
if (!adapter->tx_ring)
|
||||
return -ENOMEM;
|
||||
size = (int)sizeof(struct pch_gbe_rx_ring);
|
||||
adapter->rx_ring = kzalloc(size, GFP_KERNEL);
|
||||
|
||||
adapter->rx_ring = kzalloc(sizeof(*adapter->rx_ring), GFP_KERNEL);
|
||||
if (!adapter->rx_ring) {
|
||||
kfree(adapter->tx_ring);
|
||||
return -ENOMEM;
|
||||
|
@ -1162,7 +1159,6 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
|
|||
struct sk_buff *tmp_skb;
|
||||
unsigned int frame_ctrl;
|
||||
unsigned int ring_num;
|
||||
unsigned long flags;
|
||||
|
||||
/*-- Set frame control --*/
|
||||
frame_ctrl = 0;
|
||||
|
@ -1211,14 +1207,14 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
|
|||
}
|
||||
}
|
||||
}
|
||||
spin_lock_irqsave(&tx_ring->tx_lock, flags);
|
||||
|
||||
ring_num = tx_ring->next_to_use;
|
||||
if (unlikely((ring_num + 1) == tx_ring->count))
|
||||
tx_ring->next_to_use = 0;
|
||||
else
|
||||
tx_ring->next_to_use = ring_num + 1;
|
||||
|
||||
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
|
||||
|
||||
buffer_info = &tx_ring->buffer_info[ring_num];
|
||||
tmp_skb = buffer_info->skb;
|
||||
|
||||
|
@ -1518,7 +1514,7 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
|
|||
&rx_ring->rx_buff_pool_logic,
|
||||
GFP_KERNEL);
|
||||
if (!rx_ring->rx_buff_pool) {
|
||||
pr_err("Unable to allocate memory for the receive poll buffer\n");
|
||||
pr_err("Unable to allocate memory for the receive pool buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(rx_ring->rx_buff_pool, 0, size);
|
||||
|
@ -1637,15 +1633,17 @@ pch_gbe_clean_tx(struct pch_gbe_adapter *adapter,
|
|||
pr_debug("called pch_gbe_unmap_and_free_tx_resource() %d count\n",
|
||||
cleaned_count);
|
||||
/* Recover from running out of Tx resources in xmit_frame */
|
||||
spin_lock(&tx_ring->tx_lock);
|
||||
if (unlikely(cleaned && (netif_queue_stopped(adapter->netdev)))) {
|
||||
netif_wake_queue(adapter->netdev);
|
||||
adapter->stats.tx_restart_count++;
|
||||
pr_debug("Tx wake queue\n");
|
||||
}
|
||||
spin_lock(&adapter->tx_queue_lock);
|
||||
|
||||
tx_ring->next_to_clean = i;
|
||||
spin_unlock(&adapter->tx_queue_lock);
|
||||
|
||||
pr_debug("next_to_clean : %d\n", tx_ring->next_to_clean);
|
||||
spin_unlock(&tx_ring->tx_lock);
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
|
@ -2037,7 +2035,6 @@ static int pch_gbe_sw_init(struct pch_gbe_adapter *adapter)
|
|||
return -ENOMEM;
|
||||
}
|
||||
spin_lock_init(&adapter->hw.miim_lock);
|
||||
spin_lock_init(&adapter->tx_queue_lock);
|
||||
spin_lock_init(&adapter->stats_lock);
|
||||
spin_lock_init(&adapter->ethtool_lock);
|
||||
atomic_set(&adapter->irq_sem, 0);
|
||||
|
@ -2142,10 +2139,10 @@ static int pch_gbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
|||
tx_ring->next_to_use, tx_ring->next_to_clean);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
|
||||
|
||||
/* CRC,ITAG no support */
|
||||
pch_gbe_tx_queue(adapter, tx_ring, skb);
|
||||
spin_unlock_irqrestore(&tx_ring->tx_lock, flags);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -485,6 +485,7 @@ static const struct driver_info wwan_info = {
|
|||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define HUAWEI_VENDOR_ID 0x12D1
|
||||
#define NOVATEL_VENDOR_ID 0x1410
|
||||
|
||||
static const struct usb_device_id products [] = {
|
||||
/*
|
||||
|
@ -602,6 +603,21 @@ static const struct usb_device_id products [] = {
|
|||
* because of bugs/quirks in a given product (like Zaurus, above).
|
||||
*/
|
||||
{
|
||||
/* Novatel USB551L */
|
||||
/* This match must come *before* the generic CDC-ETHER match so that
|
||||
* we get FLAG_WWAN set on the device, since it's descriptors are
|
||||
* generic CDC-ETHER.
|
||||
*/
|
||||
.match_flags = USB_DEVICE_ID_MATCH_VENDOR
|
||||
| USB_DEVICE_ID_MATCH_PRODUCT
|
||||
| USB_DEVICE_ID_MATCH_INT_INFO,
|
||||
.idVendor = NOVATEL_VENDOR_ID,
|
||||
.idProduct = 0xB001,
|
||||
.bInterfaceClass = USB_CLASS_COMM,
|
||||
.bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
|
||||
.bInterfaceProtocol = USB_CDC_PROTO_NONE,
|
||||
.driver_info = (unsigned long)&wwan_info,
|
||||
}, {
|
||||
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long) &cdc_info,
|
||||
|
|
|
@ -282,17 +282,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usbnet_change_mtu);
|
||||
|
||||
/* The caller must hold list->lock */
|
||||
static void __usbnet_queue_skb(struct sk_buff_head *list,
|
||||
struct sk_buff *newsk, enum skb_state state)
|
||||
{
|
||||
struct skb_data *entry = (struct skb_data *) newsk->cb;
|
||||
|
||||
__skb_queue_tail(list, newsk);
|
||||
entry->state = state;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
|
||||
* completion callbacks. 2.5 should have fixed those bugs...
|
||||
*/
|
||||
|
||||
static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
|
||||
static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
|
||||
struct sk_buff_head *list, enum skb_state state)
|
||||
{
|
||||
unsigned long flags;
|
||||
enum skb_state old_state;
|
||||
struct skb_data *entry = (struct skb_data *) skb->cb;
|
||||
|
||||
spin_lock_irqsave(&list->lock, flags);
|
||||
old_state = entry->state;
|
||||
entry->state = state;
|
||||
__skb_unlink(skb, list);
|
||||
spin_unlock(&list->lock);
|
||||
spin_lock(&dev->done.lock);
|
||||
|
@ -300,6 +315,7 @@ static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_hea
|
|||
if (dev->done.qlen == 1)
|
||||
tasklet_schedule(&dev->bh);
|
||||
spin_unlock_irqrestore(&dev->done.lock, flags);
|
||||
return old_state;
|
||||
}
|
||||
|
||||
/* some work can't be done in tasklets, so we use keventd
|
||||
|
@ -340,7 +356,6 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
|
|||
entry = (struct skb_data *) skb->cb;
|
||||
entry->urb = urb;
|
||||
entry->dev = dev;
|
||||
entry->state = rx_start;
|
||||
entry->length = 0;
|
||||
|
||||
usb_fill_bulk_urb (urb, dev->udev, dev->in,
|
||||
|
@ -372,7 +387,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
|
|||
tasklet_schedule (&dev->bh);
|
||||
break;
|
||||
case 0:
|
||||
__skb_queue_tail (&dev->rxq, skb);
|
||||
__usbnet_queue_skb(&dev->rxq, skb, rx_start);
|
||||
}
|
||||
} else {
|
||||
netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
|
||||
|
@ -423,16 +438,17 @@ static void rx_complete (struct urb *urb)
|
|||
struct skb_data *entry = (struct skb_data *) skb->cb;
|
||||
struct usbnet *dev = entry->dev;
|
||||
int urb_status = urb->status;
|
||||
enum skb_state state;
|
||||
|
||||
skb_put (skb, urb->actual_length);
|
||||
entry->state = rx_done;
|
||||
state = rx_done;
|
||||
entry->urb = NULL;
|
||||
|
||||
switch (urb_status) {
|
||||
/* success */
|
||||
case 0:
|
||||
if (skb->len < dev->net->hard_header_len) {
|
||||
entry->state = rx_cleanup;
|
||||
state = rx_cleanup;
|
||||
dev->net->stats.rx_errors++;
|
||||
dev->net->stats.rx_length_errors++;
|
||||
netif_dbg(dev, rx_err, dev->net,
|
||||
|
@ -471,7 +487,7 @@ static void rx_complete (struct urb *urb)
|
|||
"rx throttle %d\n", urb_status);
|
||||
}
|
||||
block:
|
||||
entry->state = rx_cleanup;
|
||||
state = rx_cleanup;
|
||||
entry->urb = urb;
|
||||
urb = NULL;
|
||||
break;
|
||||
|
@ -482,17 +498,18 @@ block:
|
|||
// FALLTHROUGH
|
||||
|
||||
default:
|
||||
entry->state = rx_cleanup;
|
||||
state = rx_cleanup;
|
||||
dev->net->stats.rx_errors++;
|
||||
netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
|
||||
break;
|
||||
}
|
||||
|
||||
defer_bh(dev, skb, &dev->rxq);
|
||||
state = defer_bh(dev, skb, &dev->rxq, state);
|
||||
|
||||
if (urb) {
|
||||
if (netif_running (dev->net) &&
|
||||
!test_bit (EVENT_RX_HALT, &dev->flags)) {
|
||||
!test_bit (EVENT_RX_HALT, &dev->flags) &&
|
||||
state != unlink_start) {
|
||||
rx_submit (dev, urb, GFP_ATOMIC);
|
||||
usb_mark_last_busy(dev->udev);
|
||||
return;
|
||||
|
@ -579,16 +596,23 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
|
|||
static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb, *skbnext;
|
||||
struct sk_buff *skb;
|
||||
int count = 0;
|
||||
|
||||
spin_lock_irqsave (&q->lock, flags);
|
||||
skb_queue_walk_safe(q, skb, skbnext) {
|
||||
while (!skb_queue_empty(q)) {
|
||||
struct skb_data *entry;
|
||||
struct urb *urb;
|
||||
int retval;
|
||||
|
||||
entry = (struct skb_data *) skb->cb;
|
||||
skb_queue_walk(q, skb) {
|
||||
entry = (struct skb_data *) skb->cb;
|
||||
if (entry->state != unlink_start)
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
found:
|
||||
entry->state = unlink_start;
|
||||
urb = entry->urb;
|
||||
|
||||
/*
|
||||
|
@ -1039,8 +1063,7 @@ static void tx_complete (struct urb *urb)
|
|||
}
|
||||
|
||||
usb_autopm_put_interface_async(dev->intf);
|
||||
entry->state = tx_done;
|
||||
defer_bh(dev, skb, &dev->txq);
|
||||
(void) defer_bh(dev, skb, &dev->txq, tx_done);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
@ -1096,7 +1119,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|||
entry = (struct skb_data *) skb->cb;
|
||||
entry->urb = urb;
|
||||
entry->dev = dev;
|
||||
entry->state = tx_start;
|
||||
entry->length = length;
|
||||
|
||||
usb_fill_bulk_urb (urb, dev->udev, dev->out,
|
||||
|
@ -1155,7 +1177,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
|
|||
break;
|
||||
case 0:
|
||||
net->trans_start = jiffies;
|
||||
__skb_queue_tail (&dev->txq, skb);
|
||||
__usbnet_queue_skb(&dev->txq, skb, tx_start);
|
||||
if (dev->txq.qlen >= TX_QLEN (dev))
|
||||
netif_stop_queue (net);
|
||||
}
|
||||
|
|
|
@ -1851,14 +1851,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
/*like read eeprom and so on */
|
||||
rtlpriv->cfg->ops->read_eeprom_info(hw);
|
||||
|
||||
if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
|
||||
err = -ENODEV;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
rtlpriv->cfg->ops->init_sw_leds(hw);
|
||||
|
||||
/*aspm */
|
||||
rtl_pci_init_aspm(hw);
|
||||
|
||||
|
@ -1877,6 +1869,14 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
goto fail3;
|
||||
}
|
||||
|
||||
if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
|
||||
err = -ENODEV;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
rtlpriv->cfg->ops->init_sw_leds(hw);
|
||||
|
||||
err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
|
|
|
@ -971,11 +971,6 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
|
|||
rtlpriv->cfg->ops->read_chip_version(hw);
|
||||
/*like read eeprom and so on */
|
||||
rtlpriv->cfg->ops->read_eeprom_info(hw);
|
||||
if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
|
||||
goto error_out;
|
||||
}
|
||||
rtlpriv->cfg->ops->init_sw_leds(hw);
|
||||
err = _rtl_usb_init(hw);
|
||||
if (err)
|
||||
goto error_out;
|
||||
|
@ -987,6 +982,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf,
|
|||
"Can't allocate sw for mac80211\n");
|
||||
goto error_out;
|
||||
}
|
||||
if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
|
||||
goto error_out;
|
||||
}
|
||||
rtlpriv->cfg->ops->init_sw_leds(hw);
|
||||
|
||||
return 0;
|
||||
error_out:
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define STATION_ADDR_LEN 20
|
||||
#define PCI_DEVICE_ID_PCH_1588 0x8819
|
||||
|
|
|
@ -99,6 +99,22 @@ struct ip_set_hash {
|
|||
#endif
|
||||
};
|
||||
|
||||
static size_t
|
||||
htable_size(u8 hbits)
|
||||
{
|
||||
size_t hsize;
|
||||
|
||||
/* We must fit both into u32 in jhash and size_t */
|
||||
if (hbits > 31)
|
||||
return 0;
|
||||
hsize = jhash_size(hbits);
|
||||
if ((((size_t)-1) - sizeof(struct htable))/sizeof(struct hbucket)
|
||||
< hsize)
|
||||
return 0;
|
||||
|
||||
return hsize * sizeof(struct hbucket) + sizeof(struct htable);
|
||||
}
|
||||
|
||||
/* Compute htable_bits from the user input parameter hashsize */
|
||||
static u8
|
||||
htable_bits(u32 hashsize)
|
||||
|
|
|
@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usbnet *, struct urb *);
|
|||
enum skb_state {
|
||||
illegal = 0,
|
||||
tx_start, tx_done,
|
||||
rx_start, rx_done, rx_cleanup
|
||||
rx_start, rx_done, rx_cleanup,
|
||||
unlink_start
|
||||
};
|
||||
|
||||
struct skb_data { /* skb->cb is one of these */
|
||||
|
|
|
@ -191,6 +191,7 @@ struct bt_sock {
|
|||
struct list_head accept_q;
|
||||
struct sock *parent;
|
||||
u32 defer_setup;
|
||||
bool suspended;
|
||||
};
|
||||
|
||||
struct bt_sock_list {
|
||||
|
|
|
@ -450,7 +450,7 @@ unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wa
|
|||
sk->sk_state == BT_CONFIG)
|
||||
return mask;
|
||||
|
||||
if (sock_writeable(sk))
|
||||
if (!bt_sk(sk)->suspended && sock_writeable(sk))
|
||||
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
|
||||
else
|
||||
set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
|
||||
|
|
|
@ -2784,6 +2784,14 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
|||
if (conn) {
|
||||
hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
|
||||
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
|
||||
mgmt_device_connected(hdev, &conn->dst, conn->type,
|
||||
conn->dst_type, 0, NULL, 0,
|
||||
conn->dev_class);
|
||||
hci_dev_unlock(hdev);
|
||||
|
||||
/* Send to upper protocol */
|
||||
l2cap_recv_acldata(conn, skb, flags);
|
||||
return;
|
||||
|
|
|
@ -2039,6 +2039,12 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
|
|||
|
||||
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
|
||||
|
||||
if (ev->status && conn->state == BT_CONNECTED) {
|
||||
hci_acl_disconn(conn, 0x13);
|
||||
hci_conn_put(conn);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status)
|
||||
conn->state = BT_CONNECTED;
|
||||
|
@ -2049,6 +2055,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
|
|||
hci_encrypt_cfm(conn, ev->status, ev->encrypt);
|
||||
}
|
||||
|
||||
unlock:
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
|
@ -2102,7 +2109,7 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
if (!ev->status) {
|
||||
if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
|
||||
struct hci_cp_remote_name_req cp;
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
|
@ -2871,7 +2878,7 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
|
|||
if (conn->state != BT_CONFIG)
|
||||
goto unlock;
|
||||
|
||||
if (!ev->status) {
|
||||
if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
|
||||
struct hci_cp_remote_name_req cp;
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
|
|
|
@ -4589,6 +4589,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
|
|||
|
||||
if (!status && (chan->state == BT_CONNECTED ||
|
||||
chan->state == BT_CONFIG)) {
|
||||
struct sock *sk = chan->sk;
|
||||
|
||||
bt_sk(sk)->suspended = false;
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
l2cap_check_encryption(chan, encrypt);
|
||||
l2cap_chan_unlock(chan);
|
||||
continue;
|
||||
|
|
|
@ -592,10 +592,14 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
|
|||
sk->sk_state = BT_CONFIG;
|
||||
chan->state = BT_CONFIG;
|
||||
|
||||
/* or for ACL link, under defer_setup time */
|
||||
} else if (sk->sk_state == BT_CONNECT2 &&
|
||||
bt_sk(sk)->defer_setup) {
|
||||
err = l2cap_chan_check_security(chan);
|
||||
/* or for ACL link */
|
||||
} else if ((sk->sk_state == BT_CONNECT2 &&
|
||||
bt_sk(sk)->defer_setup) ||
|
||||
sk->sk_state == BT_CONNECTED) {
|
||||
if (!l2cap_chan_check_security(chan))
|
||||
bt_sk(sk)->suspended = true;
|
||||
else
|
||||
sk->sk_state_change(sk);
|
||||
} else {
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
|
|
@ -364,6 +364,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
{
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 netmask, hbits;
|
||||
size_t hsize;
|
||||
struct ip_set_hash *h;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
|
@ -405,9 +406,12 @@ hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -449,6 +449,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
size_t hsize;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
@ -476,9 +477,12 @@ hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -467,6 +467,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
size_t hsize;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
@ -494,9 +495,12 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -616,6 +616,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
size_t hsize;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
@ -645,9 +646,12 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -460,6 +460,7 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
struct ip_set_hash *h;
|
||||
u8 hbits;
|
||||
size_t hsize;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
@ -489,9 +490,12 @@ hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -722,6 +722,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
size_t hsize;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
@ -752,9 +753,12 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->ahash_max = AHASH_MAX_SIZE;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -572,6 +572,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
size_t hsize;
|
||||
|
||||
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
@ -601,9 +602,12 @@ hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
|
|||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket));
|
||||
hsize = htable_size(hbits);
|
||||
if (hsize == 0) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table = ip_set_alloc(hsize);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
|
|
Загрузка…
Ссылка в новой задаче