summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/9p/client.c60
-rw-r--r--net/Kconfig1
-rw-r--r--net/batman-adv/bat_iv_ogm.c86
-rw-r--r--net/batman-adv/bridge_loop_avoidance.c4
-rw-r--r--net/batman-adv/sysfs.c5
-rw-r--r--net/bluetooth/hci_core.c30
-rw-r--r--net/bluetooth/hidp/core.c56
-rw-r--r--net/bluetooth/hidp/hidp.h2
-rw-r--r--net/bluetooth/l2cap_core.c73
-rw-r--r--net/bluetooth/mgmt.c23
-rw-r--r--net/bluetooth/smp.c4
-rw-r--r--net/bridge/br_multicast.c5
-rw-r--r--net/ceph/auth_none.c6
-rw-r--r--net/ceph/osd_client.c65
-rw-r--r--net/core/dev.c34
-rw-r--r--net/core/dev_ioctl.c19
-rw-r--r--net/core/ethtool.c6
-rw-r--r--net/core/filter.c2
-rw-r--r--net/core/netpoll.c1
-rw-r--r--net/core/skbuff.c20
-rw-r--r--net/core/sock.c17
-rw-r--r--net/core/sock_diag.c9
-rw-r--r--net/core/utils.c22
-rw-r--r--net/ipv4/gre.c2
-rw-r--r--net/ipv4/inet_fragment.c2
-rw-r--r--net/ipv4/ip_tunnel.c4
-rw-r--r--net/ipv4/ip_vti.c3
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c12
-rw-r--r--net/ipv4/tcp_ipv4.c4
-rw-r--r--net/ipv6/addrconf.c12
-rw-r--r--net/ipv6/ip6_output.c13
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c2
-rw-r--r--net/key/af_key.c2
-rw-r--r--net/l2tp/l2tp_ppp.c6
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h5
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/mlme.c87
-rw-r--r--net/mac80211/rate.c2
-rw-r--r--net/mac80211/util.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c1
-rw-r--r--net/netfilter/nf_conntrack_labels.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c1
-rw-r--r--net/netfilter/nf_nat_sip.c3
-rw-r--r--net/netfilter/nfnetlink_acct.c7
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c7
-rw-r--r--net/netfilter/nfnetlink_queue_core.c6
-rw-r--r--net/netfilter/xt_TCPMSS.c23
-rw-r--r--net/netfilter/xt_TCPOPTSTRIP.c6
-rw-r--r--net/netlink/af_netlink.c2
-rw-r--r--net/packet/af_packet.c5
-rw-r--r--net/sched/sch_api.c11
-rw-r--r--net/sctp/outqueue.c6
-rw-r--r--net/sctp/socket.c6
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c4
-rw-r--r--net/sunrpc/clnt.c71
-rw-r--r--net/sunrpc/rpc_pipe.c8
-rw-r--r--net/sunrpc/sched.c21
-rw-r--r--net/sunrpc/svc.c2
-rw-r--r--net/unix/af_unix.c3
-rw-r--r--net/wireless/nl80211.c11
63 files changed, 596 insertions, 333 deletions
diff --git a/net/9p/client.c b/net/9p/client.c
index 8eb75425e6e6..01f1779eba80 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -127,7 +127,7 @@ static int parse_opts(char *opts, struct p9_client *clnt)
char *s;
int ret = 0;
- clnt->proto_version = p9_proto_2000u;
+ clnt->proto_version = p9_proto_2000L;
clnt->msize = 8192;
if (!opts)
@@ -562,36 +562,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
if (!p9_is_proto_dotl(c)) {
/* Error is reported in string format */
- uint16_t len;
- /* 7 = header size for RERROR, 2 is the size of string len; */
- int inline_len = in_hdrlen - (7 + 2);
+ int len;
+ /* 7 = header size for RERROR; */
+ int inline_len = in_hdrlen - 7;
- /* Read the size of error string */
- err = p9pdu_readf(req->rc, c->proto_version, "w", &len);
- if (err)
- goto out_err;
-
- ename = kmalloc(len + 1, GFP_NOFS);
- if (!ename) {
- err = -ENOMEM;
+ len = req->rc->size - req->rc->offset;
+ if (len > (P9_ZC_HDR_SZ - 7)) {
+ err = -EFAULT;
goto out_err;
}
- if (len <= inline_len) {
- /* We have error in protocol buffer itself */
- if (pdu_read(req->rc, ename, len)) {
- err = -EFAULT;
- goto out_free;
-
- }
- } else {
- /*
- * Part of the data is in user space buffer.
- */
- if (pdu_read(req->rc, ename, inline_len)) {
- err = -EFAULT;
- goto out_free;
- }
+ ename = &req->rc->sdata[req->rc->offset];
+ if (len > inline_len) {
+ /* We have error in external buffer */
if (kern_buf) {
memcpy(ename + inline_len, uidata,
len - inline_len);
@@ -600,19 +583,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
uidata, len - inline_len);
if (err) {
err = -EFAULT;
- goto out_free;
+ goto out_err;
}
}
}
- ename[len] = 0;
- if (p9_is_proto_dotu(c)) {
- /* For dotu we also have error code */
- err = p9pdu_readf(req->rc,
- c->proto_version, "d", &ecode);
- if (err)
- goto out_free;
+ ename = NULL;
+ err = p9pdu_readf(req->rc, c->proto_version, "s?d",
+ &ename, &ecode);
+ if (err)
+ goto out_err;
+
+ if (p9_is_proto_dotu(c))
err = -ecode;
- }
+
if (!err || !IS_ERR_VALUE(err)) {
err = p9_errstr2errno(ename, strlen(ename));
@@ -628,8 +611,6 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req,
}
return err;
-out_free:
- kfree(ename);
out_err:
p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err);
return err;
@@ -1015,6 +996,9 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
goto destroy_tagpool;
if (!clnt->trans_mod)
+ clnt->trans_mod = v9fs_get_trans_by_name("virtio");
+
+ if (!clnt->trans_mod)
clnt->trans_mod = v9fs_get_default_trans();
if (clnt->trans_mod == NULL) {
diff --git a/net/Kconfig b/net/Kconfig
index 2ddc9046868e..6dfe1c636a80 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -5,6 +5,7 @@
menuconfig NET
bool "Networking support"
select NLATTR
+ select GENERIC_NET_UTILS
---help---
Unless you really know what you are doing, you should say Y here.
The reason is that some programs need kernel networking support even
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 071f288b77a8..f680ee101878 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -29,6 +29,21 @@
#include "bat_algo.h"
#include "network-coding.h"
+/**
+ * batadv_dup_status - duplicate status
+ * @BATADV_NO_DUP: the packet is a duplicate
+ * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the
+ * neighbor)
+ * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor
+ * @BATADV_PROTECTED: originator is currently protected (after reboot)
+ */
+enum batadv_dup_status {
+ BATADV_NO_DUP = 0,
+ BATADV_ORIG_DUP,
+ BATADV_NEIGH_DUP,
+ BATADV_PROTECTED,
+};
+
static struct batadv_neigh_node *
batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface,
const uint8_t *neigh_addr,
@@ -650,7 +665,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
const struct batadv_ogm_packet *batadv_ogm_packet,
struct batadv_hard_iface *if_incoming,
const unsigned char *tt_buff,
- int is_duplicate)
+ enum batadv_dup_status dup_status)
{
struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
struct batadv_neigh_node *router = NULL;
@@ -676,7 +691,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
continue;
}
- if (is_duplicate)
+ if (dup_status != BATADV_NO_DUP)
continue;
spin_lock_bh(&tmp_neigh_node->lq_update_lock);
@@ -718,7 +733,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv);
spin_unlock_bh(&neigh_node->lq_update_lock);
- if (!is_duplicate) {
+ if (dup_status == BATADV_NO_DUP) {
orig_node->last_ttl = batadv_ogm_packet->header.ttl;
neigh_node->last_ttl = batadv_ogm_packet->header.ttl;
}
@@ -902,15 +917,16 @@ out:
return ret;
}
-/* processes a batman packet for all interfaces, adjusts the sequence number and
- * finds out whether it is a duplicate.
- * returns:
- * 1 the packet is a duplicate
- * 0 the packet has not yet been received
- * -1 the packet is old and has been received while the seqno window
- * was protected. Caller should drop it.
+/**
+ * batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces,
+ * adjust the sequence number and find out whether it is a duplicate
+ * @ethhdr: ethernet header of the packet
+ * @batadv_ogm_packet: OGM packet to be considered
+ * @if_incoming: interface on which the OGM packet was received
+ *
+ * Returns duplicate status as enum batadv_dup_status
*/
-static int
+static enum batadv_dup_status
batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
const struct batadv_ogm_packet *batadv_ogm_packet,
const struct batadv_hard_iface *if_incoming)
@@ -918,17 +934,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct batadv_orig_node *orig_node;
struct batadv_neigh_node *tmp_neigh_node;
- int is_duplicate = 0;
+ int is_dup;
int32_t seq_diff;
int need_update = 0;
- int set_mark, ret = -1;
+ int set_mark;
+ enum batadv_dup_status ret = BATADV_NO_DUP;
uint32_t seqno = ntohl(batadv_ogm_packet->seqno);
uint8_t *neigh_addr;
uint8_t packet_count;
orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig);
if (!orig_node)
- return 0;
+ return BATADV_NO_DUP;
spin_lock_bh(&orig_node->ogm_cnt_lock);
seq_diff = seqno - orig_node->last_real_seqno;
@@ -936,22 +953,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
/* signalize caller that the packet is to be dropped. */
if (!hlist_empty(&orig_node->neigh_list) &&
batadv_window_protected(bat_priv, seq_diff,
- &orig_node->batman_seqno_reset))
+ &orig_node->batman_seqno_reset)) {
+ ret = BATADV_PROTECTED;
goto out;
+ }
rcu_read_lock();
hlist_for_each_entry_rcu(tmp_neigh_node,
&orig_node->neigh_list, list) {
- is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits,
- orig_node->last_real_seqno,
- seqno);
-
neigh_addr = tmp_neigh_node->addr;
+ is_dup = batadv_test_bit(tmp_neigh_node->real_bits,
+ orig_node->last_real_seqno,
+ seqno);
+
if (batadv_compare_eth(neigh_addr, ethhdr->h_source) &&
- tmp_neigh_node->if_incoming == if_incoming)
+ tmp_neigh_node->if_incoming == if_incoming) {
set_mark = 1;
- else
+ if (is_dup)
+ ret = BATADV_NEIGH_DUP;
+ } else {
set_mark = 0;
+ if (is_dup && (ret != BATADV_NEIGH_DUP))
+ ret = BATADV_ORIG_DUP;
+ }
/* if the window moved, set the update flag. */
need_update |= batadv_bit_get_packet(bat_priv,
@@ -971,8 +995,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr,
orig_node->last_real_seqno = seqno;
}
- ret = is_duplicate;
-
out:
spin_unlock_bh(&orig_node->ogm_cnt_lock);
batadv_orig_node_free_ref(orig_node);
@@ -994,7 +1016,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
int is_broadcast = 0, is_bidirect;
bool is_single_hop_neigh = false;
bool is_from_best_next_hop = false;
- int is_duplicate, sameseq, simlar_ttl;
+ int sameseq, similar_ttl;
+ enum batadv_dup_status dup_status;
uint32_t if_incoming_seqno;
uint8_t *prev_sender;
@@ -1138,10 +1161,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
if (!orig_node)
return;
- is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
- if_incoming);
+ dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet,
+ if_incoming);
- if (is_duplicate == -1) {
+ if (dup_status == BATADV_PROTECTED) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: packet within seqno protection time (sender: %pM)\n",
ethhdr->h_source);
@@ -1211,11 +1234,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
* seqno and similar ttl as the non-duplicate
*/
sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno);
- simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
- if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl)))
+ similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl;
+ if (is_bidirect && ((dup_status == BATADV_NO_DUP) ||
+ (sameseq && similar_ttl)))
batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr,
batadv_ogm_packet, if_incoming,
- tt_buff, is_duplicate);
+ tt_buff, dup_status);
/* is single hop (direct) neighbor */
if (is_single_hop_neigh) {
@@ -1236,7 +1260,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
goto out_neigh;
}
- if (is_duplicate) {
+ if (dup_status == BATADV_NEIGH_DUP) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: duplicate packet received\n");
goto out_neigh;
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 379061c72549..de27b3175cfd 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1067,6 +1067,10 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN));
bat_priv->bla.claim_dest.group = group;
+ /* purge everything when bridge loop avoidance is turned off */
+ if (!atomic_read(&bat_priv->bridge_loop_avoidance))
+ oldif = NULL;
+
if (!oldif) {
batadv_bla_purge_claims(bat_priv, NULL, 1);
batadv_bla_purge_backbone_gw(bat_priv, 1);
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 15a22efa9a67..929e304dacb2 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -582,10 +582,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
(strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
goto out;
- if (!rtnl_trylock()) {
- ret = -ERESTARTSYS;
- goto out;
- }
+ rtnl_lock();
if (status_tmp == BATADV_IF_NOT_IN_USE) {
batadv_hardif_disable_interface(hard_iface,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 33843c5c4939..db7de80b88a2 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -341,7 +341,6 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt)
static void bredr_setup(struct hci_request *req)
{
- struct hci_cp_delete_stored_link_key cp;
__le16 param;
__u8 flt_type;
@@ -365,10 +364,6 @@ static void bredr_setup(struct hci_request *req)
param = __constant_cpu_to_le16(0x7d00);
hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
- bacpy(&cp.bdaddr, BDADDR_ANY);
- cp.delete_all = 0x01;
- hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
-
/* Read page scan parameters */
if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) {
hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
@@ -602,6 +597,16 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
struct hci_dev *hdev = req->hdev;
u8 p;
+ /* Only send HCI_Delete_Stored_Link_Key if it is supported */
+ if (hdev->commands[6] & 0x80) {
+ struct hci_cp_delete_stored_link_key cp;
+
+ bacpy(&cp.bdaddr, BDADDR_ANY);
+ cp.delete_all = 0x01;
+ hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY,
+ sizeof(cp), &cp);
+ }
+
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);
@@ -1555,11 +1560,15 @@ static const struct rfkill_ops hci_rfkill_ops = {
static void hci_power_on(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
+ int err;
BT_DBG("%s", hdev->name);
- if (hci_dev_open(hdev->id) < 0)
+ err = hci_dev_open(hdev->id);
+ if (err < 0) {
+ mgmt_set_powered_failed(hdev, err);
return;
+ }
if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
@@ -2202,16 +2211,15 @@ int hci_register_dev(struct hci_dev *hdev)
list_add(&hdev->list, &hci_dev_list);
write_unlock(&hci_dev_list_lock);
- hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1);
+ hdev->workqueue = alloc_workqueue("%s", WQ_HIGHPRI | WQ_UNBOUND |
+ WQ_MEM_RECLAIM, 1, hdev->name);
if (!hdev->workqueue) {
error = -ENOMEM;
goto err;
}
- hdev->req_workqueue = alloc_workqueue(hdev->name,
- WQ_HIGHPRI | WQ_UNBOUND |
- WQ_MEM_RECLAIM, 1);
+ hdev->req_workqueue = alloc_workqueue("%s", WQ_HIGHPRI | WQ_UNBOUND |
+ WQ_MEM_RECLAIM, 1, hdev->name);
if (!hdev->req_workqueue) {
destroy_workqueue(hdev->workqueue);
error = -ENOMEM;
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 940f5acb6694..46c6a148f0b3 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -851,6 +851,29 @@ static void hidp_session_dev_del(struct hidp_session *session)
}
/*
+ * Asynchronous device registration
+ * HID device drivers might want to perform I/O during initialization to
+ * detect device types. Therefore, call device registration in a separate
+ * worker so the HIDP thread can schedule I/O operations.
+ * Note that this must be called after the worker thread was initialized
+ * successfully. This will then add the devices and increase session state
+ * on success, otherwise it will terminate the session thread.
+ */
+static void hidp_session_dev_work(struct work_struct *work)
+{
+ struct hidp_session *session = container_of(work,
+ struct hidp_session,
+ dev_init);
+ int ret;
+
+ ret = hidp_session_dev_add(session);
+ if (!ret)
+ atomic_inc(&session->state);
+ else
+ hidp_session_terminate(session);
+}
+
+/*
* Create new session object
* Allocate session object, initialize static fields, copy input data into the
* object and take a reference to all sub-objects.
@@ -897,6 +920,7 @@ static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr,
session->idle_to = req->idle_to;
/* device management */
+ INIT_WORK(&session->dev_init, hidp_session_dev_work);
setup_timer(&session->timer, hidp_idle_timeout,
(unsigned long)session);
@@ -1035,8 +1059,8 @@ static void hidp_session_terminate(struct hidp_session *session)
* Probe HIDP session
* This is called from the l2cap_conn core when our l2cap_user object is bound
* to the hci-connection. We get the session via the \user object and can now
- * start the session thread, register the HID/input devices and link it into
- * the global session list.
+ * start the session thread, link it into the global session list and
+ * schedule HID/input device registration.
* The global session-list owns its own reference to the session object so you
* can drop your own reference after registering the l2cap_user object.
*/
@@ -1058,21 +1082,30 @@ static int hidp_session_probe(struct l2cap_conn *conn,
goto out_unlock;
}
+ if (session->input) {
+ ret = hidp_session_dev_add(session);
+ if (ret)
+ goto out_unlock;
+ }
+
ret = hidp_session_start_sync(session);
if (ret)
- goto out_unlock;
+ goto out_del;
- ret = hidp_session_dev_add(session);
- if (ret)
- goto out_stop;
+ /* HID device registration is async to allow I/O during probe */
+ if (session->input)
+ atomic_inc(&session->state);
+ else
+ schedule_work(&session->dev_init);
hidp_session_get(session);
list_add(&session->list, &hidp_session_list);
ret = 0;
goto out_unlock;
-out_stop:
- hidp_session_terminate(session);
+out_del:
+ if (session->input)
+ hidp_session_dev_del(session);
out_unlock:
up_write(&hidp_session_sem);
return ret;
@@ -1102,7 +1135,12 @@ static void hidp_session_remove(struct l2cap_conn *conn,
down_write(&hidp_session_sem);
hidp_session_terminate(session);
- hidp_session_dev_del(session);
+
+ cancel_work_sync(&session->dev_init);
+ if (session->input ||
+ atomic_read(&session->state) > HIDP_SESSION_PREPARING)
+ hidp_session_dev_del(session);
+
list_del(&session->list);
up_write(&hidp_session_sem);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 6162ce8606ac..9e6cc3553105 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -128,6 +128,7 @@ int hidp_get_conninfo(struct hidp_conninfo *ci);
enum hidp_session_state {
HIDP_SESSION_IDLING,
+ HIDP_SESSION_PREPARING,
HIDP_SESSION_RUNNING,
};
@@ -156,6 +157,7 @@ struct hidp_session {
unsigned long idle_to;
/* device management */
+ struct work_struct dev_init;
struct input_dev *input;
struct hid_device *hid;
struct timer_list timer;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a76d1ac0321b..68843a28a7af 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -2852,6 +2852,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code,
BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u",
conn, code, ident, dlen);
+ if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE)
+ return NULL;
+
len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
count = min_t(unsigned int, conn->mtu, len);
@@ -3677,10 +3680,14 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
}
static inline int l2cap_command_rej(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
+ if (cmd_len < sizeof(*rej))
+ return -EPROTO;
+
if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
return 0;
@@ -3829,11 +3836,14 @@ sendresp:
}
static int l2cap_connect_req(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
{
struct hci_dev *hdev = conn->hcon->hdev;
struct hci_conn *hcon = conn->hcon;
+ if (cmd_len < sizeof(struct l2cap_conn_req))
+ return -EPROTO;
+
hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
@@ -3847,7 +3857,8 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
}
static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
u16 scid, dcid, result, status;
@@ -3855,6 +3866,9 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
u8 req[128];
int err;
+ if (cmd_len < sizeof(*rsp))
+ return -EPROTO;
+
scid = __le16_to_cpu(rsp->scid);
dcid = __le16_to_cpu(rsp->dcid);
result = __le16_to_cpu(rsp->result);
@@ -3952,6 +3966,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
struct l2cap_chan *chan;
int len, err = 0;
+ if (cmd_len < sizeof(*req))
+ return -EPROTO;
+
dcid = __le16_to_cpu(req->dcid);
flags = __le16_to_cpu(req->flags);
@@ -3975,7 +3992,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
/* Reject if config buffer is too small. */
len = cmd_len - sizeof(*req);
- if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
+ if (chan->conf_len + len > sizeof(chan->conf_req)) {
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
l2cap_build_conf_rsp(chan, rsp,
L2CAP_CONF_REJECT, flags), rsp);
@@ -4053,14 +4070,18 @@ unlock:
}
static inline int l2cap_config_rsp(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
u16 scid, flags, result;
struct l2cap_chan *chan;
- int len = le16_to_cpu(cmd->len) - sizeof(*rsp);
+ int len = cmd_len - sizeof(*rsp);
int err = 0;
+ if (cmd_len < sizeof(*rsp))
+ return -EPROTO;
+
scid = __le16_to_cpu(rsp->scid);
flags = __le16_to_cpu(rsp->flags);
result = __le16_to_cpu(rsp->result);
@@ -4161,7 +4182,8 @@ done:
}
static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
struct l2cap_disconn_rsp rsp;
@@ -4169,6 +4191,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
struct l2cap_chan *chan;
struct sock *sk;
+ if (cmd_len != sizeof(*req))
+ return -EPROTO;
+
scid = __le16_to_cpu(req->scid);
dcid = __le16_to_cpu(req->dcid);
@@ -4208,12 +4233,16 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
}
static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
u16 dcid, scid;
struct l2cap_chan *chan;
+ if (cmd_len != sizeof(*rsp))
+ return -EPROTO;
+
scid = __le16_to_cpu(rsp->scid);
dcid = __le16_to_cpu(rsp->dcid);
@@ -4243,11 +4272,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
}
static inline int l2cap_information_req(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_info_req *req = (struct l2cap_info_req *) data;
u16 type;
+ if (cmd_len != sizeof(*req))
+ return -EPROTO;
+
type = __le16_to_cpu(req->type);
BT_DBG("type 0x%4.4x", type);
@@ -4294,11 +4327,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
}
static inline int l2cap_information_rsp(struct l2cap_conn *conn,
- struct l2cap_cmd_hdr *cmd, u8 *data)
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
+ u8 *data)
{
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
u16 type, result;
+ if (cmd_len < sizeof(*rsp))
+ return -EPROTO;
+
type = __le16_to_cpu(rsp->type);
result = __le16_to_cpu(rsp->result);
@@ -5164,16 +5201,16 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
switch (cmd->code) {
case L2CAP_COMMAND_REJ:
- l2cap_command_rej(conn, cmd, data);
+ l2cap_command_rej(conn, cmd, cmd_len, data);
break;
case L2CAP_CONN_REQ:
- err = l2cap_connect_req(conn, cmd, data);
+ err = l2cap_connect_req(conn, cmd, cmd_len, data);
break;
case L2CAP_CONN_RSP:
case L2CAP_CREATE_CHAN_RSP:
- err = l2cap_connect_create_rsp(conn, cmd, data);
+ err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_CONF_REQ:
@@ -5181,15 +5218,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_CONF_RSP:
- err = l2cap_config_rsp(conn, cmd, data);
+ err = l2cap_config_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_DISCONN_REQ:
- err = l2cap_disconnect_req(conn, cmd, data);
+ err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
break;
case L2CAP_DISCONN_RSP:
- err = l2cap_disconnect_rsp(conn, cmd, data);
+ err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_ECHO_REQ:
@@ -5200,11 +5237,11 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
break;
case L2CAP_INFO_REQ:
- err = l2cap_information_req(conn, cmd, data);
+ err = l2cap_information_req(conn, cmd, cmd_len, data);
break;
case L2CAP_INFO_RSP:
- err = l2cap_information_rsp(conn, cmd, data);
+ err = l2cap_information_rsp(conn, cmd, cmd_len, data);
break;
case L2CAP_CREATE_CHAN_REQ:
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 35fef22703e9..f8ecbc70293d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2700,7 +2700,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
break;
case DISCOV_TYPE_LE:
- if (!lmp_host_le_capable(hdev)) {
+ if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED);
mgmt_pending_remove(cmd);
@@ -3418,6 +3418,27 @@ new_settings:
return err;
}
+int mgmt_set_powered_failed(struct hci_dev *hdev, int err)
+{
+ struct pending_cmd *cmd;
+ u8 status;
+
+ cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
+ if (!cmd)
+ return -ENOENT;
+
+ if (err == -ERFKILL)
+ status = MGMT_STATUS_RFKILLED;
+ else
+ status = MGMT_STATUS_FAILED;
+
+ err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
+
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
{
struct cmd_lookup match = { NULL, hdev };
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index b2296d3857a0..b5562abdd6e0 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -770,7 +770,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
- if (!lmp_host_le_capable(hcon->hdev))
+ if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
return 1;
if (sec_level == BT_SECURITY_LOW)
@@ -851,7 +851,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
__u8 reason;
int err = 0;
- if (!lmp_host_le_capable(conn->hcon->hdev)) {
+ if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) {
err = -ENOTSUPP;
reason = SMP_PAIRING_NOTSUPP;
goto done;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 81f2389f78eb..d6448e35e027 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -465,8 +465,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
skb_set_transport_header(skb, skb->len);
mldq = (struct mld_msg *) icmp6_hdr(skb);
- interval = ipv6_addr_any(group) ? br->multicast_last_member_interval :
- br->multicast_query_response_interval;
+ interval = ipv6_addr_any(group) ?
+ br->multicast_query_response_interval :
+ br->multicast_last_member_interval;
mldq->mld_type = ICMPV6_MGM_QUERY;
mldq->mld_code = 0;
diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c
index 925ca583c09c..8c93fa8d81bc 100644
--- a/net/ceph/auth_none.c
+++ b/net/ceph/auth_none.c
@@ -39,6 +39,11 @@ static int should_authenticate(struct ceph_auth_client *ac)
return xi->starting;
}
+static int build_request(struct ceph_auth_client *ac, void *buf, void *end)
+{
+ return 0;
+}
+
/*
* the generic auth code decode the global_id, and we carry no actual
* authenticate state, so nothing happens here.
@@ -106,6 +111,7 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = {
.destroy = destroy,
.is_authenticated = is_authenticated,
.should_authenticate = should_authenticate,
+ .build_request = build_request,
.handle_reply = handle_reply,
.create_authorizer = ceph_auth_none_create_authorizer,
.destroy_authorizer = ceph_auth_none_destroy_authorizer,
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index d5953b87918c..dd47889adc4a 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -733,12 +733,14 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
object_size = le32_to_cpu(layout->fl_object_size);
object_base = off - objoff;
- if (truncate_size <= object_base) {
- truncate_size = 0;
- } else {
- truncate_size -= object_base;
- if (truncate_size > object_size)
- truncate_size = object_size;
+ if (!(truncate_seq == 1 && truncate_size == -1ULL)) {
+ if (truncate_size <= object_base) {
+ truncate_size = 0;
+ } else {
+ truncate_size -= object_base;
+ if (truncate_size > object_size)
+ truncate_size = object_size;
+ }
}
osd_req_op_extent_init(req, 0, opcode, objoff, objlen,
@@ -1174,6 +1176,7 @@ static void __register_linger_request(struct ceph_osd_client *osdc,
struct ceph_osd_request *req)
{
dout("__register_linger_request %p\n", req);
+ ceph_osdc_get_request(req);
list_add_tail(&req->r_linger_item, &osdc->req_linger);
if (req->r_osd)
list_add_tail(&req->r_linger_osd,
@@ -1196,6 +1199,7 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc,
if (list_empty(&req->r_osd_item))
req->r_osd = NULL;
}
+ ceph_osdc_put_request(req);
}
void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc,
@@ -1203,9 +1207,8 @@ void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc,
{
mutex_lock(&osdc->request_mutex);
if (req->r_linger) {
- __unregister_linger_request(osdc, req);
req->r_linger = 0;
- ceph_osdc_put_request(req);
+ __unregister_linger_request(osdc, req);
}
mutex_unlock(&osdc->request_mutex);
}
@@ -1217,11 +1220,6 @@ void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc,
if (!req->r_linger) {
dout("set_request_linger %p\n", req);
req->r_linger = 1;
- /*
- * caller is now responsible for calling
- * unregister_linger_request
- */
- ceph_osdc_get_request(req);
}
}
EXPORT_SYMBOL(ceph_osdc_set_request_linger);
@@ -1339,10 +1337,6 @@ static void __send_request(struct ceph_osd_client *osdc,
ceph_msg_get(req->r_request); /* send consumes a ref */
- /* Mark the request unsafe if this is the first timet's being sent. */
-
- if (!req->r_sent && req->r_unsafe_callback)
- req->r_unsafe_callback(req, true);
req->r_sent = req->r_osd->o_incarnation;
ceph_con_send(&req->r_osd->o_con, req->r_request);
@@ -1433,8 +1427,6 @@ static void handle_osds_timeout(struct work_struct *work)
static void complete_request(struct ceph_osd_request *req)
{
- if (req->r_unsafe_callback)
- req->r_unsafe_callback(req, false);
complete_all(&req->r_safe_completion); /* fsync waiter */
}
@@ -1526,6 +1518,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
for (i = 0; i < numops; i++)
req->r_reply_op_result[i] = ceph_decode_32(&p);
+ already_completed = req->r_got_reply;
+
if (!req->r_got_reply) {
req->r_result = result;
@@ -1556,19 +1550,23 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
((flags & CEPH_OSD_FLAG_WRITE) == 0))
__unregister_request(osdc, req);
- already_completed = req->r_completed;
- req->r_completed = 1;
mutex_unlock(&osdc->request_mutex);
- if (already_completed)
- goto done;
- if (req->r_callback)
- req->r_callback(req, msg);
- else
- complete_all(&req->r_completion);
+ if (!already_completed) {
+ if (req->r_unsafe_callback &&
+ result >= 0 && !(flags & CEPH_OSD_FLAG_ONDISK))
+ req->r_unsafe_callback(req, true);
+ if (req->r_callback)
+ req->r_callback(req, msg);
+ else
+ complete_all(&req->r_completion);
+ }
- if (flags & CEPH_OSD_FLAG_ONDISK)
+ if (flags & CEPH_OSD_FLAG_ONDISK) {
+ if (req->r_unsafe_callback && already_completed)
+ req->r_unsafe_callback(req, false);
complete_request(req);
+ }
done:
dout("req=%p req->r_linger=%d\n", req, req->r_linger);
@@ -1633,8 +1631,10 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
dout("%p tid %llu restart on osd%d\n",
req, req->r_tid,
req->r_osd ? req->r_osd->o_osd : -1);
+ ceph_osdc_get_request(req);
__unregister_request(osdc, req);
__register_linger_request(osdc, req);
+ ceph_osdc_put_request(req);
continue;
}
@@ -1675,13 +1675,13 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend)
__register_request(osdc, req);
__unregister_linger_request(osdc, req);
}
+ reset_changed_osds(osdc);
mutex_unlock(&osdc->request_mutex);
if (needmap) {
dout("%d requests for down osds, need new map\n", needmap);
ceph_monc_request_next_osdmap(&osdc->client->monc);
}
- reset_changed_osds(osdc);
}
@@ -2123,7 +2123,6 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
__register_request(osdc, req);
req->r_sent = 0;
req->r_got_reply = 0;
- req->r_completed = 0;
rc = __map_request(osdc, req, 0);
if (rc < 0) {
if (nofail) {
@@ -2456,8 +2455,10 @@ static struct ceph_msg *get_reply(struct ceph_connection *con,
ceph_msg_revoke_incoming(req->r_reply);
if (front > req->r_reply->front.iov_len) {
- pr_warning("get_reply front %d > preallocated %d\n",
- front, (int)req->r_reply->front.iov_len);
+ pr_warning("get_reply front %d > preallocated %d (%u#%llu)\n",
+ front, (int)req->r_reply->front.iov_len,
+ (unsigned int)con->peer_name.type,
+ le64_to_cpu(con->peer_name.num));
m = ceph_msg_new(CEPH_MSG_OSD_OPREPLY, front, GFP_NOFS, false);
if (!m)
goto out;
diff --git a/net/core/dev.c b/net/core/dev.c
index fc1e289397f5..faebb398fb46 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -792,6 +792,40 @@ struct net_device *dev_get_by_index(struct net *net, int ifindex)
EXPORT_SYMBOL(dev_get_by_index);
/**
+ * netdev_get_name - get a netdevice name, knowing its ifindex.
+ * @net: network namespace
+ * @name: a pointer to the buffer where the name will be stored.
+ * @ifindex: the ifindex of the interface to get the name from.
+ *
+ * The use of raw_seqcount_begin() and cond_resched() before
+ * retrying is required as we want to give the writers a chance
+ * to complete when CONFIG_PREEMPT is not set.
+ */
+int netdev_get_name(struct net *net, char *name, int ifindex)
+{
+ struct net_device *dev;
+ unsigned int seq;
+
+retry:
+ seq = raw_seqcount_begin(&devnet_rename_seq);
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(net, ifindex);
+ if (!dev) {
+ rcu_read_unlock();
+ return -ENODEV;
+ }
+
+ strcpy(name, dev->name);
+ rcu_read_unlock();
+ if (read_seqcount_retry(&devnet_rename_seq, seq)) {
+ cond_resched();
+ goto retry;
+ }
+
+ return 0;
+}
+
+/**
* dev_getbyhwaddr_rcu - find a device by its hardware address
* @net: the applicable net namespace
* @type: media type of device
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 6cc0481faade..5b7d0e1d0664 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -19,9 +19,8 @@
static int dev_ifname(struct net *net, struct ifreq __user *arg)
{
- struct net_device *dev;
struct ifreq ifr;
- unsigned seq;
+ int error;
/*
* Fetch the caller's info block.
@@ -30,19 +29,9 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
return -EFAULT;
-retry:
- seq = read_seqcount_begin(&devnet_rename_seq);
- rcu_read_lock();
- dev = dev_get_by_index_rcu(net, ifr.ifr_ifindex);
- if (!dev) {
- rcu_read_unlock();
- return -ENODEV;
- }
-
- strcpy(ifr.ifr_name, dev->name);
- rcu_read_unlock();
- if (read_seqcount_retry(&devnet_rename_seq, seq))
- goto retry;
+ error = netdev_get_name(net, ifr.ifr_name, ifr.ifr_ifindex);
+ if (error)
+ return error;
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
return -EFAULT;
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 22efdaa76ebf..ce91766eeca9 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -60,10 +60,10 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
[NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6",
[NETIF_F_HIGHDMA_BIT] = "highdma",
[NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist",
- [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-ctag-hw-insert",
+ [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-hw-insert",
- [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-ctag-hw-parse",
- [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-ctag-filter",
+ [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse",
+ [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-filter",
[NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert",
[NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse",
[NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter",
diff --git a/net/core/filter.c b/net/core/filter.c
index dad2a178f9f8..6438f29ff266 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -778,7 +778,7 @@ int sk_detach_filter(struct sock *sk)
}
EXPORT_SYMBOL_GPL(sk_detach_filter);
-static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
+void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
{
static const u16 decodes[] = {
[BPF_S_ALU_ADD_K] = BPF_ALU|BPF_ADD|BPF_K,
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index cec074be8c43..35a9f0804b6f 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -12,6 +12,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/moduleparam.h>
+#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/string.h>
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index cfd777bd6bd0..1c1738cc4538 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -483,15 +483,8 @@ EXPORT_SYMBOL(skb_add_rx_frag);
static void skb_drop_list(struct sk_buff **listp)
{
- struct sk_buff *list = *listp;
-
+ kfree_skb_list(*listp);
*listp = NULL;
-
- do {
- struct sk_buff *this = list;
- list = list->next;
- kfree_skb(this);
- } while (list);
}
static inline void skb_drop_fraglist(struct sk_buff *skb)
@@ -651,6 +644,17 @@ void kfree_skb(struct sk_buff *skb)
}
EXPORT_SYMBOL(kfree_skb);
+void kfree_skb_list(struct sk_buff *segs)
+{
+ while (segs) {
+ struct sk_buff *next = segs->next;
+
+ kfree_skb(segs);
+ segs = next;
+ }
+}
+EXPORT_SYMBOL(kfree_skb_list);
+
/**
* skb_tx_error - report an sk_buff xmit error
* @skb: buffer that triggered an error
diff --git a/net/core/sock.c b/net/core/sock.c
index 88868a9d21da..d6d024cfaaaf 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -571,9 +571,7 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
int ret = -ENOPROTOOPT;
#ifdef CONFIG_NETDEVICES
struct net *net = sock_net(sk);
- struct net_device *dev;
char devname[IFNAMSIZ];
- unsigned seq;
if (sk->sk_bound_dev_if == 0) {
len = 0;
@@ -584,20 +582,9 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
if (len < IFNAMSIZ)
goto out;
-retry:
- seq = read_seqcount_begin(&devnet_rename_seq);
- rcu_read_lock();
- dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
- ret = -ENODEV;
- if (!dev) {
- rcu_read_unlock();
+ ret = netdev_get_name(net, devname, sk->sk_bound_dev_if);
+ if (ret)
goto out;
- }
-
- strcpy(devname, dev->name);
- rcu_read_unlock();
- if (read_seqcount_retry(&devnet_rename_seq, seq))
- goto retry;
len = strlen(devname) + 1;
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index d5bef0b0f639..a0e9cf6379de 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -73,8 +73,13 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk,
goto out;
}
- if (filter)
- memcpy(nla_data(attr), filter->insns, len);
+ if (filter) {
+ struct sock_filter *fb = (struct sock_filter *)nla_data(attr);
+ int i;
+
+ for (i = 0; i < filter->len; i++, fb++)
+ sk_decode_filter(&filter->insns[i], fb);
+ }
out:
rcu_read_unlock();
diff --git a/net/core/utils.c b/net/core/utils.c
index 3c7f5b51b979..aa88e23fc87a 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -338,25 +338,3 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
csum_unfold(*sum)));
}
EXPORT_SYMBOL(inet_proto_csum_replace16);
-
-int mac_pton(const char *s, u8 *mac)
-{
- int i;
-
- /* XX:XX:XX:XX:XX:XX */
- if (strlen(s) < 3 * ETH_ALEN - 1)
- return 0;
-
- /* Don't dirty result unless string is valid MAC. */
- for (i = 0; i < ETH_ALEN; i++) {
- if (!isxdigit(s[i * 3]) || !isxdigit(s[i * 3 + 1]))
- return 0;
- if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
- return 0;
- }
- for (i = 0; i < ETH_ALEN; i++) {
- mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
- }
- return 1;
-}
-EXPORT_SYMBOL(mac_pton);
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index b2e805af9b87..7856d1651d05 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -178,7 +178,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
err = __skb_linearize(skb);
if (err) {
- kfree_skb(segs);
+ kfree_skb_list(segs);
segs = ERR_PTR(err);
goto out;
}
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 7e06641e36ae..cec539458307 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -93,7 +93,7 @@ void inet_frags_init(struct inet_frags *f)
}
rwlock_init(&f->lock);
- f->rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
+ f->rnd = (u32) ((totalram_pages ^ (totalram_pages >> 7)) ^
(jiffies ^ (jiffies >> 6)));
setup_timer(&f->secret_timer, inet_frag_secret_rebuild,
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index be2f8da0ae8e..7fa8f08fa7ae 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -853,7 +853,7 @@ void ip_tunnel_dellink(struct net_device *dev, struct list_head *head)
}
EXPORT_SYMBOL_GPL(ip_tunnel_dellink);
-int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
+int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id,
struct rtnl_link_ops *ops, char *devname)
{
struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id);
@@ -899,7 +899,7 @@ static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head)
unregister_netdevice_queue(itn->fb_tunnel_dev, head);
}
-void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn)
+void ip_tunnel_delete_net(struct ip_tunnel_net *itn)
{
LIST_HEAD(list);
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 9d2bdb2c1d3f..c118f6b576bb 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -361,8 +361,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
tunnel->err_count = 0;
}
- IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED |
- IPSKB_REROUTED);
+ memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
skb_dst_drop(skb);
skb_dst_set(skb, &rt->dst);
nf_reset(skb);
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index ff4b781b1056..32b0e978c8e0 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -125,15 +125,16 @@ static void ulog_send(struct ulog_net *ulog, unsigned int nlgroupnum)
/* timer function to flush queue in flushtimeout time */
static void ulog_timer(unsigned long data)
{
+ unsigned int groupnum = *((unsigned int *)data);
struct ulog_net *ulog = container_of((void *)data,
struct ulog_net,
- nlgroup[*(unsigned int *)data]);
+ nlgroup[groupnum]);
pr_debug("timer function called, calling ulog_send\n");
/* lock to protect against somebody modifying our structure
* from ipt_ulog_target at the same time */
spin_lock_bh(&ulog->lock);
- ulog_send(ulog, data);
+ ulog_send(ulog, groupnum);
spin_unlock_bh(&ulog->lock);
}
@@ -407,8 +408,11 @@ static int __net_init ulog_tg_net_init(struct net *net)
spin_lock_init(&ulog->lock);
/* initialize ulog_buffers */
- for (i = 0; i < ULOG_MAXNLGROUPS; i++)
- setup_timer(&ulog->ulog_buffers[i].timer, ulog_timer, i);
+ for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
+ ulog->nlgroup[i] = i;
+ setup_timer(&ulog->ulog_buffers[i].timer, ulog_timer,
+ (unsigned long)&ulog->nlgroup[i]);
+ }
ulog->nflognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg);
if (!ulog->nflognl)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 719652305a29..7999fc55c83b 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1003,7 +1003,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
struct tcp_sock *tp = tcp_sk(sk);
struct tcp_md5sig_info *md5sig;
- key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
+ key = tcp_md5_do_lookup(sk, addr, family);
if (key) {
/* Pre-existing entry - just update that one. */
memcpy(key->key, newkey, newkeylen);
@@ -1048,7 +1048,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
struct tcp_md5sig_key *key;
struct tcp_md5sig_info *md5sig;
- key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET);
+ key = tcp_md5_do_lookup(sk, addr, family);
if (!key)
return -ENOENT;
hlist_del_rcu(&key->node);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1bbf744c2cc3..4ab4c38958c6 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2655,6 +2655,9 @@ static void init_loopback(struct net_device *dev)
if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
continue;
+ if (sp_ifa->rt)
+ continue;
+
sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
/* Failure cases are ignored */
@@ -4303,6 +4306,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
struct inet6_ifaddr *ifp;
struct net_device *dev = idev->dev;
bool update_rs = false;
+ struct in6_addr ll_addr;
if (token == NULL)
return -EINVAL;
@@ -4322,11 +4326,9 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
write_unlock_bh(&idev->lock);
- if (!idev->dead && (idev->if_flags & IF_READY)) {
- struct in6_addr ll_addr;
-
- ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE |
- IFA_F_OPTIMISTIC);
+ if (!idev->dead && (idev->if_flags & IF_READY) &&
+ !ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE |
+ IFA_F_OPTIMISTIC)) {
/* If we're not ready, then normal ifup will take care
* of this. Otherwise, we need to request our rs here.
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index dae1949019d7..d5d20cde8d92 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -381,9 +381,8 @@ int ip6_forward(struct sk_buff *skb)
* cannot be fragmented, because there is no warranty
* that different fragments will go along one path. --ANK
*/
- if (opt->ra) {
- u8 *ptr = skb_network_header(skb) + opt->ra;
- if (ip6_call_ra_chain(skb, (ptr[2]<<8) + ptr[3]))
+ if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) {
+ if (ip6_call_ra_chain(skb, ntohs(opt->ra)))
return 0;
}
@@ -822,11 +821,17 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
const struct flowi6 *fl6)
{
struct ipv6_pinfo *np = inet6_sk(sk);
- struct rt6_info *rt = (struct rt6_info *)dst;
+ struct rt6_info *rt;
if (!dst)
goto out;
+ if (dst->ops->family != AF_INET6) {
+ dst_release(dst);
+ return NULL;
+ }
+
+ rt = (struct rt6_info *)dst;
/* Yes, checking route validity in not connected
* case is not very simple. Take into account,
* that we do not support routing by source, TOS,
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 2712ab22a174..ca4ffcc287f1 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1493,7 +1493,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
*/
if (ha)
- ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR, ha);
+ ndisc_fill_addr_option(buff, ND_OPT_TARGET_LL_ADDR, ha);
/*
* build redirect option and copy skb over to the new packet.
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 97bcf2bae857..c9b6a6e6a1e8 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -204,7 +204,7 @@ static unsigned int __ipv6_conntrack_in(struct net *net,
if (ct != NULL && !nf_ct_is_untracked(ct)) {
help = nfct_help(ct);
if ((help && help->helper) || !nf_ct_is_confirmed(ct)) {
- nf_conntrack_get_reasm(skb);
+ nf_conntrack_get_reasm(reasm);
NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
(struct net_device *)in,
(struct net_device *)out,
diff --git a/net/key/af_key.c b/net/key/af_key.c
index c5fbd7589681..9da862070dd8 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1710,6 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c)
hdr->sadb_msg_version = PF_KEY_V2;
hdr->sadb_msg_errno = (uint8_t) 0;
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+ hdr->sadb_msg_reserved = 0;
pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
@@ -2699,6 +2700,7 @@ static int key_notify_policy_flush(const struct km_event *c)
hdr->sadb_msg_errno = (uint8_t) 0;
hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+ hdr->sadb_msg_reserved = 0;
pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
return 0;
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 637a341c1e2d..8dec6876dc50 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -346,19 +346,19 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
skb_put(skb, 2);
/* Copy user data into skb */
- error = memcpy_fromiovec(skb->data, m->msg_iov, total_len);
+ error = memcpy_fromiovec(skb_put(skb, total_len), m->msg_iov,
+ total_len);
if (error < 0) {
kfree_skb(skb);
goto error_put_sess_tun;
}
- skb_put(skb, total_len);
l2tp_xmit_skb(session, skb, session->hdr_len);
sock_put(ps->tunnel_sock);
sock_put(sk);
- return error;
+ return total_len;
error_put_sess_tun:
sock_put(ps->tunnel_sock);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1a89c80e6407..4fdb306e42e0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1057,6 +1057,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
+ if (sdata->wdev.cac_started) {
+ cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
+ cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
+ GFP_KERNEL);
+ }
+
drv_stop_ap(sdata->local, sdata);
/* free all potentially still buffered bcast frames */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 44be28cfc6c4..9ca8e3278cc0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1497,10 +1497,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
ieee80211_tx_skb_tid(sdata, skb, 7);
}
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
+u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc);
-static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
+static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
+ bool action,
struct ieee802_11_elems *elems)
{
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8a7bfc47d577..8eae74ac4e1e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -921,7 +921,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
hw->queues = IEEE80211_MAX_QUEUES;
local->workqueue =
- alloc_ordered_workqueue(wiphy_name(local->hw.wiphy), 0);
+ alloc_ordered_workqueue("%s", 0, wiphy_name(local->hw.wiphy));
if (!local->workqueue) {
result = -ENOMEM;
goto fail_workqueue;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a8c2130c8ba4..741448b30825 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2522,8 +2522,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
u16 capab_info, aid;
struct ieee802_11_elems elems;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
+ const struct cfg80211_bss_ies *bss_ies = NULL;
+ struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
u32 changed = 0;
int err;
+ bool ret;
/* AssocResp and ReassocResp have identical structure */
@@ -2555,21 +2558,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
ifmgd->aid = aid;
/*
+ * Some APs are erroneously not including some information in their
+ * (re)association response frames. Try to recover by using the data
+ * from the beacon or probe response. This seems to afflict mobile
+ * 2G/3G/4G wifi routers, reported models include the "Onda PN51T",
+ * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device.
+ */
+ if ((assoc_data->wmm && !elems.wmm_param) ||
+ (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
+ (!elems.ht_cap_elem || !elems.ht_operation)) ||
+ (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
+ (!elems.vht_cap_elem || !elems.vht_operation))) {
+ const struct cfg80211_bss_ies *ies;
+ struct ieee802_11_elems bss_elems;
+
+ rcu_read_lock();
+ ies = rcu_dereference(cbss->ies);
+ if (ies)
+ bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
+ GFP_ATOMIC);
+ rcu_read_unlock();
+ if (!bss_ies)
+ return false;
+
+ ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
+ false, &bss_elems);
+ if (assoc_data->wmm &&
+ !elems.wmm_param && bss_elems.wmm_param) {
+ elems.wmm_param = bss_elems.wmm_param;
+ sdata_info(sdata,
+ "AP bug: WMM param missing from AssocResp\n");
+ }
+
+ /*
+ * Also check if we requested HT/VHT, otherwise the AP doesn't
+ * have to include the IEs in the (re)association response.
+ */
+ if (!elems.ht_cap_elem && bss_elems.ht_cap_elem &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
+ elems.ht_cap_elem = bss_elems.ht_cap_elem;
+ sdata_info(sdata,
+ "AP bug: HT capability missing from AssocResp\n");
+ }
+ if (!elems.ht_operation && bss_elems.ht_operation &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
+ elems.ht_operation = bss_elems.ht_operation;
+ sdata_info(sdata,
+ "AP bug: HT operation missing from AssocResp\n");
+ }
+ if (!elems.vht_cap_elem && bss_elems.vht_cap_elem &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
+ elems.vht_cap_elem = bss_elems.vht_cap_elem;
+ sdata_info(sdata,
+ "AP bug: VHT capa missing from AssocResp\n");
+ }
+ if (!elems.vht_operation && bss_elems.vht_operation &&
+ !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) {
+ elems.vht_operation = bss_elems.vht_operation;
+ sdata_info(sdata,
+ "AP bug: VHT operation missing from AssocResp\n");
+ }
+ }
+
+ /*
* We previously checked these in the beacon/probe response, so
* they should be present here. This is just a safety net.
*/
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
(!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) {
sdata_info(sdata,
- "HT AP is missing WMM params or HT capability/operation in AssocResp\n");
- return false;
+ "HT AP is missing WMM params or HT capability/operation\n");
+ ret = false;
+ goto out;
}
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) &&
(!elems.vht_cap_elem || !elems.vht_operation)) {
sdata_info(sdata,
- "VHT AP is missing VHT capability/operation in AssocResp\n");
- return false;
+ "VHT AP is missing VHT capability/operation\n");
+ ret = false;
+ goto out;
}
mutex_lock(&sdata->local->sta_mtx);
@@ -2580,7 +2648,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
sta = sta_info_get(sdata, cbss->bssid);
if (WARN_ON(!sta)) {
mutex_unlock(&sdata->local->sta_mtx);
- return false;
+ ret = false;
+ goto out;
}
sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
@@ -2633,7 +2702,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
sta->sta.addr);
WARN_ON(__sta_info_destroy(sta));
mutex_unlock(&sdata->local->sta_mtx);
- return false;
+ ret = false;
+ goto out;
}
mutex_unlock(&sdata->local->sta_mtx);
@@ -2673,7 +2743,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
ieee80211_sta_reset_beacon_monitor(sdata);
- return true;
+ ret = true;
+ out:
+ kfree(bss_ies);
+ return ret;
}
static enum rx_mgmt_action __must_check
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index d3f414fe67e0..a02bef35b134 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -615,7 +615,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata,
if (rates[i].idx < 0)
break;
- rate_idx_match_mask(&rates[i], sband, mask, chan_width,
+ rate_idx_match_mask(&rates[i], sband, chan_width, mask,
mcs_mask);
}
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 27e07150eb46..72e6292955bb 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -661,12 +661,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action,
+u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc)
{
size_t left = len;
- u8 *pos = start;
+ const u8 *pos = start;
bool calc_crc = filter != 0;
DECLARE_BITMAP(seen_elems, 256);
const u8 *ie;
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 05565d2b3a61..23b8eb53a569 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1442,7 +1442,8 @@ ignore_ipip:
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
- if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
+ if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol ||
+ IPPROTO_SCTP == cih->protocol)
offset += 2 * sizeof(__u16);
verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 5b142fb16480..9e6c2a075a4c 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2542,6 +2542,7 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
struct ip_vs_dest *dest;
struct ip_vs_dest_entry entry;
+ memset(&entry, 0, sizeof(entry));
list_for_each_entry(dest, &svc->destinations, n_list) {
if (count >= get->num_dests)
break;
diff --git a/net/netfilter/nf_conntrack_labels.c b/net/netfilter/nf_conntrack_labels.c
index 8fe2e99428b7..355d2ef08094 100644
--- a/net/netfilter/nf_conntrack_labels.c
+++ b/net/netfilter/nf_conntrack_labels.c
@@ -45,7 +45,7 @@ int nf_connlabel_set(struct nf_conn *ct, u16 bit)
if (test_bit(bit, labels->bits))
return 0;
- if (test_and_set_bit(bit, labels->bits))
+ if (!test_and_set_bit(bit, labels->bits))
nf_conntrack_event_cache(IPCT_LABEL, ct);
return 0;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 6d0f8a17c5b7..ecf065f94032 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1825,6 +1825,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
(1 << IPCT_ASSURED) |
(1 << IPCT_HELPER) |
+ (1 << IPCT_LABEL) |
(1 << IPCT_PROTOINFO) |
(1 << IPCT_NATSEQADJ) |
(1 << IPCT_MARK),
diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c
index 96ccdf78a29f..dac11f73868e 100644
--- a/net/netfilter/nf_nat_sip.c
+++ b/net/netfilter/nf_nat_sip.c
@@ -230,9 +230,10 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff,
&ct->tuplehash[!dir].tuple.src.u3,
false);
if (!mangle_packet(skb, protoff, dataoff, dptr, datalen,
- poff, plen, buffer, buflen))
+ poff, plen, buffer, buflen)) {
nf_ct_helper_log(skb, ct, "cannot mangle received");
return NF_DROP;
+ }
}
/* The rport= parameter (RFC 3581) contains the port number
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index dc3fd5d44464..c7b6d466a662 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -149,9 +149,12 @@ nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
list_for_each_entry_rcu(cur, &nfnl_acct_list, head) {
- if (last && cur != last)
- continue;
+ if (last) {
+ if (cur != last)
+ continue;
+ last = NULL;
+ }
if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index 701c88a20fea..65074dfb9383 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -220,9 +220,12 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
rcu_read_lock();
list_for_each_entry_rcu(cur, &cttimeout_list, head) {
- if (last && cur != last)
- continue;
+ if (last) {
+ if (cur != last)
+ continue;
+ last = NULL;
+ }
if (ctnl_timeout_fill_info(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 4e27fa035814..5352b2d2d5bf 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -637,9 +637,6 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
if (queue->copy_mode == NFQNL_COPY_NONE)
return -EINVAL;
- if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(entry->skb))
- return __nfqnl_enqueue_packet(net, queue, entry);
-
skb = entry->skb;
switch (entry->pf) {
@@ -651,6 +648,9 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
break;
}
+ if ((queue->flags & NFQA_CFG_F_GSO) || !skb_is_gso(skb))
+ return __nfqnl_enqueue_packet(net, queue, entry);
+
nf_bridge_adjust_skb_data(skb);
segs = skb_gso_segment(skb, 0);
/* Does not use PTR_ERR to limit the number of error codes that can be
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index a75240f0d42b..7011c71646f0 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -45,17 +45,22 @@ optlen(const u_int8_t *opt, unsigned int offset)
static int
tcpmss_mangle_packet(struct sk_buff *skb,
- const struct xt_tcpmss_info *info,
+ const struct xt_action_param *par,
unsigned int in_mtu,
unsigned int tcphoff,
unsigned int minlen)
{
+ const struct xt_tcpmss_info *info = par->targinfo;
struct tcphdr *tcph;
unsigned int tcplen, i;
__be16 oldval;
u16 newmss;
u8 *opt;
+ /* This is a fragment, no TCP header is available */
+ if (par->fragoff != 0)
+ return XT_CONTINUE;
+
if (!skb_make_writable(skb, skb->len))
return -1;
@@ -125,6 +130,18 @@ tcpmss_mangle_packet(struct sk_buff *skb,
skb_put(skb, TCPOLEN_MSS);
+ /*
+ * IPv4: RFC 1122 states "If an MSS option is not received at
+ * connection setup, TCP MUST assume a default send MSS of 536".
+ * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum
+ * length IPv6 header of 60, ergo the default MSS value is 1220
+ * Since no MSS was provided, we must use the default values
+ */
+ if (par->family == NFPROTO_IPV4)
+ newmss = min(newmss, (u16)536);
+ else
+ newmss = min(newmss, (u16)1220);
+
opt = (u_int8_t *)tcph + sizeof(struct tcphdr);
memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr));
@@ -182,7 +199,7 @@ tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par)
__be16 newlen;
int ret;
- ret = tcpmss_mangle_packet(skb, par->targinfo,
+ ret = tcpmss_mangle_packet(skb, par,
tcpmss_reverse_mtu(skb, PF_INET),
iph->ihl * 4,
sizeof(*iph) + sizeof(struct tcphdr));
@@ -211,7 +228,7 @@ tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par)
tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off);
if (tcphoff < 0)
return NF_DROP;
- ret = tcpmss_mangle_packet(skb, par->targinfo,
+ ret = tcpmss_mangle_packet(skb, par,
tcpmss_reverse_mtu(skb, PF_INET6),
tcphoff,
sizeof(*ipv6h) + sizeof(struct tcphdr));
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c
index 1eb1a44bfd3d..b68fa191710f 100644
--- a/net/netfilter/xt_TCPOPTSTRIP.c
+++ b/net/netfilter/xt_TCPOPTSTRIP.c
@@ -48,11 +48,13 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb,
return NF_DROP;
len = skb->len - tcphoff;
- if (len < (int)sizeof(struct tcphdr) ||
- tcp_hdr(skb)->doff * 4 > len)
+ if (len < (int)sizeof(struct tcphdr))
return NF_DROP;
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
+ if (tcph->doff * 4 > len)
+ return NF_DROP;
+
opt = (u_int8_t *)tcph;
/*
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d0b3dd60d386..57ee84d21470 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -371,7 +371,7 @@ static int netlink_mmap(struct file *file, struct socket *sock,
err = 0;
out:
mutex_unlock(&nlk->pg_vec_lock);
- return 0;
+ return err;
}
static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8ec1bca7f859..20a1bd0e6549 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2851,12 +2851,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
return -EOPNOTSUPP;
uaddr->sa_family = AF_PACKET;
+ memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data));
rcu_read_lock();
dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex);
if (dev)
- strncpy(uaddr->sa_data, dev->name, 14);
- else
- memset(uaddr->sa_data, 0, 14);
+ strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
rcu_read_unlock();
*uaddr_len = sizeof(*uaddr);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 2b935e7cfe7b..281c1bded1f6 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -291,17 +291,18 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta
{
struct qdisc_rate_table *rtab;
+ if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
+ nla_len(tab) != TC_RTAB_SIZE)
+ return NULL;
+
for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
- if (memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) == 0) {
+ if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) &&
+ !memcmp(&rtab->data, nla_data(tab), 1024)) {
rtab->refcnt++;
return rtab;
}
}
- if (tab == NULL || r->rate == 0 || r->cell_log == 0 ||
- nla_len(tab) != TC_RTAB_SIZE)
- return NULL;
-
rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
if (rtab) {
rtab->rate = *r;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 32a4625fef77..be35e2dbcc9a 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -206,6 +206,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary,
*/
void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
{
+ memset(q, 0, sizeof(struct sctp_outq));
+
q->asoc = asoc;
INIT_LIST_HEAD(&q->out_chunk_list);
INIT_LIST_HEAD(&q->control_chunk_list);
@@ -213,11 +215,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q)
INIT_LIST_HEAD(&q->sacked);
INIT_LIST_HEAD(&q->abandoned);
- q->fast_rtx = 0;
- q->outstanding_bytes = 0;
q->empty = 1;
- q->cork = 0;
- q->out_qlen = 0;
}
/* Free the outqueue structure and any related pending chunks.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index f631c5ff4dbf..6abb1caf9836 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4003,6 +4003,12 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk)
/* Release our hold on the endpoint. */
sp = sctp_sk(sk);
+ /* This could happen during socket init, thus we bail out
+ * early, since the rest of the below is not setup either.
+ */
+ if (sp->ep == NULL)
+ return;
+
if (sp->do_auto_asconf) {
sp->do_auto_asconf = 0;
list_del(&sp->auto_asconf_list);
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 29b4ba93ab3c..b05ace4c5f12 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1330,7 +1330,7 @@ static int wait_for_gss_proxy(struct net *net, struct file *file)
static ssize_t write_gssp(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct net *net = PDE_DATA(file->f_path.dentry->d_inode);
+ struct net *net = PDE_DATA(file_inode(file));
char tbuf[20];
unsigned long i;
int res;
@@ -1358,7 +1358,7 @@ static ssize_t write_gssp(struct file *file, const char __user *buf,
static ssize_t read_gssp(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct net *net = PDE_DATA(file->f_path.dentry->d_inode);
+ struct net *net = PDE_DATA(file_inode(file));
unsigned long p = *ppos;
char tbuf[10];
size_t len;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5a750b9c3640..f0339ae9bf37 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -157,20 +157,15 @@ static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb,
}
static int
-rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name)
+rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name,
+ struct super_block *pipefs_sb)
{
- struct net *net = rpc_net_ns(clnt);
- struct super_block *pipefs_sb;
struct dentry *dentry;
clnt->cl_dentry = NULL;
if (dir_name == NULL)
return 0;
- pipefs_sb = rpc_get_sb_net(net);
- if (!pipefs_sb)
- return 0;
dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name);
- rpc_put_sb_net(net);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
clnt->cl_dentry = dentry;
@@ -182,6 +177,8 @@ static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event
if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
return 1;
+ if ((event == RPC_PIPEFS_MOUNT) && atomic_read(&clnt->cl_count) == 0)
+ return 1;
return 0;
}
@@ -241,8 +238,6 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
continue;
if (rpc_clnt_skip_event(clnt, event))
continue;
- if (atomic_inc_not_zero(&clnt->cl_count) == 0)
- continue;
spin_unlock(&sn->rpc_client_lock);
return clnt;
}
@@ -259,7 +254,6 @@ static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event,
while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) {
error = __rpc_pipefs_event(clnt, event, sb);
- rpc_release_client(clnt);
if (error)
break;
}
@@ -289,12 +283,46 @@ static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
}
+static int rpc_client_register(const struct rpc_create_args *args,
+ struct rpc_clnt *clnt)
+{
+ const struct rpc_program *program = args->program;
+ struct rpc_auth *auth;
+ struct net *net = rpc_net_ns(clnt);
+ struct super_block *pipefs_sb;
+ int err = 0;
+
+ pipefs_sb = rpc_get_sb_net(net);
+ if (pipefs_sb) {
+ err = rpc_setup_pipedir(clnt, program->pipe_dir_name, pipefs_sb);
+ if (err)
+ goto out;
+ }
+
+ auth = rpcauth_create(args->authflavor, clnt);
+ if (IS_ERR(auth)) {
+ dprintk("RPC: Couldn't create auth handle (flavor %u)\n",
+ args->authflavor);
+ err = PTR_ERR(auth);
+ goto err_auth;
+ }
+
+ rpc_register_client(clnt);
+out:
+ if (pipefs_sb)
+ rpc_put_sb_net(net);
+ return err;
+
+err_auth:
+ __rpc_clnt_remove_pipedir(clnt);
+ goto out;
+}
+
static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
{
const struct rpc_program *program = args->program;
const struct rpc_version *version;
struct rpc_clnt *clnt = NULL;
- struct rpc_auth *auth;
int err;
/* sanity check the name before trying to print it */
@@ -354,25 +382,14 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
atomic_set(&clnt->cl_count, 1);
- err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
- if (err < 0)
- goto out_no_path;
-
- auth = rpcauth_create(args->authflavor, clnt);
- if (IS_ERR(auth)) {
- dprintk("RPC: Couldn't create auth handle (flavor %u)\n",
- args->authflavor);
- err = PTR_ERR(auth);
- goto out_no_auth;
- }
-
/* save the nodename */
rpc_clnt_set_nodename(clnt, utsname()->nodename);
- rpc_register_client(clnt);
+
+ err = rpc_client_register(args, clnt);
+ if (err)
+ goto out_no_path;
return clnt;
-out_no_auth:
- rpc_clnt_remove_pipedir(clnt);
out_no_path:
kfree(clnt->cl_principal);
out_no_principal:
@@ -637,8 +654,8 @@ rpc_free_client(struct rpc_clnt *clnt)
rcu_dereference(clnt->cl_xprt)->servername);
if (clnt->cl_parent != clnt)
rpc_release_client(clnt->cl_parent);
- rpc_unregister_client(clnt);
rpc_clnt_remove_pipedir(clnt);
+ rpc_unregister_client(clnt);
rpc_free_iostats(clnt->cl_metrics);
kfree(clnt->cl_principal);
clnt->cl_metrics = NULL;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index e7ce4b3eb0bd..4679df5a6d50 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -667,7 +667,8 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent,
return ERR_PTR(-ENOMEM);
}
if (dentry->d_inode == NULL) {
- d_set_d_op(dentry, &rpc_dentry_operations);
+ if (!dentry->d_op)
+ d_set_d_op(dentry, &rpc_dentry_operations);
return dentry;
}
dput(dentry);
@@ -1126,6 +1127,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
return -ENOMEM;
dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n",
net, NET_NAME(net));
+ mutex_lock(&sn->pipefs_sb_lock);
sn->pipefs_sb = sb;
err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
RPC_PIPEFS_MOUNT,
@@ -1133,6 +1135,7 @@ rpc_fill_super(struct super_block *sb, void *data, int silent)
if (err)
goto err_depopulate;
sb->s_fs_info = get_net(net);
+ mutex_unlock(&sn->pipefs_sb_lock);
return 0;
err_depopulate:
@@ -1141,6 +1144,7 @@ err_depopulate:
sb);
sn->pipefs_sb = NULL;
__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
+ mutex_unlock(&sn->pipefs_sb_lock);
return err;
}
@@ -1162,12 +1166,12 @@ static void rpc_kill_sb(struct super_block *sb)
goto out;
}
sn->pipefs_sb = NULL;
- mutex_unlock(&sn->pipefs_sb_lock);
dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n",
net, NET_NAME(net));
blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
RPC_PIPEFS_UMOUNT,
sb);
+ mutex_unlock(&sn->pipefs_sb_lock);
put_net(net);
out:
kill_litter_super(sb);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 5356b120dbf8..93a7a4e94d80 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -254,7 +254,7 @@ static int rpc_wait_bit_killable(void *word)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
- freezable_schedule();
+ freezable_schedule_unsafe();
return 0;
}
@@ -446,20 +446,6 @@ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct r
}
/*
- * Tests whether rpc queue is empty
- */
-int rpc_queue_empty(struct rpc_wait_queue *queue)
-{
- int res;
-
- spin_lock_bh(&queue->lock);
- res = queue->qlen;
- spin_unlock_bh(&queue->lock);
- return res == 0;
-}
-EXPORT_SYMBOL_GPL(rpc_queue_empty);
-
-/*
* Wake up a task on a specific queue
*/
void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task)
@@ -804,7 +790,6 @@ static void __rpc_execute(struct rpc_task *task)
task->tk_flags |= RPC_TASK_KILLED;
rpc_exit(task, -ERESTARTSYS);
}
- rpc_set_running(task);
dprintk("RPC: %5u sync task resuming\n", task->tk_pid);
}
@@ -825,9 +810,11 @@ static void __rpc_execute(struct rpc_task *task)
*/
void rpc_execute(struct rpc_task *task)
{
+ bool is_async = RPC_IS_ASYNC(task);
+
rpc_set_active(task);
rpc_make_runnable(task);
- if (!RPC_IS_ASYNC(task))
+ if (!is_async)
__rpc_execute(task);
}
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 89a588b4478b..b974571126fe 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -740,7 +740,7 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
__module_get(serv->sv_module);
task = kthread_create_on_node(serv->sv_function, rqstp,
- node, serv->sv_name);
+ node, "%s", serv->sv_name);
if (IS_ERR(task)) {
error = PTR_ERR(task);
module_put(serv->sv_module);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 826e09938bff..c4ce243824bb 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -114,6 +114,7 @@
#include <linux/mount.h>
#include <net/checksum.h>
#include <linux/security.h>
+#include <linux/freezer.h>
struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
EXPORT_SYMBOL_GPL(unix_socket_table);
@@ -1879,7 +1880,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo,
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
unix_state_unlock(sk);
- timeo = schedule_timeout(timeo);
+ timeo = freezable_schedule_timeout(timeo);
unix_state_lock(sk);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d5aed3bb3945..b14b7e3cb6e6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1564,12 +1564,17 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
struct cfg80211_registered_device *dev;
s64 filter_wiphy = -1;
bool split = false;
- struct nlattr **tb = nl80211_fam.attrbuf;
+ struct nlattr **tb;
int res;
+ /* will be zeroed in nlmsg_parse() */
+ tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL);
+ if (!tb)
+ return -ENOMEM;
+
mutex_lock(&cfg80211_mutex);
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
- tb, nl80211_fam.maxattr, nl80211_policy);
+ tb, NL80211_ATTR_MAX, nl80211_policy);
if (res == 0) {
split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP];
if (tb[NL80211_ATTR_WIPHY])
@@ -1583,6 +1588,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
if (!netdev) {
mutex_unlock(&cfg80211_mutex);
+ kfree(tb);
return -ENODEV;
}
if (netdev->ieee80211_ptr) {
@@ -1593,6 +1599,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
dev_put(netdev);
}
}
+ kfree(tb);
list_for_each_entry(dev, &cfg80211_rdev_list, list) {
if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk)))