aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Al-Asadi <alasadi56@gmail.com>2017-11-20 19:16:17 +0100
committerAli Al-Asadi <alasadi56@gmail.com>2017-11-20 19:17:37 +0100
commitfbe6feeff76b5b11031a95c38f49125d979a310f (patch)
treee6673c1faefaaa03ccee9580add98738bffa3c8c
parentac647004adb3fa02d0900825aaffcaff496fafdc (diff)
parent4d3a6849e576efbedc83a59095eecf305a57b1a2 (diff)
Merge https://github.com/LineageOS/android_kernel_motorola_msm8952 into n7.1n7.1
Change-Id: I0ff4601ef70e26a89871b5c200749e79569b6494
-rw-r--r--arch/x86/kernel/acpi/boot.c8
-rw-r--r--drivers/char/diag/diagchar.h1
-rw-r--r--drivers/char/diag/diagchar_core.c24
-rw-r--r--drivers/char/diag/diagfwd.c44
-rw-r--r--drivers/coresight/coresight-tmc.c33
-rw-r--r--drivers/crypto/msm/qcedev.c14
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.c121
-rw-r--r--drivers/input/misc/keychord.c90
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c31
-rw-r--r--drivers/input/touchscreen/synaptics_i2c_rmi4.c31
-rwxr-xr-x[-rw-r--r--]drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c8
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c40
-rw-r--r--drivers/misc/uid_sys_stats.c26
-rw-r--r--drivers/mmc/host/cmdq_hci.c37
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c5
-rw-r--r--drivers/net/wireless/cnss/cnss_pci.c64
-rw-r--r--drivers/net/wireless/wcnss/wcnss_wlan.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_rt.c6
-rw-r--r--drivers/platform/msm/ipa/rmnet_ipa.c3
-rw-r--r--drivers/soc/qcom/msm_glink_pkt.c46
-rw-r--r--drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h3
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c65
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c1
-rw-r--r--drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c1
-rw-r--r--drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h4
-rw-r--r--drivers/staging/prima/CORE/MAC/src/include/dot11f.h6
-rw-r--r--drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c355
-rw-r--r--drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c6
-rw-r--r--drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h4
-rw-r--r--drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c27
-rw-r--r--drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c9
-rw-r--r--drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c12
-rwxr-xr-x[-rw-r--r--]drivers/staging/prima/CORE/VOSS/inc/vos_types.h0
-rw-r--r--drivers/usb/phy/phy-msm-usb.c2
-rw-r--r--drivers/video/msm/mdss/mdss_dsi.c9
-rwxr-xr-xfs/sdcardfs/file.c16
-rwxr-xr-xfs/sdcardfs/inode.c6
-rw-r--r--include/linux/pid.h4
-rw-r--r--include/linux/sched.h17
-rw-r--r--kernel/events/core.c60
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/pid.c11
-rw-r--r--net/bluetooth/l2cap_core.c80
-rw-r--r--net/key/af_key.c47
-rw-r--r--net/netfilter/xt_qtaguid.c68
-rw-r--r--net/netfilter/xt_qtaguid_internal.h4
-rw-r--r--net/xfrm/xfrm_user.c18
-rw-r--r--sound/core/seq/seq_clientmgr.c6
-rw-r--r--sound/core/seq/seq_ports.c7
-rw-r--r--sound/soc/msm/qdsp6v2/audio_calibration.c14
50 files changed, 1047 insertions, 452 deletions
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 230c8ea878e..ba8b7bab211 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -968,6 +968,14 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
struct mpc_intsrc mp_irq;
/*
+ * Check bus_irq boundary.
+ */
+ if (bus_irq >= NR_IRQS_LEGACY) {
+ pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq);
+ return;
+ }
+
+ /*
* Convert 'gsi' to 'ioapic.pin'.
*/
ioapic = mp_find_ioapic(gsi);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9f1fe171150..491f4fa3a14 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -503,6 +503,7 @@ struct diagchar_dev {
unsigned char *buf_feature_mask_update;
uint8_t hdlc_disabled;
struct mutex hdlc_disable_mutex;
+ struct mutex hdlc_recovery_mutex;
struct timer_list hdlc_reset_timer;
struct mutex diag_hdlc_mutex;
unsigned char *hdlc_buf;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 96da705f031..9d908497f89 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -943,14 +943,29 @@ static int diag_send_raw_data_remote(int proc, void *buf, int len,
return -EAGAIN;
if (driver->hdlc_disabled) {
+ if (len < 4) {
+ pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
+ __func__, len);
+ return -EBADMSG;
+ }
payload = *(uint16_t *)(buf + 2);
driver->hdlc_encode_buf_len = payload;
/*
- * Adding 4 bytes for start (1 byte), version (1 byte) and
- * payload (2 bytes)
+ * Adding 5 bytes for start (1 byte), version (1 byte),
+ * payload (2 bytes) and end (1 byte)
*/
- memcpy(driver->hdlc_encode_buf, buf + 4, payload);
- goto send_data;
+ if (len == (payload + 5)) {
+ /*
+ * Adding 4 bytes for start (1 byte), version (1 byte)
+ * and payload (2 bytes)
+ */
+ memcpy(driver->hdlc_encode_buf, buf + 4, payload);
+ goto send_data;
+ } else {
+ pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
+ __func__, len);
+ return -EBADMSG;
+ }
}
if (hdlc_flag) {
@@ -3009,6 +3024,7 @@ static int __init diagchar_init(void)
mutex_init(&apps_data_mutex);
mutex_init(&driver->msg_mask_lock);
mutex_init(&driver->diagfwd_channel_mutex);
+ mutex_init(&driver->hdlc_recovery_mutex);
init_waitqueue_head(&driver->wait_q);
INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
INIT_WORK(&(driver->update_user_clients),
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 5cff1f7beaa..a25b93c2685 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1270,7 +1270,9 @@ static void diag_hdlc_start_recovery(unsigned char *buf, int len)
if (start_ptr) {
/* Discard any partial packet reads */
+ mutex_lock(&driver->hdlc_recovery_mutex);
driver->incoming_pkt.processing = 0;
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_process_non_hdlc_pkt(start_ptr, len - i);
}
}
@@ -1283,18 +1285,24 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len)
const uint32_t header_len = sizeof(struct diag_pkt_frame_t);
struct diag_pkt_frame_t *actual_pkt = NULL;
unsigned char *data_ptr = NULL;
- struct diag_partial_pkt_t *partial_pkt = &driver->incoming_pkt;
+ struct diag_partial_pkt_t *partial_pkt = NULL;
- if (!buf || len <= 0)
+ mutex_lock(&driver->hdlc_recovery_mutex);
+ if (!buf || len <= 0) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
return;
-
- if (!partial_pkt->processing)
+ }
+ partial_pkt = &driver->incoming_pkt;
+ if (!partial_pkt->processing) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto start;
+ }
if (partial_pkt->remaining > len) {
if ((partial_pkt->read_len + len) > partial_pkt->capacity) {
pr_err("diag: Invalid length %d, %d received in %s\n",
partial_pkt->read_len, len, __func__);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
}
memcpy(partial_pkt->data + partial_pkt->read_len, buf, len);
@@ -1308,6 +1316,7 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len)
pr_err("diag: Invalid length during partial read %d, %d received in %s\n",
partial_pkt->read_len,
partial_pkt->remaining, __func__);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
}
memcpy(partial_pkt->data + partial_pkt->read_len, buf,
@@ -1321,20 +1330,27 @@ void diag_process_non_hdlc_pkt(unsigned char *buf, int len)
if (partial_pkt->remaining == 0) {
actual_pkt = (struct diag_pkt_frame_t *)(partial_pkt->data);
data_ptr = partial_pkt->data + header_len;
- if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR)
+ if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
+ CONTROL_CHAR) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_hdlc_start_recovery(buf, len);
+ mutex_lock(&driver->hdlc_recovery_mutex);
+ }
err = diag_process_apps_pkt(data_ptr,
actual_pkt->length);
if (err) {
pr_err("diag: In %s, unable to process incoming data packet, err: %d\n",
__func__, err);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
}
partial_pkt->read_len = 0;
partial_pkt->total_len = 0;
partial_pkt->processing = 0;
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto start;
}
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
start:
@@ -1347,14 +1363,14 @@ start:
diag_send_error_rsp(buf, len);
goto end;
}
-
+ mutex_lock(&driver->hdlc_recovery_mutex);
if (pkt_len + header_len > partial_pkt->capacity) {
pr_err("diag: In %s, incoming data is too large for the request buffer %d\n",
__func__, pkt_len);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_hdlc_start_recovery(buf, len);
break;
}
-
if ((pkt_len + header_len) > (len - read_bytes)) {
partial_pkt->read_len = len - read_bytes;
partial_pkt->total_len = pkt_len + header_len;
@@ -1362,19 +1378,27 @@ start:
partial_pkt->read_len;
partial_pkt->processing = 1;
memcpy(partial_pkt->data, buf, partial_pkt->read_len);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
break;
}
data_ptr = buf + header_len;
- if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR)
+ if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
+ CONTROL_CHAR) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_hdlc_start_recovery(buf, len);
+ mutex_lock(&driver->hdlc_recovery_mutex);
+ }
else
hdlc_reset = 0;
err = diag_process_apps_pkt(data_ptr,
actual_pkt->length);
- if (err)
+ if (err) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
break;
+ }
read_bytes += header_len + pkt_len + 1;
buf += header_len + pkt_len + 1; /* advance to next pkt */
+ mutex_unlock(&driver->hdlc_recovery_mutex);
}
end:
return;
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
index 042b735cbd0..cdea19e163c 100644
--- a/drivers/coresight/coresight-tmc.c
+++ b/drivers/coresight/coresight-tmc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -850,6 +850,14 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
return ret;
mutex_lock(&drvdata->usb_lock);
+ spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (drvdata->reading) {
+ ret = -EBUSY;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ goto err0;
+ }
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
coresight_cti_map_trigout(drvdata->cti_flush, 1, 0);
coresight_cti_map_trigin(drvdata->cti_reset, 2, 0);
@@ -896,10 +904,6 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
}
spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- ret = -EBUSY;
- goto err1;
- }
if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
__tmc_etb_enable(drvdata);
@@ -929,11 +933,6 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
dev_info(drvdata->dev, "TMC enabled\n");
return 0;
-err1:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
- if (drvdata->out_mode == TMC_ETR_OUT_MODE_USB)
- usb_qdss_close(drvdata->usbch);
err0:
mutex_unlock(&drvdata->usb_lock);
clk_disable_unprepare(drvdata->clk);
@@ -1328,6 +1327,7 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
unsigned long flags;
enum tmc_mode mode;
+ mutex_lock(&drvdata->usb_lock);
spin_lock_irqsave(&drvdata->spinlock, flags);
if (!drvdata->sticky_enable) {
dev_err(drvdata->dev, "enable tmc once before reading\n");
@@ -1358,11 +1358,13 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata)
out:
drvdata->reading = true;
spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ mutex_unlock(&drvdata->usb_lock);
dev_info(drvdata->dev, "TMC read start\n");
return 0;
err:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ mutex_unlock(&drvdata->usb_lock);
return ret;
}
@@ -1544,8 +1546,12 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
{
struct tmc_drvdata *drvdata = container_of(file->private_data,
struct tmc_drvdata, miscdev);
- char *bufp = drvdata->buf + *ppos;
- char *end = (char *)(drvdata->vaddr + drvdata->size);
+ char *bufp, *end;
+
+ mutex_lock(&drvdata->usb_lock);
+
+ bufp = drvdata->buf + *ppos;
+ end = (char *)(drvdata->vaddr + drvdata->size);
if (*ppos + len > drvdata->size)
len = drvdata->size - *ppos;
@@ -1572,6 +1578,7 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
if (copy_to_user(data, bufp, len)) {
dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+ mutex_unlock(&drvdata->usb_lock);
return -EFAULT;
}
@@ -1579,6 +1586,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
out:
dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
__func__, len, (int) (drvdata->size - *ppos));
+
+ mutex_unlock(&drvdata->usb_lock);
return len;
}
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 59a654dff2e..574d246f915 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1768,6 +1768,13 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_unlock(&hash_access_lock);
return err;
}
+
+ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
+ pr_err("Invalid sha_ctxt.diglen %d\n",
+ handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
+ return -EINVAL;
+ }
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
@@ -1804,6 +1811,13 @@ long qcedev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_unlock(&hash_access_lock);
return err;
}
+
+ if (handle->sha_ctxt.diglen > QCEDEV_MAX_SHA_DIGEST) {
+ pr_err("Invalid sha_ctxt.diglen %d\n",
+ handle->sha_ctxt.diglen);
+ mutex_unlock(&hash_access_lock);
+ return -EINVAL;
+ }
qcedev_areq.sha_op_req.diglen = handle->sha_ctxt.diglen;
memcpy(&qcedev_areq.sha_op_req.digest[0],
&handle->sha_ctxt.digest[0],
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index e55ff922785..8fb21aabc8a 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2017. The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -579,16 +579,70 @@ static inline unsigned int _fixup_cache_range_op(unsigned int op)
}
#endif
-int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset,
- uint64_t size, unsigned int op)
+static int kgsl_do_cache_op(struct page *page, void *addr,
+ uint64_t offset, uint64_t size, unsigned int op)
{
+ void (*cache_op)(const void *, const void *);
+
/*
- * If the buffer is mapped in the kernel operate on that address
- * otherwise use the user address
+ * The dmac_xxx_range functions handle addresses and sizes that
+ * are not aligned to the cacheline size correctly.
*/
+ switch (_fixup_cache_range_op(op)) {
+ case KGSL_CACHE_OP_FLUSH:
+ cache_op = dmac_flush_range;
+ break;
+ case KGSL_CACHE_OP_CLEAN:
+ cache_op = dmac_clean_range;
+ break;
+ case KGSL_CACHE_OP_INV:
+ cache_op = dmac_inv_range;
+ break;
+ default:
+ return -EINVAL;
+ }
- void *addr = (memdesc->hostptr) ?
- memdesc->hostptr : (void *) memdesc->useraddr;
+ if (page != NULL) {
+ unsigned long pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+ /*
+ * page_address() returns the kernel virtual address of page.
+ * For high memory kernel virtual address exists only if page
+ * has been mapped. So use a version of kmap rather than
+ * page_address() for high memory.
+ */
+ if (PageHighMem(page)) {
+ offset &= ~PAGE_MASK;
+
+ do {
+ unsigned int len = size;
+
+ if (len + offset > PAGE_SIZE)
+ len = PAGE_SIZE - offset;
+
+ page = pfn_to_page(pfn++);
+ addr = kmap_atomic(page);
+ cache_op(addr + offset, addr + offset + len);
+ kunmap_atomic(addr);
+
+ size -= len;
+ offset = 0;
+ } while (size);
+
+ return 0;
+ }
+
+ addr = page_address(page);
+ }
+
+ cache_op(addr + offset, addr + offset + (size_t) size);
+ return 0;
+}
+
+int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset,
+ uint64_t size, unsigned int op)
+{
+ void *addr = NULL;
+ int ret = 0;
if (size == 0 || size > UINT_MAX)
return -EINVAL;
@@ -597,38 +651,47 @@ int kgsl_cache_range_op(struct kgsl_memdesc *memdesc, uint64_t offset,
if ((offset + size < offset) || (offset + size < size))
return -ERANGE;
- /* Make sure the offset + size do not overflow the address */
- if (addr + ((size_t) offset + (size_t) size) < addr)
- return -ERANGE;
-
/* Check that offset+length does not exceed memdesc->size */
if (offset + size > memdesc->size)
return -ERANGE;
- /* Return quietly if the buffer isn't mapped on the CPU */
- if (addr == NULL)
- return 0;
+ if (memdesc->hostptr) {
+ addr = memdesc->hostptr;
+ /* Make sure the offset + size do not overflow the address */
+ if (addr + ((size_t) offset + (size_t) size) < addr)
+ return -ERANGE;
- addr = addr + offset;
+ ret = kgsl_do_cache_op(NULL, addr, offset, size, op);
+ return ret;
+ }
/*
- * The dmac_xxx_range functions handle addresses and sizes that
- * are not aligned to the cacheline size correctly.
+ * If the buffer is not to mapped to kernel, perform cache
+ * operations after mapping to kernel.
*/
+ if (memdesc->sgt != NULL) {
+ struct scatterlist *sg;
+ unsigned int i, pos = 0;
- switch (_fixup_cache_range_op(op)) {
- case KGSL_CACHE_OP_FLUSH:
- dmac_flush_range(addr, addr + (size_t) size);
- break;
- case KGSL_CACHE_OP_CLEAN:
- dmac_clean_range(addr, addr + (size_t) size);
- break;
- case KGSL_CACHE_OP_INV:
- dmac_inv_range(addr, addr + (size_t) size);
- break;
- }
+ for_each_sg(memdesc->sgt->sgl, sg, memdesc->sgt->nents, i) {
+ uint64_t sg_offset, sg_left;
- return 0;
+ if (offset >= (pos + sg->length)) {
+ pos += sg->length;
+ continue;
+ }
+ sg_offset = offset > pos ? offset - pos : 0;
+ sg_left = (sg->length - sg_offset > size) ? size :
+ sg->length - sg_offset;
+ ret = kgsl_do_cache_op(sg_page(sg), NULL, sg_offset,
+ sg_left, op);
+ size -= sg_left;
+ if (size == 0)
+ break;
+ pos += sg->length;
+ }
+ }
+ return ret;
}
EXPORT_SYMBOL(kgsl_cache_range_op);
diff --git a/drivers/input/misc/keychord.c b/drivers/input/misc/keychord.c
index a5ea27ad0e1..fdcc14653b6 100644
--- a/drivers/input/misc/keychord.c
+++ b/drivers/input/misc/keychord.c
@@ -60,6 +60,10 @@ struct keychord_device {
unsigned char head;
unsigned char tail;
__u16 buff[BUFFER_SIZE];
+ /* Bit to serialize writes to this device */
+#define KEYCHORD_BUSY 0x01
+ unsigned long flags;
+ wait_queue_head_t write_waitq;
};
static int check_keychord(struct keychord_device *kdev,
@@ -172,7 +176,6 @@ static int keychord_connect(struct input_handler *handler,
goto err_input_open_device;
pr_info("keychord: using input dev %s for fevent\n", dev->name);
-
return 0;
err_input_open_device:
@@ -225,6 +228,41 @@ static ssize_t keychord_read(struct file *file, char __user *buffer,
}
/*
+ * serializes writes on a device. can use mutex_lock_interruptible()
+ * for this particular use case as well - a matter of preference.
+ */
+static int
+keychord_write_lock(struct keychord_device *kdev)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&kdev->lock, flags);
+ while (kdev->flags & KEYCHORD_BUSY) {
+ spin_unlock_irqrestore(&kdev->lock, flags);
+ ret = wait_event_interruptible(kdev->write_waitq,
+ ((kdev->flags & KEYCHORD_BUSY) == 0));
+ if (ret)
+ return ret;
+ spin_lock_irqsave(&kdev->lock, flags);
+ }
+ kdev->flags |= KEYCHORD_BUSY;
+ spin_unlock_irqrestore(&kdev->lock, flags);
+ return 0;
+}
+
+static void
+keychord_write_unlock(struct keychord_device *kdev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&kdev->lock, flags);
+ kdev->flags &= ~KEYCHORD_BUSY;
+ spin_unlock_irqrestore(&kdev->lock, flags);
+ wake_up_interruptible(&kdev->write_waitq);
+}
+
+/*
* keychord_write is used to configure the driver
*/
static ssize_t keychord_write(struct file *file, const char __user *buffer,
@@ -232,9 +270,11 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
{
struct keychord_device *kdev = file->private_data;
struct input_keychord *keychords = 0;
- struct input_keychord *keychord, *next, *end;
+ struct input_keychord *keychord;
int ret, i, key;
unsigned long flags;
+ size_t resid = count;
+ size_t key_bytes;
if (count < sizeof(struct input_keychord))
return -EINVAL;
@@ -248,6 +288,22 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
return -EFAULT;
}
+ /*
+ * Serialize writes to this device to prevent various races.
+ * 1) writers racing here could do duplicate input_unregister_handler()
+ * calls, resulting in attempting to unlink a node from a list that
+ * does not exist.
+ * 2) writers racing here could do duplicate input_register_handler() calls
+ * below, resulting in a duplicate insertion of a node into the list.
+ * 3) a double kfree of keychords can occur (in the event that
+ * input_register_handler() fails below.
+ */
+ ret = keychord_write_lock(kdev);
+ if (ret) {
+ kfree(keychords);
+ return ret;
+ }
+
/* unregister handler before changing configuration */
if (kdev->registered) {
input_unregister_handler(&kdev->input_handler);
@@ -265,15 +321,29 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
kdev->head = kdev->tail = 0;
keychord = keychords;
- end = (struct input_keychord *)((char *)keychord + count);
- while (keychord < end) {
- next = NEXT_KEYCHORD(keychord);
- if (keychord->count <= 0 || next > end) {
+ while (resid > 0) {
+ /* Is the entire keychord entry header present ? */
+ if (resid < sizeof(struct input_keychord)) {
+ pr_err("keychord: Insufficient bytes present for header %zu\n",
+ resid);
+ goto err_unlock_return;
+ }
+ resid -= sizeof(struct input_keychord);
+ if (keychord->count <= 0) {
pr_err("keychord: invalid keycode count %d\n",
keychord->count);
goto err_unlock_return;
}
+ key_bytes = keychord->count * sizeof(keychord->keycodes[0]);
+ /* Do we have all the expected keycodes ? */
+ if (resid < key_bytes) {
+ pr_err("keychord: Insufficient bytes present for keycount %zu\n",
+ resid);
+ goto err_unlock_return;
+ }
+ resid -= key_bytes;
+
if (keychord->version != KEYCHORD_VERSION) {
pr_err("keychord: unsupported version %d\n",
keychord->version);
@@ -292,7 +362,7 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
}
kdev->keychord_count++;
- keychord = next;
+ keychord = NEXT_KEYCHORD(keychord);
}
kdev->keychords = keychords;
@@ -302,15 +372,19 @@ static ssize_t keychord_write(struct file *file, const char __user *buffer,
if (ret) {
kfree(keychords);
kdev->keychords = 0;
+ keychord_write_unlock(kdev);
return ret;
}
kdev->registered = 1;
+ keychord_write_unlock(kdev);
+
return count;
err_unlock_return:
spin_unlock_irqrestore(&kdev->lock, flags);
kfree(keychords);
+ keychord_write_unlock(kdev);
return -EINVAL;
}
@@ -336,6 +410,7 @@ static int keychord_open(struct inode *inode, struct file *file)
spin_lock_init(&kdev->lock);
init_waitqueue_head(&kdev->waitq);
+ init_waitqueue_head(&kdev->write_waitq);
kdev->input_handler.event = keychord_event;
kdev->input_handler.connect = keychord_connect;
@@ -357,6 +432,7 @@ static int keychord_release(struct inode *inode, struct file *file)
if (kdev->registered)
input_unregister_handler(&kdev->input_handler);
+ kfree(kdev->keychords);
kfree(kdev);
return 0;
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
index 0728ad77229..e004455abcc 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
@@ -1464,7 +1464,7 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
return retval;
}
-static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
+static int synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
struct synaptics_rmi4_fn_desc *fd,
unsigned int intr_count)
{
@@ -1472,6 +1472,12 @@ static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
unsigned char intr_offset;
fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) {
+ fhandler->intr_reg_num = 0;
+ fhandler->num_of_data_sources = 0;
+ fhandler->intr_mask = 0;
+ return -EINVAL;
+ }
if (fhandler->intr_reg_num != 0)
fhandler->intr_reg_num -= 1;
@@ -1484,7 +1490,7 @@ static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
ii++)
fhandler->intr_mask |= 1 << ii;
- return;
+ return 0;
}
static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data,
@@ -1492,12 +1498,17 @@ static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn_desc *fd,
unsigned int intr_count)
{
+ int retval;
+
fhandler->fn_number = fd->fn_number;
fhandler->num_of_data_sources = fd->intr_src_count;
fhandler->data = NULL;
fhandler->extra = NULL;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
+
rmi4_data->f01_query_base_addr = fd->query_base_addr;
rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr;
@@ -1622,7 +1633,9 @@ static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
if (retval < 0)
return retval;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
abs_data_size = query[5] & MASK_2BIT;
abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0));
@@ -1903,7 +1916,9 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
if (retval < 0)
goto free_function_handler_mem;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
/* Allocate memory for finger data storage space */
fhandler->data_size = num_of_fingers * size_of_2d_data;
@@ -2061,7 +2076,9 @@ static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
fhandler->fn_number = fd->fn_number;
fhandler->num_of_data_sources = fd->intr_src_count;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler);
if (retval < 0)
@@ -2460,6 +2477,8 @@ flash_prog_mode:
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Number of interrupt registers = %d\n",
__func__, rmi4_data->num_of_intr_regs);
+ if (rmi4_data->num_of_intr_regs >= MAX_INTR_REGISTERS)
+ return -EINVAL;
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_query_base_addr,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 410fee6fca3..ef6f098ad84 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -2091,6 +2091,12 @@ static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
rmi4_data->max_touch_width = MAX_F11_TOUCH_WIDTH;
fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) {
+ fhandler->intr_reg_num = 0;
+ fhandler->num_of_data_sources = 0;
+ fhandler->intr_mask = 0;
+ return -EINVAL;
+ }
if (fhandler->intr_reg_num != 0)
fhandler->intr_reg_num -= 1;
@@ -2365,6 +2371,13 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
rmi4_data->num_of_tx);
fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) {
+ fhandler->intr_reg_num = 0;
+ fhandler->num_of_data_sources = 0;
+ fhandler->intr_mask = 0;
+ retval = -EINVAL;
+ goto free_function_handler_mem;
+ }
if (fhandler->intr_reg_num != 0)
fhandler->intr_reg_num -= 1;
@@ -2508,6 +2521,13 @@ static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
fhandler->num_of_data_sources = fd->intr_src_count;
fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) {
+ fhandler->intr_reg_num = 0;
+ fhandler->num_of_data_sources = 0;
+ fhandler->intr_mask = 0;
+ retval = -EINVAL;
+ goto error_exit;
+ }
if (fhandler->intr_reg_num != 0)
fhandler->intr_reg_num -= 1;
@@ -2856,7 +2876,8 @@ flash_prog_mode:
dev_dbg(&rmi4_data->i2c_client->dev,
"%s: Number of interrupt registers = %d\n",
__func__, rmi4_data->num_of_intr_regs);
-
+ if (rmi4_data->num_of_intr_regs >= MAX_INTR_REGISTERS)
+ return -EINVAL;
memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask));
/*
@@ -3744,6 +3765,7 @@ err_enable_irq:
input_unregister_device(rmi4_data->input_dev);
err_register_input:
+err_free_gpios:
mutex_lock(&rmi->support_fn_list_mutex);
if (!list_empty(&rmi->support_fn_list)) {
list_for_each_entry_safe(fhandler, next_fhandler,
@@ -3751,14 +3773,15 @@ err_register_input:
if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
synaptics_rmi4_f1a_kfree(fhandler);
else {
- kfree(fhandler->data);
- kfree(fhandler->extra);
+ if (fhandler->data != NULL)
+ kfree(fhandler->data);
+ if (fhandler->extra != NULL)
+ kfree(fhandler->extra);
}
kfree(fhandler);
}
}
mutex_unlock(&rmi->support_fn_list_mutex);
-err_free_gpios:
if (gpio_is_valid(rmi4_data->board->reset_gpio))
gpio_free(rmi4_data->board->reset_gpio);
if (gpio_is_valid(rmi4_data->board->irq_gpio))
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 877525bddcc..1c3c604120e 100644..100755
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -1655,7 +1655,6 @@ static long msm_actuator_subdev_do_ioctl(
switch (cmd) {
case VIDIOC_MSM_ACTUATOR_CFG32:
- cmd = VIDIOC_MSM_ACTUATOR_CFG;
switch (u32->cfgtype) {
case CFG_SET_ACTUATOR_INFO:
actuator_data.cfgtype = u32->cfgtype;
@@ -1794,11 +1793,14 @@ static long msm_actuator_subdev_do_ioctl(
}
}
- rc = msm_actuator_subdev_ioctl(sd, cmd, parg);
+ if (cmd == VIDIOC_MSM_ACTUATOR_CFG32)
+ rc = msm_actuator_subdev_ioctl(sd, VIDIOC_MSM_ACTUATOR_CFG, parg);
+ else
+ rc = msm_actuator_subdev_ioctl(sd, cmd, parg);
switch (cmd) {
- case VIDIOC_MSM_ACTUATOR_CFG:
+ case VIDIOC_MSM_ACTUATOR_CFG32:
switch (u32->cfgtype) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index 3b8dbeded44..e2754a4952e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2015, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -523,22 +523,44 @@ static int32_t msm_flash_init(
return 0;
}
-#ifdef CONFIG_COMPAT
static int32_t msm_flash_init_prepare(
struct msm_flash_ctrl_t *flash_ctrl,
struct msm_flash_cfg_data_t *flash_data)
{
+#ifdef CONFIG_COMPAT
+ struct msm_flash_cfg_data_t flash_data_k;
+ struct msm_flash_init_info_t flash_init_info;
+ int32_t i = 0;
+ if(!is_compat_task()) {
+ /*for 64-bit usecase,it need copy the data to local memory*/
+ flash_data_k.cfg_type = flash_data->cfg_type;
+ for (i = 0; i < MAX_LED_TRIGGERS; i++) {
+ flash_data_k.flash_current[i] =
+ flash_data->flash_current[i];
+ flash_data_k.flash_duration[i] =
+ flash_data->flash_duration[i];
+ }
+
+ flash_data_k.cfg.flash_init_info = &flash_init_info;
+ if (copy_from_user(&flash_init_info,
+ (void *)(flash_data->cfg.flash_init_info),
+ sizeof(struct msm_flash_init_info_t))) {
+ pr_err("%s copy_from_user failed %d\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
+ return msm_flash_init(flash_ctrl, &flash_data_k);
+ }
+ /*
+ * for 32-bit usecase,it already copy the userspace
+ * data to local memory in msm_flash_subdev_do_ioctl()
+ * so here do not need copy from user
+ */
return msm_flash_init(flash_ctrl, flash_data);
-}
#else
-static int32_t msm_flash_init_prepare(
- struct msm_flash_ctrl_t *flash_ctrl,
- struct msm_flash_cfg_data_t *flash_data)
-{
struct msm_flash_cfg_data_t flash_data_k;
struct msm_flash_init_info_t flash_init_info;
int32_t i = 0;
-
flash_data_k.cfg_type = flash_data->cfg_type;
for (i = 0; i < MAX_LED_TRIGGERS; i++) {
flash_data_k.flash_current[i] =
@@ -556,8 +578,8 @@ static int32_t msm_flash_init_prepare(
return -EFAULT;
}
return msm_flash_init(flash_ctrl, &flash_data_k);
-}
#endif
+}
static int32_t msm_flash_low(
struct msm_flash_ctrl_t *flash_ctrl,
diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c
index d4ef4977e11..3c031f9b0cd 100644
--- a/drivers/misc/uid_sys_stats.c
+++ b/drivers/misc/uid_sys_stats.c
@@ -244,13 +244,29 @@ static void compute_uid_io_bucket_stats(struct io_stats *io_bucket,
struct io_stats *io_last,
struct io_stats *io_dead)
{
- io_bucket->read_bytes += io_curr->read_bytes + io_dead->read_bytes -
+ s64 delta;
+
+ delta = io_curr->read_bytes + io_dead->read_bytes -
io_last->read_bytes;
- io_bucket->write_bytes += io_curr->write_bytes + io_dead->write_bytes -
+ if (delta > 0)
+ io_bucket->read_bytes += delta;
+
+ delta = io_curr->write_bytes + io_dead->write_bytes -
io_last->write_bytes;
- io_bucket->rchar += io_curr->rchar + io_dead->rchar - io_last->rchar;
- io_bucket->wchar += io_curr->wchar + io_dead->wchar - io_last->wchar;
- io_bucket->fsync += io_curr->fsync + io_dead->fsync - io_last->fsync;
+ if (delta > 0)
+ io_bucket->write_bytes += delta;
+
+ delta = io_curr->rchar + io_dead->rchar - io_last->rchar;
+ if (delta > 0)
+ io_bucket->rchar += delta;
+
+ delta = io_curr->wchar + io_dead->wchar - io_last->wchar;
+ if (delta > 0)
+ io_bucket->wchar += delta;
+
+ delta = io_curr->fsync + io_dead->fsync - io_last->fsync;
+ if (delta > 0)
+ io_bucket->fsync += delta;
io_last->read_bytes = io_curr->read_bytes;
io_last->write_bytes = io_curr->write_bytes;
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 4d04cb8846a..76fb2dfba00 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -29,8 +29,8 @@
#define DCMD_SLOT 31
#define NUM_SLOTS 32
-/* 1 sec */
-#define HALT_TIMEOUT_MS 1000
+/* 10 sec */
+#define HALT_TIMEOUT_MS 10000
static int cmdq_halt_poll(struct mmc_host *mmc);
static int cmdq_halt(struct mmc_host *mmc, bool halt);
@@ -844,6 +844,9 @@ skip_cqterri:
if (status & CQIS_HAC) {
if (cq_host->ops->post_cqe_halt)
cq_host->ops->post_cqe_halt(mmc);
+ /* halt done: re-enable legacy interrupts */
+ if (cq_host->ops->clear_set_irqs)
+ cq_host->ops->clear_set_irqs(mmc, false);
/* halt is completed, wakeup waiting thread */
complete(&cq_host->halt_comp);
}
@@ -890,6 +893,7 @@ static int cmdq_halt(struct mmc_host *mmc, bool halt)
{
struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
u32 val;
+ u32 config = 0;
int retries = 3;
unsigned long flags;
@@ -899,14 +903,29 @@ static int cmdq_halt(struct mmc_host *mmc, bool halt)
CQCTL);
val = wait_for_completion_timeout(&cq_host->halt_comp,
msecs_to_jiffies(HALT_TIMEOUT_MS));
- if (!val && !(cmdq_readl(cq_host, CQCTL) & HALT)) {
- retries--;
- continue;
+ if (!val) {
+ pr_warn("%s: %s: HAC int timeout\n",
+ mmc_hostname(mmc), __func__);
+ if ((cmdq_readl(cq_host, CQCTL) & HALT)) {
+ /*
+ * Don't retry if CQE is halted but irq
+ * is not triggered in timeout period.
+ * And since we are returning error,
+ * un-halt CQE. Since irq was not fired
+ * yet, no need to set other params
+ */
+ retries = 0;
+ config = cmdq_readl(cq_host, CQCTL);
+ config &= ~HALT;
+ cmdq_writel(cq_host, config, CQCTL);
+ } else {
+ pr_warn("%s: %s: retryng halt (%d)\n",
+ mmc_hostname(mmc), __func__,
+ retries);
+ retries--;
+ continue;
+ }
} else {
- /* halt done: re-enable legacy interrupts */
- if (cq_host->ops->clear_set_irqs)
- cq_host->ops->clear_set_irqs(mmc,
- false);
break;
}
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 031b54682e2..fef9ab790d1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -4019,6 +4019,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
GFP_KERNEL);
} else if (ieee80211_is_action(mgmt->frame_control)) {
+ if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) {
+ brcmf_err("invalid action frame length\n");
+ err = -EINVAL;
+ goto exit;
+ }
af_params = kzalloc(sizeof(*af_params), GFP_KERNEL);
if (af_params == NULL) {
brcmf_err("unable to allocate frame\n");
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c
index cfc6322cbc9..bb43dec6bd1 100644
--- a/drivers/net/wireless/cnss/cnss_pci.c
+++ b/drivers/net/wireless/cnss/cnss_pci.c
@@ -149,6 +149,7 @@ static DEFINE_SPINLOCK(pci_link_down_lock);
#define FW_IMAGE_MISSION (0x02)
#define FW_IMAGE_BDATA (0x03)
#define FW_IMAGE_PRINT (0x04)
+#define FW_SETUP_DELAY 2000
#define SEG_METADATA (0x01)
#define SEG_NON_PAGED (0x02)
@@ -240,7 +241,7 @@ static struct cnss_data {
u16 revision_id;
u16 dfs_nol_info_len;
bool recovery_in_progress;
- bool fw_available;
+ atomic_t fw_available;
struct codeswap_codeseg_info *cnss_seg_info;
/* Virtual Address of the DMA page */
void *codeseg_cpuaddr[CODESWAP_MAX_CODESEGS];
@@ -269,6 +270,10 @@ static struct cnss_data {
u32 fw_dma_size;
u32 fw_seg_count;
struct segment_memory fw_seg_mem[MAX_NUM_OF_SEGMENTS];
+ atomic_t fw_store_in_progress;
+ /* Firmware setup complete lock */
+ struct mutex fw_setup_stat_lock;
+ struct completion fw_setup_complete;
void *bdata_cpu;
dma_addr_t bdata_dma;
u32 bdata_dma_size;
@@ -1182,10 +1187,21 @@ int cnss_get_fw_image(struct image_desc_info *image_desc_info)
!penv->fw_seg_count || !penv->bdata_seg_count)
return -EINVAL;
+ /* Check for firmware setup trigger by usersapce is in progress
+ * and wait for complition of firmware setup.
+ */
+
+ if (atomic_read(&penv->fw_store_in_progress)) {
+ wait_for_completion_timeout(&penv->fw_setup_complete,
+ msecs_to_jiffies(FW_SETUP_DELAY));
+ }
+
+ mutex_lock(&penv->fw_setup_stat_lock);
image_desc_info->fw_addr = penv->fw_dma;
image_desc_info->fw_size = penv->fw_dma_size;
image_desc_info->bdata_addr = penv->bdata_dma;
image_desc_info->bdata_size = penv->bdata_dma_size;
+ mutex_unlock(&penv->fw_setup_stat_lock);
return 0;
}
@@ -1227,7 +1243,7 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev,
penv->pdev = pdev;
penv->id = id;
- penv->fw_available = false;
+ atomic_set(&penv->fw_available, 0);
penv->device_id = pdev->device;
if (penv->pci_register_again) {
@@ -1530,8 +1546,19 @@ static ssize_t fw_image_setup_store(struct device *dev,
if (!penv)
return -ENODEV;
- if (sscanf(buf, "%d", &val) != 1)
+ if (atomic_read(&penv->fw_store_in_progress)) {
+ pr_info("%s: Firmware setup in progress\n", __func__);
+ return 0;
+ }
+
+ atomic_set(&penv->fw_store_in_progress, 1);
+ init_completion(&penv->fw_setup_complete);
+
+ if (kstrtoint(buf, 0, &val)) {
+ atomic_set(&penv->fw_store_in_progress, 0);
+ complete(&penv->fw_setup_complete);
return -EINVAL;
+ }
if (val == FW_IMAGE_FTM || val == FW_IMAGE_MISSION
|| val == FW_IMAGE_BDATA) {
@@ -1540,6 +1567,8 @@ static ssize_t fw_image_setup_store(struct device *dev,
if (ret != 0) {
pr_err("%s: Invalid parsing of FW image files %d",
__func__, ret);
+ atomic_set(&penv->fw_store_in_progress, 0);
+ complete(&penv->fw_setup_complete);
return -EINVAL;
}
penv->fw_image_setup = val;
@@ -1549,6 +1578,9 @@ static ssize_t fw_image_setup_store(struct device *dev,
penv->bmi_test = val;
}
+ atomic_set(&penv->fw_store_in_progress, 0);
+ complete(&penv->fw_setup_complete);
+
return count;
}
@@ -1637,7 +1669,8 @@ int cnss_get_codeswap_struct(struct codeswap_codeseg_info *swap_seg)
swap_seg = NULL;
return -ENOENT;
}
- if (!penv->fw_available) {
+
+ if (!atomic_read(&penv->fw_available)) {
pr_debug("%s: fw is not available\n", __func__);
return -ENOENT;
}
@@ -1661,26 +1694,40 @@ static void cnss_wlan_memory_expansion(void)
u_int32_t total_length = 0;
struct pci_dev *pdev;
+ /* Check for firmware setup trigger by usersapce is in progress
+ * and wait for complition of firmware setup.
+ */
+
+ if (atomic_read(&penv->fw_store_in_progress)) {
+ wait_for_completion_timeout(&penv->fw_setup_complete,
+ msecs_to_jiffies(FW_SETUP_DELAY));
+ }
+
+ mutex_lock(&penv->fw_setup_stat_lock);
pdev = penv->pdev;
dev = &pdev->dev;
cnss_seg_info = penv->cnss_seg_info;
if (!cnss_seg_info) {
pr_debug("cnss: cnss_seg_info is NULL\n");
+ mutex_unlock(&penv->fw_setup_stat_lock);
goto end;
}
- if (penv->fw_available) {
+ if (atomic_read(&penv->fw_available)) {
pr_debug("cnss: fw code already copied to host memory\n");
+ mutex_unlock(&penv->fw_setup_stat_lock);
goto end;
}
if (request_firmware(&fw_entry, filename, dev) != 0) {
- pr_debug("cnss: failed to get fw: %s\n", filename);
+ mutex_unlock(&penv->fw_setup_stat_lock);
+ pr_err("cnss:failed to get fw: %s\n", filename);
goto end;
}
if (!fw_entry || !fw_entry->data) {
+ mutex_unlock(&penv->fw_setup_stat_lock);
pr_err("%s: INVALID FW entries\n", __func__);
goto release_fw;
}
@@ -1716,7 +1763,8 @@ static void cnss_wlan_memory_expansion(void)
}
pr_debug("cnss: total_bytes copied: %d\n", total_length);
cnss_seg_info->codeseg_total_bytes = total_length;
- penv->fw_available = 1;
+ atomic_set(&penv->fw_available, 1);
+ mutex_unlock(&penv->fw_setup_stat_lock);
release_fw:
release_firmware(fw_entry);
@@ -2554,6 +2602,8 @@ skip_ramdump:
memset(phys_to_virt(0), 0, SZ_4K);
#endif
+ atomic_set(&penv->fw_store_in_progress, 0);
+ mutex_init(&penv->fw_setup_stat_lock);
ret = device_create_file(dev, &dev_attr_fw_image_setup);
if (ret) {
pr_err("cnss: fw_image_setup sys file creation failed\n");
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 4bd69945066..d6ef4f24b74 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -400,7 +400,7 @@ static struct {
int user_cal_read;
int user_cal_available;
u32 user_cal_rcvd;
- int user_cal_exp_size;
+ u32 user_cal_exp_size;
int iris_xo_mode_set;
int fw_vbatt_state;
char wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE];
diff --git a/drivers/platform/msm/ipa/ipa_rt.c b/drivers/platform/msm/ipa/ipa_rt.c
index 0476f519b24..87a88dc6aaa 100644
--- a/drivers/platform/msm/ipa/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_rt.c
@@ -828,12 +828,16 @@ int ipa_query_rt_index(struct ipa_ioc_get_rt_tbl_indx *in)
return -EINVAL;
}
+ mutex_lock(&ipa_ctx->lock);
/* check if this table exists */
entry = __ipa_find_rt_tbl(in->ip, in->name);
- if (!entry)
+ if (!entry){
+ mutex_unlock(&ipa_ctx->lock);
return -EFAULT;
+ }
in->idx = entry->idx;
+ mutex_unlock(&ipa_ctx->lock);
return 0;
}
diff --git a/drivers/platform/msm/ipa/rmnet_ipa.c b/drivers/platform/msm/ipa/rmnet_ipa.c
index dc6ce0eed81..7d3b5554f6e 100644
--- a/drivers/platform/msm/ipa/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/rmnet_ipa.c
@@ -2395,6 +2395,9 @@ int rmnet_ipa_set_data_quota(struct wan_ioctl_set_data_quota *data)
int index;
struct ipa_set_data_usage_quota_req_msg_v01 req;
+ /* prevent string buffer overflows */
+ data->interface_name[IFNAMSIZ-1] = '\0';
+
index = find_vchannel_name_index(data->interface_name);
IPAWANERR("iface name %s, quota %lu\n",
data->interface_name,
diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c
index 70da821709f..b0549097396 100644
--- a/drivers/soc/qcom/msm_glink_pkt.c
+++ b/drivers/soc/qcom/msm_glink_pkt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -117,7 +117,7 @@ struct glink_pkt_dev {
wait_queue_head_t ch_read_wait_queue;
wait_queue_head_t ch_opened_wait_queue;
struct list_head pkt_list;
- struct mutex pkt_list_lock;
+ spinlock_t pkt_list_lock;
struct wakeup_source pa_ws; /* Packet Arrival Wakeup Source */
struct work_struct packet_arrival_work;
@@ -177,7 +177,7 @@ module_param_named(debug_mask, msm_glink_pkt_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
static void glink_pkt_queue_rx_intent_worker(struct work_struct *work);
-
+static bool glink_pkt_read_avail(struct glink_pkt_dev *devp);
#define DEBUG
@@ -308,7 +308,7 @@ void glink_pkt_notify_rx(void *handle, const void *priv,
GLINK_PKT_INFO("%s(): priv[%p] data[%p] size[%zu]\n",
__func__, pkt_priv, (char *)ptr, size);
- pkt = kzalloc(sizeof(struct glink_rx_pkt), GFP_KERNEL);
+ pkt = kzalloc(sizeof(*pkt), GFP_ATOMIC);
if (!pkt) {
GLINK_PKT_ERR("%s: memory allocation failed\n", __func__);
return;
@@ -317,9 +317,9 @@ void glink_pkt_notify_rx(void *handle, const void *priv,
pkt->data = ptr;
pkt->pkt_priv = pkt_priv;
pkt->size = size;
- mutex_lock(&devp->pkt_list_lock);
+ spin_lock_irqsave(&devp->pkt_list_lock, flags);
list_add_tail(&pkt->list, &devp->pkt_list);
- mutex_unlock(&devp->pkt_list_lock);
+ spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
spin_lock_irqsave(&devp->pa_spinlock, flags);
__pm_stay_awake(&devp->pa_ws);
@@ -457,6 +457,24 @@ static void glink_pkt_queue_rx_intent_worker(struct work_struct *work)
}
/**
+ * glink_pkt_read_avail() - check any pending packets to read
+ * devp: pointer to G-Link packet device.
+ *
+ * This function is used to check any pending data packets are
+ * available to read or not.
+ */
+static bool glink_pkt_read_avail(struct glink_pkt_dev *devp)
+{
+ bool list_is_empty;
+ unsigned long flags;
+
+ spin_lock_irqsave(&devp->pkt_list_lock, flags);
+ list_is_empty = list_empty(&devp->pkt_list);
+ spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
+ return !list_is_empty;
+}
+
+/**
* glink_pkt_read() - read() syscall for the glink_pkt device
* file: Pointer to the file structure.
* buf: Pointer to the userspace buffer.
@@ -507,9 +525,8 @@ ssize_t glink_pkt_read(struct file *file,
__func__, devp->i, count);
ret = wait_event_interruptible(devp->ch_read_wait_queue,
- !devp->handle ||
- !list_empty(&devp->pkt_list) ||
- devp->in_reset);
+ !devp->handle || devp->in_reset ||
+ glink_pkt_read_avail(devp));
if (devp->in_reset) {
GLINK_PKT_ERR("%s: notifying reset for glink_pkt_dev id:%d\n",
__func__, devp->i);
@@ -530,15 +547,16 @@ ssize_t glink_pkt_read(struct file *file,
return ret;
}
+ spin_lock_irqsave(&devp->pkt_list_lock, flags);
pkt = list_first_entry(&devp->pkt_list, struct glink_rx_pkt, list);
-
if (pkt->size > count) {
GLINK_PKT_ERR("%s: Small Buff on dev Id:%d-[%zu > %zu]\n",
__func__, devp->i, pkt->size, count);
+ spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
return -ETOOSMALL;
}
-
list_del(&pkt->list);
+ spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
ret = copy_to_user(buf, pkt->data, pkt->size);
BUG_ON(ret != 0);
@@ -549,7 +567,7 @@ ssize_t glink_pkt_read(struct file *file,
mutex_lock(&devp->ch_lock);
spin_lock_irqsave(&devp->pa_spinlock, flags);
- if (devp->poll_mode && list_empty(&devp->pkt_list)) {
+ if (devp->poll_mode && !glink_pkt_read_avail(devp)) {
__pm_relax(&devp->pa_ws);
devp->ws_locked = 0;
devp->poll_mode = 0;
@@ -661,7 +679,7 @@ static unsigned int glink_pkt_poll(struct file *file, poll_table *wait)
return POLLHUP;
}
- if (!list_empty(&devp->pkt_list)) {
+ if (glink_pkt_read_avail(devp)) {
mask |= POLLIN | POLLRDNORM;
GLINK_PKT_INFO("%s sets POLLIN for glink_pkt_dev id: %d\n",
__func__, devp->i);
@@ -933,7 +951,7 @@ static int glink_pkt_init_add_device(struct glink_pkt_dev *devp, int i)
init_waitqueue_head(&devp->ch_opened_wait_queue);
spin_lock_init(&devp->pa_spinlock);
INIT_LIST_HEAD(&devp->pkt_list);
- mutex_init(&devp->pkt_list_lock);
+ spin_lock_init(&devp->pkt_list_lock);
wakeup_source_init(&devp->pa_ws, devp->dev_name);
INIT_WORK(&devp->packet_arrival_work, packet_arrival_worker);
diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h
index dd20161009f..91d3e4b507e 100644
--- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h
+++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h
@@ -241,6 +241,8 @@ typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN];
#endif
#define SCAN_REJECT_THRESHOLD_TIME 300000 /* Time is in msec, equal to 5 mins */
+#define SCAN_REJECT_THRESHOLD 15
+
#define WLAN_WAIT_TIME_EXTSCAN 1000
@@ -1686,6 +1688,7 @@ struct hdd_context_s
v_U8_t last_scan_reject_session_id;
scan_reject_states last_scan_reject_reason;
v_TIME_t last_scan_reject_timestamp;
+ v_U8_t scan_reject_cnt;
uint32_t track_arp_ip;
};
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c
index ec677c11a18..4eda9428042 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -2189,8 +2189,9 @@ wlan_hdd_extscan_config_policy
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX] =
{ .type = NLA_U32 },
- [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] =
- { .type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_BSSID] = {
+ .type = NLA_UNSPEC,
+ .len = HDD_MAC_ADDR_LEN},
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_LOW] =
{ .type = NLA_S32 },
[QCA_WLAN_VENDOR_ATTR_EXTSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH] =
@@ -3811,8 +3812,9 @@ static int hdd_extscan_start_fill_bucket_channel_spec(
nla_for_each_nested(buckets,
tb[QCA_WLAN_VENDOR_ATTR_EXTSCAN_BUCKET_SPEC], rem1) {
if (nla_parse(bucket,
- QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
- nla_data(buckets), nla_len(buckets), NULL)) {
+ QCA_WLAN_VENDOR_ATTR_EXTSCAN_SUBCMD_CONFIG_PARAM_MAX,
+ nla_data(buckets), nla_len(buckets),
+ wlan_hdd_extscan_config_policy)) {
hddLog(LOGE, FL("nla_parse failed"));
return -EINVAL;
}
@@ -4449,7 +4451,9 @@ static int wlan_hdd_cfg80211_extscan_reset_bssid_hotlist(struct wiphy *wiphy,
static const struct nla_policy
wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] =
{
- [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {.type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAC_ADDR] = {
+ .type = NLA_UNSPEC,
+ .len = HDD_MAC_ADDR_LEN},
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_CHANNEL] = {.type = NLA_S32 },
[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_GLOBAL_OPERATING_CLASS] =
{.type = NLA_S32 },
@@ -4461,7 +4465,9 @@ wlan_hdd_tdls_config_enable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_ENABLE_MAX +1] =
static const struct nla_policy
wlan_hdd_tdls_config_disable_policy[QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAX +1] =
{
- [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {.type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_TDLS_DISABLE_MAC_ADDR] = {
+ .type = NLA_UNSPEC,
+ .len = HDD_MAC_ADDR_LEN},
};
@@ -4469,7 +4475,9 @@ static const struct nla_policy
wlan_hdd_tdls_config_state_change_policy[
QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAX +1] =
{
- [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {.type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_TDLS_STATE_MAC_ADDR] = {
+ .type = NLA_UNSPEC,
+ .len = HDD_MAC_ADDR_LEN},
[QCA_WLAN_VENDOR_ATTR_TDLS_NEW_STATE] = {.type = NLA_S32 },
[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_REASON] = {.type = NLA_S32 },
[QCA_WLAN_VENDOR_ATTR_TDLS_STATE_CHANNEL] = {.type = NLA_S32 },
@@ -4482,7 +4490,9 @@ static const struct nla_policy
wlan_hdd_tdls_config_get_status_policy[
QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAX +1] =
{
- [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {.type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_MAC_ADDR] = {
+ .type = NLA_UNSPEC,
+ .len = HDD_MAC_ADDR_LEN},
[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_STATE] = {.type = NLA_S32 },
[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_REASON] = {.type = NLA_S32 },
[QCA_WLAN_VENDOR_ATTR_TDLS_GET_STATUS_CHANNEL] = {.type = NLA_S32 },
@@ -4494,7 +4504,9 @@ wlan_hdd_tdls_config_get_status_policy[
static const struct nla_policy
wlan_hdd_mac_config[QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI_MAX+1] =
{
- [QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI] = {.type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI] = {
+ .type = NLA_UNSPEC,
+ .len = VOS_MAC_ADDR_FIRST_3_BYTES},
};
static int __wlan_hdd_cfg80211_set_spoofed_mac_oui(struct wiphy *wiphy,
@@ -5544,7 +5556,9 @@ const struct
nla_policy qca_wlan_vendor_attr[QCA_WLAN_VENDOR_ATTR_MAX+1] =
{
[QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY] = { .type = NLA_U32 },
- [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
+ .type = NLA_UNSPEC,
+ .len = HDD_MAC_ADDR_LEN},
};
static int __wlan_hdd_cfg80211_firmware_roaming(struct wiphy *wiphy,
@@ -6534,7 +6548,9 @@ static int wlan_hdd_cfg80211_offloaded_packets(struct wiphy *wiphy,
static const struct
nla_policy
qca_wlan_vendor_attr_policy[QCA_WLAN_VENDOR_ATTR_MAX+1] = {
- [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = { .type = NLA_UNSPEC },
+ [QCA_WLAN_VENDOR_ATTR_MAC_ADDR] = {
+ .type = NLA_BINARY,
+ .len = HDD_MAC_ADDR_LEN},
};
/**
@@ -6588,6 +6604,13 @@ static int wlan_hdd_cfg80211_get_link_properties(struct wiphy *wiphy,
return -EINVAL;
}
+ if (nla_len(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]) < sizeof(peer_mac)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Attribute peerMac is invalid=%d"),
+ adapter->device_mode);
+ return -EINVAL;
+ }
+
memcpy(peer_mac, nla_data(tb[QCA_WLAN_VENDOR_ATTR_MAC_ADDR]),
sizeof(peer_mac));
hddLog(VOS_TRACE_LEVEL_INFO,
@@ -13102,13 +13125,24 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
pHddCtx->last_scan_reject_session_id = curr_session_id;
pHddCtx->last_scan_reject_reason = curr_reason;
pHddCtx->last_scan_reject_timestamp = jiffies_to_msecs(jiffies);
+ pHddCtx->scan_reject_cnt = 0;
}
- else {
- if ((jiffies_to_msecs(jiffies) -
- pHddCtx->last_scan_reject_timestamp) >=
- SCAN_REJECT_THRESHOLD_TIME)
+ else
+ {
+ pHddCtx->scan_reject_cnt++;
+
+ hddLog(LOGE, FL("Reject cnt %d time delta %lu ms"), pHddCtx->scan_reject_cnt,
+ (jiffies_to_msecs(jiffies) -
+ pHddCtx->last_scan_reject_timestamp));
+
+ if ((pHddCtx->scan_reject_cnt >=
+ SCAN_REJECT_THRESHOLD) &&
+ (jiffies_to_msecs(jiffies) -
+ pHddCtx->last_scan_reject_timestamp) >=
+ SCAN_REJECT_THRESHOLD_TIME)
{
pHddCtx->last_scan_reject_timestamp = 0;
+ pHddCtx->scan_reject_cnt = 0;
if (pHddCtx->cfg_ini->enableFatalEvent)
vos_fatal_event_logs_req(WLAN_LOG_TYPE_FATAL,
WLAN_LOG_INDICATOR_HOST_DRIVER,
@@ -13126,6 +13160,7 @@ int __wlan_hdd_cfg80211_scan( struct wiphy *wiphy,
pHddCtx->last_scan_reject_timestamp = 0;
pHddCtx->last_scan_reject_session_id = 0xFF;
pHddCtx->last_scan_reject_reason = 0;
+ pHddCtx->scan_reject_cnt = 0;
vos_mem_zero( &scanRequest, sizeof(scanRequest));
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c
index d04cea15934..57596797597 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c
@@ -2530,6 +2530,7 @@ VOS_STATUS hdd_wlan_re_init(void)
pHddCtx->last_scan_reject_session_id = 0xFF;
pHddCtx->last_scan_reject_reason = 0;
pHddCtx->last_scan_reject_timestamp = 0;
+ pHddCtx->scan_reject_cnt = 0;
pHddCtx->hdd_mcastbcast_filter_set = FALSE;
pHddCtx->btCoexModeSet = FALSE;
hdd_register_mcast_bcast_filter(pHddCtx);
diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c
index 4423bc22d49..668b61948f4 100644
--- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c
+++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c
@@ -11789,6 +11789,7 @@ int hdd_wlan_startup(struct device *dev )
pHddCtx->last_scan_reject_session_id = 0xFF;
pHddCtx->last_scan_reject_reason = 0;
pHddCtx->last_scan_reject_timestamp = 0;
+ pHddCtx->scan_reject_cnt = 0;
init_completion(&pHddCtx->full_pwr_comp_var);
init_completion(&pHddCtx->standby_comp_var);
diff --git a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h
index b635693130c..75c73e44102 100644
--- a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h
+++ b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2016, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -597,7 +597,7 @@
#define SIR_MAC_MAX_NUMBER_OF_RATES 12
#define SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS 4
#define SIR_MAC_KEY_LENGTH 13 // WEP Maximum key length size
-#define SIR_MAC_AUTH_CHALLENGE_LENGTH 128
+#define SIR_MAC_AUTH_CHALLENGE_LENGTH 253
#define SIR_MAC_WEP_IV_LENGTH 4
#define SIR_MAC_WEP_ICV_LENGTH 4
diff --git a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h
index c4284495059..50788d8af08 100644
--- a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h
+++ b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -30,7 +30,7 @@
*
*
* This file was automatically generated by 'framesc'
- * Wed Aug 10 14:01:47 2016 from the following file(s):
+ * Tue Jul 4 11:19:48 2017 from the following file(s):
*
* dot11f.frms
*
@@ -84,8 +84,8 @@ typedef tANI_U32 tDOT11F_U64[2];
#define DOT11F_BUFFER_OVERFLOW ( 0x10000005 )
#define DOT11F_MANDATORY_TLV_MISSING ( 0x00001000 )
#define DOT11F_FAILED(code) ( (code) & 0x10000000 )
-#define DOT11F_WARNED(code) ( ( ( 0 == (code) ) & 0x10000000 ) && code)
#define DOT11F_SUCCEEDED(code) ( (code) == 0 )
+#define DOT11F_WARNED(code) (!DOT11F_SUCCEEDED(code) && !DOT11F_FAILED(code))
/*********************************************************************
* Fixed Fields *
diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
index 09bb745e1f5..0f1ee26b701 100644
--- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
+++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c
@@ -140,12 +140,14 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
{
tANI_U8 *pBody, keyId, cfgPrivacyOptImp,
defaultKey[SIR_MAC_KEY_LENGTH],
- encrAuthFrame[LIM_ENCR_AUTH_BODY_LEN],
- plainBody[256];
+ *encrAuthFrame = NULL,
+ *plainBody = NULL;
tANI_U16 frameLen;
//tANI_U32 authRspTimeout, maxNumPreAuth, val;
tANI_U32 maxNumPreAuth, val;
- tSirMacAuthFrameBody *pRxAuthFrameBody, rxAuthFrame, authFrame;
+ tSirMacAuthFrameBody *pRxAuthFrameBody,
+ *rxAuthFrame = NULL,
+ *authFrame = NULL;
tpSirMacMgmtHdr pHdr;
tCfgWepKeyEntry *pKeyMapEntry = NULL;
struct tLimPreAuthNode *pAuthNode;
@@ -153,7 +155,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
tANI_U8 decryptResult;
tANI_U8 *pChallenge;
tANI_U32 key_length=8;
- tANI_U8 challengeTextArray[SIR_MAC_AUTH_CHALLENGE_LENGTH];
+ tANI_U8 *challengeTextArray = NULL;
tpDphHashNode pStaDs = NULL;
tANI_U16 assocId = 0;
tANI_U16 currSeqNo = 0;
@@ -203,6 +205,42 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
ccmCfgSetInt(pMac,WNI_CFG_AUTHENTICATE_FAILURE_TIMEOUT ,
psessionEntry->defaultAuthFailureTimeout, NULL, eANI_BOOLEAN_FALSE);
}
+
+ rxAuthFrame = vos_mem_malloc(sizeof(tSirMacAuthFrameBody));
+ if (!rxAuthFrame) {
+ limLog(pMac, LOGE, FL("Failed to allocate memory"));
+ return;
+ }
+
+ authFrame = vos_mem_malloc(sizeof(tSirMacAuthFrameBody));
+ if (!authFrame) {
+ limLog(pMac, LOGE, FL("failed to allocate memory"));
+ goto free;
+ }
+
+ encrAuthFrame = vos_mem_malloc(LIM_ENCR_AUTH_BODY_LEN);
+ if (!encrAuthFrame) {
+ limLog(pMac, LOGE, FL("failed to allocate memory"));
+ goto free;
+ }
+
+ plainBody = vos_mem_malloc(LIM_ENCR_AUTH_BODY_LEN);
+ if (!plainBody) {
+ limLog(pMac, LOGE, FL("failed to allocate memory"));
+ goto free;
+ }
+
+ challengeTextArray = vos_mem_malloc(SIR_MAC_AUTH_CHALLENGE_LENGTH);
+ if(!challengeTextArray) {
+ limLog(pMac, LOGE, FL("failed to allocate memory"));
+ goto free;
+ }
+
+ vos_mem_set(rxAuthFrame, sizeof(tSirMacAuthFrameBody), 0);
+ vos_mem_set(authFrame, sizeof(tSirMacAuthFrameBody), 0);
+ vos_mem_set(encrAuthFrame, LIM_ENCR_AUTH_BODY_LEN, 0);
+ vos_mem_set(plainBody, LIM_ENCR_AUTH_BODY_LEN, 0);
+ vos_mem_set(challengeTextArray, SIR_MAC_AUTH_CHALLENGE_LENGTH, 0);
/// Determine if WEP bit is set in the FC or received MAC header
if (pHdr->fc.wep)
@@ -220,7 +258,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limSendDeauthMgmtFrame( pMac, eSIR_MAC_MIC_FAILURE_REASON,
pHdr->sa, psessionEntry, FALSE );
- return;
+ goto free;
}
// Extract key ID from IV (most 2 bits of 4th byte of IV)
@@ -238,19 +276,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
if (psessionEntry->limSystemRole == eLIM_STA_ROLE || psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)
{
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode = eSIR_MAC_CHALLENGE_FAILURE_STATUS;
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber = SIR_MAC_AUTH_FRAME_4;
+ authFrame->authStatusCode = eSIR_MAC_CHALLENGE_FAILURE_STATUS;
// Log error
PELOGE(limLog(pMac, LOGE,
FL("received Authentication frame with wep bit set on "
"role=%d "MAC_ADDRESS_STR),
psessionEntry->limSystemRole, MAC_ADDR_ARRAY(pHdr->sa) );)
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
if (frameLen < LIM_ENCR_AUTH_BODY_LEN)
@@ -261,7 +299,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
frameLen);
limPrintMacAddr(pMac, pHdr->sa, LOGE);
- return;
+ goto free;
}
if(psessionEntry->limSystemRole == eLIM_AP_ROLE)
{
@@ -303,18 +341,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* an Authentication frame with FC bit set.
* Send Auth frame4 with 'out of sequence' status code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
else
{
@@ -342,18 +380,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* out of sequence Auth frame status code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
}
@@ -378,18 +416,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* Send Authentication frame
* with challenge failure status code
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
} // if (!pKeyMapEntry->wepOn)
else
{
@@ -411,30 +449,30 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limDeletePreAuthNode(pMac,
pHdr->sa);
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
if ( ( sirConvertAuthFrame2Struct(pMac, plainBody, frameLen-8,
- &rxAuthFrame)!=eSIR_SUCCESS ) ||
- ( !isAuthValid(pMac, &rxAuthFrame,psessionEntry) ) )
+ rxAuthFrame)!=eSIR_SUCCESS ) ||
+ ( !isAuthValid(pMac, rxAuthFrame,psessionEntry) ) )
{
PELOGE(limLog(pMac, LOGE,
FL("failed to convert Auth Frame to structure "
"or Auth is not valid "));)
- return;
+ goto free;
}
@@ -466,18 +504,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* with challenge failure status code
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
key_length=val;
@@ -499,28 +537,28 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
/// ICV failure
limDeletePreAuthNode(pMac,
pHdr->sa);
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
if ( ( sirConvertAuthFrame2Struct(pMac, plainBody, frameLen-8,
- &rxAuthFrame)!=eSIR_SUCCESS ) ||
- ( !isAuthValid(pMac, &rxAuthFrame, psessionEntry) ) )
+ rxAuthFrame)!=eSIR_SUCCESS ) ||
+ ( !isAuthValid(pMac, rxAuthFrame, psessionEntry) ) )
{
limLog(pMac, LOGE,
FL("failed to convert Auth Frame to structure "
"or Auth is not valid "));
- return;
+ goto free;
}
} // End of check for Key Mapping/Default key presence
}
@@ -540,18 +578,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* should have been 'unsupported algorithm' status code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
} // else if (wlan_cfgGetInt(CFG_PRIVACY_OPTION_IMPLEMENTED))
} // if (fc.wep)
else
@@ -559,18 +597,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
if ( ( sirConvertAuthFrame2Struct(pMac, pBody,
- frameLen, &rxAuthFrame)!=eSIR_SUCCESS ) ||
- ( !isAuthValid(pMac, &rxAuthFrame,psessionEntry) ) )
+ frameLen, rxAuthFrame)!=eSIR_SUCCESS ) ||
+ ( !isAuthValid(pMac, rxAuthFrame,psessionEntry) ) )
{
PELOGE(limLog(pMac, LOGE,
FL("failed to convert Auth Frame to structure or Auth is "
"not valid "));)
- return;
+ goto free;
}
}
- pRxAuthFrameBody = &rxAuthFrame;
+ pRxAuthFrameBody = rxAuthFrame;
PELOGW(limLog(pMac, LOGW,
FL("Received Auth frame with type=%d seqnum=%d, status=%d (%d)"),
@@ -655,7 +693,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limSendDeauthMgmtFrame(pMac, eSIR_MAC_UNSPEC_FAILURE_REASON,
(tANI_U8 *) pHdr->sa, psessionEntry, FALSE);
limTriggerSTAdeletion(pMac, pStaDs, psessionEntry);
- return;
+ goto free;
}
}
@@ -718,7 +756,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limSendDeauthMgmtFrame(pMac,
eSIR_MAC_UNSPEC_FAILURE_REASON, (tANI_U8 *) pAuthNode->peerMacAddr, psessionEntry, FALSE);
limTriggerSTAdeletion(pMac, pStaDs, psessionEntry);
- return;
+ goto free;
}
}
else
@@ -730,7 +768,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* */
PELOGE(limLog(pMac, LOGE, FL("STA is initiating "
"Authentication after ACK lost..."));)
- return;
+ goto free;
}
}
if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_NUM_PRE_AUTH,
@@ -754,19 +792,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* reached. Send Authentication frame
* with unspecified failure
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_UNSPEC_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
/// No Pre-auth context exists for the STA.
if (limIsAuthAlgoSupported(
@@ -786,8 +824,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limLog(pMac, LOGW,
FL("Max pre-auth nodes reached "));
limPrintMacAddr(pMac, pHdr->sa, LOGW);
-
- return;
+ goto free;
}
limLog(pMac, LOG1,
@@ -814,13 +851,13 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* status code.
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode = eSIR_MAC_SUCCESS_STATUS;
+ authFrame->authStatusCode = eSIR_MAC_SUCCESS_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
@@ -873,20 +910,20 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* code.
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
else
{
@@ -900,7 +937,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
FL("Max pre-auth nodes reached "));
limPrintMacAddr(pMac, pHdr->sa, LOGW);
- return;
+ goto free;
}
vos_mem_copy((tANI_U8 *) pAuthNode->peerMacAddr,
@@ -937,33 +974,34 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* unspecified failure status code.
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_UNSPEC_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
limDeletePreAuthNode(pMac, pHdr->sa);
- return;
+ goto free;
}
limActivateAuthRspTimer(pMac, pAuthNode);
pAuthNode->fTimerStarted = 1;
- // get random bytes and use as
- // challenge text
- // TODO
- //if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( 0, (tANI_U8 *)challengeTextArray, SIR_MAC_AUTH_CHALLENGE_LENGTH ) ) )
+ /*
+ * get random bytes and use as challenge text
+ */
+ if( !VOS_IS_STATUS_SUCCESS( vos_rand_get_bytes( 0, (tANI_U8 *)challengeTextArray, SIR_MAC_AUTH_CHALLENGE_LENGTH ) ) )
{
limLog(pMac, LOGE,FL("Challenge text "
"preparation failed in limProcessAuthFrame"));
+ goto free;
}
pChallenge = pAuthNode->challengeText;
@@ -976,20 +1014,20 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* Sending Authenticaton frame with challenge.
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_SUCCESS_STATUS;
- authFrame.type = SIR_MAC_CHALLENGE_TEXT_EID;
- authFrame.length = SIR_MAC_AUTH_CHALLENGE_LENGTH;
- vos_mem_copy(authFrame.challengeText,
+ authFrame->type = SIR_MAC_CHALLENGE_TEXT_EID;
+ authFrame->length = SIR_MAC_AUTH_CHALLENGE_LENGTH;
+ vos_mem_copy(authFrame->challengeText,
pAuthNode->challengeText,
SIR_MAC_AUTH_CHALLENGE_LENGTH);
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
@@ -1013,20 +1051,20 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* with auth algorithm not supported status code
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
} // end switch(pRxAuthFrameBody->authAlgoNumber)
} // if (limIsAuthAlgoSupported(pRxAuthFrameBody->authAlgoNumber))
else
@@ -1043,19 +1081,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* authentication algorithm requested by sending party.
* Reject Authentication with StatusCode=13.
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
} //end if (limIsAuthAlgoSupported(pRxAuthFrameBody->authAlgoNumber))
break;
@@ -1075,7 +1113,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
psessionEntry->limMlmState);
limPrintMacAddr(pMac, pHdr->sa, LOG1);
- return;
+ goto free;
}
if ( !vos_mem_compare((tANI_U8 *) pHdr->sa,
@@ -1150,7 +1188,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
FL("Max pre-auth nodes reached "));
limPrintMacAddr(pMac, pHdr->sa, LOGW);
- return;
+ goto free;
}
limLog(pMac, LOG1,
@@ -1205,18 +1243,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber,
MAC_ADDR_ARRAY(pHdr->sa));)
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_ALGO_NOT_SUPPORTED_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
else
{
@@ -1229,7 +1267,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
FL("received Auth frame with invalid "
"challenge text IE"));)
- return;
+ goto free;
}
/**
@@ -1254,14 +1292,14 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* Send Auth frame with
* challenge failure status code
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
@@ -1269,7 +1307,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limRestoreFromAuthState(pMac, eSIR_SME_NO_KEY_MAPPING_KEY_FOR_PEER,
eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry);
- return;
+ goto free;
} // if (pKeyMapEntry->key == NULL)
else
{
@@ -1334,15 +1372,15 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limLog(pMac, LOGP,
FL("could not retrieve Default key"));
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
pRxAuthFrameBody->authTransactionSeqNumber + 1;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
@@ -1420,18 +1458,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* Shared Key authentication type. Reject with Auth frame4
* with 'out of sequence' status code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
if (psessionEntry->limSystemRole == eLIM_AP_ROLE || psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE ||
@@ -1451,18 +1489,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
MAC_ADDR_ARRAY(pHdr->sa));)
/// WEP bit is not set in FC of Auth Frame3
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
pAuthNode = limSearchPreAuthList(pMac,
@@ -1482,18 +1520,18 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* Send Auth frame4 with 'out of sequence'
* status code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_FRAME_OUT_OF_SEQ_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
if (pAuthNode->mlmState == eLIM_MLM_AUTH_RSP_TIMEOUT_STATE)
@@ -1507,14 +1545,14 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* Reject by sending Auth Frame4 with
* Auth respone timeout Status Code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_AUTH_RSP_TIMEOUT_STATUS;
limSendAuthMgmtFrame(
- pMac, &authFrame,
+ pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
@@ -1523,7 +1561,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
limDeletePreAuthNode(pMac,
pHdr->sa);
- return;
+ goto free;
} // end switch (pAuthNode->mlmState)
if (pRxAuthFrameBody->authStatusCode != eSIR_MAC_SUCCESS_STATUS)
@@ -1540,7 +1578,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
MAC_ADDRESS_STR), pRxAuthFrameBody->authStatusCode,
MAC_ADDR_ARRAY(pHdr->sa));)
- return;
+ goto free;
}
/**
@@ -1565,12 +1603,12 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
/**
* Send Authentication Frame4 with 'success' Status Code.
*/
- authFrame.authAlgoNumber = eSIR_SHARED_KEY;
- authFrame.authTransactionSeqNumber =
+ authFrame->authAlgoNumber = eSIR_SHARED_KEY;
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode = eSIR_MAC_SUCCESS_STATUS;
+ authFrame->authStatusCode = eSIR_MAC_SUCCESS_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
@@ -1603,19 +1641,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
* delete STA context.
*/
- authFrame.authAlgoNumber =
+ authFrame->authAlgoNumber =
pRxAuthFrameBody->authAlgoNumber;
- authFrame.authTransactionSeqNumber =
+ authFrame->authTransactionSeqNumber =
SIR_MAC_AUTH_FRAME_4;
- authFrame.authStatusCode =
+ authFrame->authStatusCode =
eSIR_MAC_CHALLENGE_FAILURE_STATUS;
- limSendAuthMgmtFrame(pMac, &authFrame,
+ limSendAuthMgmtFrame(pMac, authFrame,
pHdr->sa,
LIM_NO_WEP_IN_FC,
psessionEntry, eSIR_FALSE);
- return;
+ goto free;
}
} // if (pMac->lim.gLimSystemRole == eLIM_AP_ROLE || ...
@@ -1636,7 +1674,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
"%d, addr "MAC_ADDRESS_STR), psessionEntry->limMlmState,
MAC_ADDR_ARRAY(pHdr->sa));
- return;
+ goto free;
}
if (pRxAuthFrameBody->authAlgoNumber != eSIR_SHARED_KEY)
@@ -1654,7 +1692,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
"algo %d "MAC_ADDRESS_STR), pRxAuthFrameBody->authAlgoNumber,
MAC_ADDR_ARRAY(pHdr->sa));)
- return;
+ goto free;
}
if ( !vos_mem_compare((tANI_U8 *) pHdr->sa,
@@ -1710,7 +1748,7 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
FL("Max pre-auth nodes reached "));
limPrintMacAddr(pMac, pHdr->sa, LOGW);
- return;
+ goto free;
}
limLog(pMac, LOG1,
FL("Alloc new data: peer " MAC_ADDRESS_STR),
@@ -1759,6 +1797,19 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse
break;
} // end switch (pRxAuthFrameBody->authTransactionSeqNumber)
+
+free:
+ if (authFrame)
+ vos_mem_free(authFrame);
+ if (rxAuthFrame)
+ vos_mem_free(rxAuthFrame);
+ if (encrAuthFrame)
+ vos_mem_free(encrAuthFrame);
+ if (plainBody)
+ vos_mem_free(plainBody);
+ if (challengeTextArray)
+ vos_mem_free(challengeTextArray);
+
} /*** end limProcessAuthFrame() ***/
diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c
index 45a7823fa43..ae588284b56 100644
--- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c
+++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c
@@ -666,7 +666,7 @@ limEncryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 keyId, tANI_U8 *pKey, tANI_U8 *
*/
void
-limComputeCrc32(tANI_U8 *pDest, tANI_U8 * pSrc, tANI_U8 len)
+limComputeCrc32(tANI_U8 *pDest, tANI_U8 * pSrc, tANI_U16 len)
{
tANI_U32 crc;
int i;
@@ -753,7 +753,7 @@ limRC4(tANI_U8 *pDest, tANI_U8 *pSrc, tANI_U8 *seed, tANI_U32 keyLength, tANI_U1
{
tANI_U8 i = ctx.i;
tANI_U8 j = ctx.j;
- tANI_U8 len = (tANI_U8) frameLen;
+ tANI_U16 len = frameLen;
while (len-- > 0)
{
@@ -835,7 +835,7 @@ limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody,
// Compute CRC-32 and place them in last 4 bytes of encrypted body
limComputeCrc32(icv,
(tANI_U8 *) pPlainBody,
- (tANI_U8) (frameLen - SIR_MAC_WEP_ICV_LENGTH));
+ (frameLen - SIR_MAC_WEP_ICV_LENGTH));
// Compare RX_ICV with computed ICV
for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++)
diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h
index e379bc2a370..1fc227478d7 100644
--- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h
+++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -59,7 +59,7 @@ tANI_U8 limDeleteOpenAuthPreAuthNode(tpAniSirGlobal pMac);
// Encryption/Decryption related functions
tCfgWepKeyEntry *limLookUpKeyMappings(tSirMacAddr);
-void limComputeCrc32(tANI_U8 *, tANI_U8 *, tANI_U8);
+void limComputeCrc32(tANI_U8 *, tANI_U8 *, tANI_U16);
void limRC4(tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32, tANI_U16);
void limEncryptAuthFrame(tpAniSirGlobal, tANI_U8, tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32);
tANI_U8 limDecryptAuthFrame(tpAniSirGlobal, tANI_U8 *, tANI_U8 *, tANI_U8 *, tANI_U32, tANI_U16);
diff --git a/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c b/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c
index 43516354634..5bba7e7df26 100644
--- a/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c
+++ b/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c
@@ -622,14 +622,25 @@ rrmProcessBeaconReportReq( tpAniSirGlobal pMac,
pSmeBcnReportReq->channelList.numChannels = num_channels;
if( pBeaconReq->measurement_request.Beacon.num_APChannelReport )
{
- tANI_U8 *pChanList = pSmeBcnReportReq->channelList.channelNumber;
- for( num_APChanReport = 0 ; num_APChanReport < pBeaconReq->measurement_request.Beacon.num_APChannelReport ; num_APChanReport++ )
- {
- vos_mem_copy(pChanList,
- pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].channelList,
- pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList);
-
- pChanList += pBeaconReq->measurement_request.Beacon.APChannelReport[num_APChanReport].num_channelList;
+ tANI_U8 *ch_lst = pSmeBcnReportReq->channelList.channelNumber;
+ tANI_U8 len;
+ tANI_U16 ch_ctr = 0;
+ for(num_APChanReport = 0;
+ num_APChanReport <
+ pBeaconReq->measurement_request.Beacon.num_APChannelReport;
+ num_APChanReport++) {
+ len = pBeaconReq->measurement_request.Beacon.
+ APChannelReport[num_APChanReport].num_channelList;
+ if (ch_ctr + len >
+ sizeof(pSmeBcnReportReq->channelList.channelNumber))
+ break;
+
+ vos_mem_copy(&ch_lst[ch_ctr],
+ pBeaconReq->measurement_request.Beacon.
+ APChannelReport[num_APChanReport].channelList,
+ len);
+
+ ch_ctr += len;
}
}
diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c
index 52117f00b59..ebdb096da29 100644
--- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c
+++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 2016, 2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -28,7 +28,7 @@
*
*
* This file was automatically generated by 'framesc'
- * Wed Aug 10 14:01:47 2016 from the following file(s):
+ * Tue Jul 4 11:19:48 2017 from the following file(s):
*
* dot11f.frms
*
@@ -20257,6 +20257,10 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx,
}
countOffset = ( (0 != pIe->arraybound) * ( *(tANI_U16* )(pFrm + pIe->countOffset)));
+ if (0 != pIe->arraybound && countOffset >= pIe->arraybound) {
+ status |= DOT11F_DUPLICATE_IE;
+ goto skip_dup_ie;
+ }
switch (pIe->sig)
{
case SigIeAPName:
@@ -20731,6 +20735,7 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx,
status |= DOT11F_UNKNOWN_IES;
}
+skip_dup_ie:
pBufRemaining += len;
if (len > nBufRemaining)
diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c
index 6009013c992..a3f30f0653f 100644
--- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c
+++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/parserApi.c
@@ -2176,12 +2176,6 @@ tSirRetStatus sirConvertProbeFrame2Struct(tpAniSirGlobal pMac,
vos_mem_vfree(pr);
return eSIR_FAILURE;
}
- else if ( DOT11F_WARNED( status ) )
- {
- limLog( pMac, LOGW, FL("There were warnings while unpacking a Probe Response (0x%08x, %d bytes)"),
- status, nFrame );
- PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);)
- }
// & "transliterate" from a 'tDot11fProbeResponse' to a 'tSirProbeRespBeacon'...
@@ -3553,12 +3547,6 @@ sirConvertBeaconFrame2Struct(tpAniSirGlobal pMac,
vos_mem_vfree(pBeacon);
return eSIR_FAILURE;
}
- else if ( DOT11F_WARNED( status ) )
- {
- limLog( pMac, LOGW, FL("There were warnings while unpacking Beacon IEs (0x%08x, %d bytes)"),
- status, nPayload );
- PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pPayload, nPayload);)
- }
// & "transliterate" from a 'tDot11fBeacon' to a 'tSirProbeRespBeacon'...
// Timestamp
diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_types.h b/drivers/staging/prima/CORE/VOSS/inc/vos_types.h
index 70387494ad4..70387494ad4 100644..100755
--- a/drivers/staging/prima/CORE/VOSS/inc/vos_types.h
+++ b/drivers/staging/prima/CORE/VOSS/inc/vos_types.h
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 5864d5cd8b3..a15eb1cac2f 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -2169,6 +2169,8 @@ static void msm_otg_start_host(struct usb_otg *otg, int on)
motg->inputs, otg->phy->state);
wake_up(&motg->host_suspend_wait);
+ pm_runtime_disable(&hcd->self.root_hub->dev);
+ pm_runtime_barrier(&hcd->self.root_hub->dev);
usb_remove_hcd(hcd);
if (pdata->enable_axi_prefetch)
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 083bb2045dd..33cf2cf96c4 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -801,10 +801,15 @@ static ssize_t mdss_dsi_cmd_write(struct file *file, const char __user *p,
/* Writing in batches is possible */
ret = simple_write_to_buffer(string_buf, blen, ppos, p, count);
+ if (ret < 0) {
+ pr_err("%s: Failed to copy data\n", __func__);
+ mutex_unlock(&pcmds->dbg_mutex);
+ return -EINVAL;
+ }
- string_buf[blen] = '\0';
+ string_buf[ret] = '\0';
pcmds->string_buf = string_buf;
- pcmds->sblen = blen;
+ pcmds->sblen = count;
mutex_unlock(&pcmds->dbg_mutex);
return ret;
}
diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c
index fbb081245dc..a1f12e27f3c 100755
--- a/fs/sdcardfs/file.c
+++ b/fs/sdcardfs/file.c
@@ -104,12 +104,19 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd,
{
long err = -ENOTTY;
struct file *lower_file;
+ const struct cred *saved_cred = NULL;
+ struct dentry *dentry = file->f_path.dentry;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
lower_file = sdcardfs_lower_file(file);
/* XXX: use vfs_ioctl if/when VFS exports it */
if (!lower_file || !lower_file->f_op)
goto out;
+
+ /* save current_cred and override it */
+ OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file)));
+
if (lower_file->f_op->unlocked_ioctl)
err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
@@ -117,6 +124,7 @@ static long sdcardfs_unlocked_ioctl(struct file *file, unsigned int cmd,
if (!err)
sdcardfs_copy_and_fix_attrs(file_inode(file),
file_inode(lower_file));
+ REVERT_CRED(saved_cred);
out:
return err;
}
@@ -127,15 +135,23 @@ static long sdcardfs_compat_ioctl(struct file *file, unsigned int cmd,
{
long err = -ENOTTY;
struct file *lower_file;
+ const struct cred *saved_cred = NULL;
+ struct dentry *dentry = file->f_path.dentry;
+ struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
lower_file = sdcardfs_lower_file(file);
/* XXX: use vfs_ioctl if/when VFS exports it */
if (!lower_file || !lower_file->f_op)
goto out;
+
+ /* save current_cred and override it */
+ OVERRIDE_CRED(sbi, saved_cred, SDCARDFS_I(file_inode(file)));
+
if (lower_file->f_op->compat_ioctl)
err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
+ REVERT_CRED(saved_cred);
out:
return err;
}
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 05dcf0d5e08..91e180d7161 100755
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -773,13 +773,9 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct
* afterwards in the other cases: we fsstack_copy_inode_size from
* the lower level.
*/
- if (current->mm)
- down_write(&current->mm->mmap_sem);
if (ia->ia_valid & ATTR_SIZE) {
err = inode_newsize_ok(&tmp, ia->ia_size);
if (err) {
- if (current->mm)
- up_write(&current->mm->mmap_sem);
goto out;
}
truncate_setsize(inode, ia->ia_size);
@@ -802,8 +798,6 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct
err = notify_change2(lower_mnt, lower_dentry, &lower_ia); /* note: lower_ia */
mutex_unlock(&lower_dentry->d_inode->i_mutex);
- if (current->mm)
- up_write(&current->mm->mmap_sem);
if (err)
goto out;
diff --git a/include/linux/pid.h b/include/linux/pid.h
index a089a3c447f..ed7b1f73192 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -8,7 +8,9 @@ enum pid_type
PIDTYPE_PID,
PIDTYPE_PGID,
PIDTYPE_SID,
- PIDTYPE_MAX
+ PIDTYPE_MAX,
+ /* only valid to __task_pid_nr_ns() */
+ __PIDTYPE_TGID
};
/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 425bf4c52d4..5b7d2abe10d 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1704,13 +1704,6 @@ static inline pid_t task_tgid_nr(struct task_struct *tsk)
return tsk->tgid;
}
-pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);
-
-static inline pid_t task_tgid_vnr(struct task_struct *tsk)
-{
- return pid_vnr(task_tgid(tsk));
-}
-
static inline pid_t task_pgrp_nr_ns(struct task_struct *tsk,
struct pid_namespace *ns)
@@ -1735,6 +1728,16 @@ static inline pid_t task_session_vnr(struct task_struct *tsk)
return __task_pid_nr_ns(tsk, PIDTYPE_SID, NULL);
}
+static inline pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
+{
+ return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, ns);
+}
+
+static inline pid_t task_tgid_vnr(struct task_struct *tsk)
+{
+ return __task_pid_nr_ns(tsk, __PIDTYPE_TGID, NULL);
+}
+
/* obsolete, do not use */
static inline pid_t task_pgrp_nr(struct task_struct *tsk)
{
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 5cadd509fef..a4987ae1680 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6996,6 +6996,37 @@ static void mutex_lock_double(struct mutex *a, struct mutex *b)
mutex_lock_nested(b, SINGLE_DEPTH_NESTING);
}
+/*
+ * Variation on perf_event_ctx_lock_nested(), except we take two context
+ * mutexes.
+ */
+static struct perf_event_context *
+__perf_event_ctx_lock_double(struct perf_event *group_leader,
+ struct perf_event_context *ctx)
+{
+ struct perf_event_context *gctx;
+
+again:
+ rcu_read_lock();
+ gctx = ACCESS_ONCE(group_leader->ctx);
+ if (!atomic_inc_not_zero(&gctx->refcount)) {
+ rcu_read_unlock();
+ goto again;
+ }
+ rcu_read_unlock();
+
+ mutex_lock_double(&gctx->mutex, &ctx->mutex);
+
+ if (group_leader->ctx != gctx) {
+ mutex_unlock(&ctx->mutex);
+ mutex_unlock(&gctx->mutex);
+ put_ctx(gctx);
+ goto again;
+ }
+
+ return gctx;
+}
+
/**
* sys_perf_event_open - open a performance event, associate it to a task/cpu
*
@@ -7210,13 +7241,31 @@ SYSCALL_DEFINE5(perf_event_open,
}
if (move_group) {
- gctx = group_leader->ctx;
+ gctx = __perf_event_ctx_lock_double(group_leader, ctx);
+
+ /*
+ * Check if we raced against another sys_perf_event_open() call
+ * moving the software group underneath us.
+ */
+ if (!(group_leader->group_flags & PERF_GROUP_SOFTWARE)) {
+ /*
+ * If someone moved the group out from under us, check
+ * if this new event wound up on the same ctx, if so
+ * its the regular !move_group case, otherwise fail.
+ */
+ if (gctx != ctx) {
+ err = -EINVAL;
+ goto err_locked;
+ } else {
+ perf_event_ctx_unlock(group_leader, gctx);
+ move_group = 0;
+ }
+ }
/*
* See perf_event_ctx_lock() for comments on the details
* of swizzling perf_event::ctx.
*/
- mutex_lock_double(&gctx->mutex, &ctx->mutex);
mutex_lock(&gctx->mutex);
perf_remove_from_context(group_leader, false);
@@ -7259,7 +7308,7 @@ SYSCALL_DEFINE5(perf_event_open,
perf_unpin_context(ctx);
if (move_group) {
- mutex_unlock(&gctx->mutex);
+ perf_event_ctx_unlock(group_leader, gctx);
put_ctx(gctx);
}
mutex_unlock(&ctx->mutex);
@@ -7290,6 +7339,11 @@ SYSCALL_DEFINE5(perf_event_open,
fd_install(event_fd, event_file);
return event_fd;
+err_locked:
+ if (move_group)
+ perf_event_ctx_unlock(group_leader, gctx);
+ mutex_unlock(&ctx->mutex);
+ fput(event_file);
err_context:
perf_unpin_context(ctx);
put_ctx(ctx);
diff --git a/kernel/fork.c b/kernel/fork.c
index b49f32dd113..23d54f051a5 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -721,8 +721,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
mm = get_task_mm(task);
if (mm && mm != current->mm &&
- !ptrace_may_access(task, mode) &&
- !capable(CAP_SYS_RESOURCE)) {
+ !ptrace_may_access(task, mode)) {
mmput(mm);
mm = ERR_PTR(-EACCES);
}
diff --git a/kernel/pid.c b/kernel/pid.c
index 43f22f451bd..054389f18fb 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -522,8 +522,11 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
if (!ns)
ns = task_active_pid_ns(current);
if (likely(pid_alive(task))) {
- if (type != PIDTYPE_PID)
+ if (type != PIDTYPE_PID) {
+ if (type == __PIDTYPE_TGID)
+ type = PIDTYPE_PID;
task = task->group_leader;
+ }
nr = pid_nr_ns(task->pids[type].pid, ns);
}
rcu_read_unlock();
@@ -532,12 +535,6 @@ pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type,
}
EXPORT_SYMBOL(__task_pid_nr_ns);
-pid_t task_tgid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns)
-{
- return pid_nr_ns(task_tgid(tsk), ns);
-}
-EXPORT_SYMBOL(task_tgid_nr_ns);
-
struct pid_namespace *task_active_pid_ns(struct task_struct *tsk)
{
return ns_of_pid(task_pid(tsk));
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 42bddf3dbe8..a311ba68fcc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -52,7 +52,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
u8 code, u8 ident, u16 dlen, void *data);
static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
void *data);
-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
@@ -1298,7 +1298,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -2992,12 +2992,15 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
return len;
}
-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
{
struct l2cap_conf_opt *opt = *ptr;
BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
+ if (size < L2CAP_CONF_OPT_SIZE + len)
+ return;
+
opt->type = type;
opt->len = len;
@@ -3022,7 +3025,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
*ptr += L2CAP_CONF_OPT_SIZE + len;
}
-static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
+static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
{
struct l2cap_conf_efs efs;
@@ -3050,7 +3053,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
}
l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, size);
}
static void l2cap_ack_timeout(struct work_struct *work)
@@ -3194,11 +3197,12 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
chan->ack_win = chan->tx_win;
}
-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
{
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = chan->mode };
void *ptr = req->data;
+ void *endptr = data + data_size;
u16 size;
BT_DBG("chan %pK", chan);
@@ -3223,7 +3227,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
done:
if (chan->imtu != L2CAP_DEFAULT_MTU)
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
switch (chan->mode) {
case L2CAP_MODE_BASIC:
@@ -3239,7 +3243,7 @@ done:
rfc.max_pdu_size = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_MODE_ERTM:
@@ -3259,21 +3263,21 @@ done:
L2CAP_DEFAULT_TX_WINDOW);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
- l2cap_add_opt_efs(&ptr, chan);
+ l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
- chan->tx_win);
+ chan->tx_win, endptr - ptr);
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
if (chan->fcs == L2CAP_FCS_NONE ||
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
chan->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
- chan->fcs);
+ chan->fcs, endptr - ptr);
}
break;
@@ -3291,17 +3295,17 @@ done:
rfc.max_pdu_size = cpu_to_le16(size);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
- l2cap_add_opt_efs(&ptr, chan);
+ l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
if (chan->fcs == L2CAP_FCS_NONE ||
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
chan->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
- chan->fcs);
+ chan->fcs, endptr - ptr);
}
break;
}
@@ -3312,10 +3316,11 @@ done:
return ptr - data;
}
-static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
+static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
{
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
+ void *endptr = data + data_size;
void *req = chan->conf_req;
int len = chan->conf_len;
int type, hint, olen;
@@ -3417,7 +3422,7 @@ done:
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
}
if (result == L2CAP_CONF_SUCCESS) {
@@ -3430,7 +3435,7 @@ done:
chan->omtu = mtu;
set_bit(CONF_MTU_DONE, &chan->conf_state);
}
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
if (remote_efs) {
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
@@ -3444,7 +3449,7 @@ done:
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, endptr - ptr);
} else {
/* Send PENDING Conf Rsp */
result = L2CAP_CONF_PENDING;
@@ -3477,7 +3482,7 @@ done:
set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
chan->remote_id = efs.id;
@@ -3491,7 +3496,7 @@ done:
le32_to_cpu(efs.sdu_itime);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, endptr - ptr);
}
break;
@@ -3505,7 +3510,7 @@ done:
set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
break;
@@ -3527,10 +3532,11 @@ done:
}
static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
- void *data, u16 *result)
+ void *data, size_t size, u16 *result)
{
struct l2cap_conf_req *req = data;
void *ptr = req->data;
+ void *endptr = data + size;
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
@@ -3548,13 +3554,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
chan->imtu = L2CAP_DEFAULT_MIN_MTU;
} else
chan->imtu = val;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
break;
case L2CAP_CONF_FLUSH_TO:
chan->flush_to = val;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
- 2, chan->flush_to);
+ 2, chan->flush_to, endptr - ptr);
break;
case L2CAP_CONF_RFC:
@@ -3568,13 +3574,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
chan->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_CONF_EWS:
chan->ack_win = min_t(u16, val, chan->ack_win);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
- chan->tx_win);
+ chan->tx_win, endptr - ptr);
break;
case L2CAP_CONF_EFS:
@@ -3587,7 +3593,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, endptr - ptr);
break;
case L2CAP_CONF_FCS:
@@ -3677,7 +3683,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
return;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -3885,7 +3891,7 @@ sendresp:
u8 buf[128];
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -3965,7 +3971,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
break;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, req), req);
+ l2cap_build_conf_req(chan, req, sizeof(req)), req);
chan->num_conf_req++;
break;
@@ -4069,7 +4075,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
}
/* Complete config. */
- len = l2cap_parse_conf_req(chan, rsp);
+ len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
if (len < 0) {
l2cap_send_disconn_req(chan, ECONNRESET);
goto unlock;
@@ -4103,7 +4109,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
u8 buf[64];
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -4163,7 +4169,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
char buf[64];
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
- buf, &result);
+ buf, sizeof(buf), &result);
if (len < 0) {
l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
@@ -4193,7 +4199,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
/* throw out any old stored conf requests */
result = L2CAP_CONF_SUCCESS;
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
- req, &result);
+ req, sizeof(req), &result);
if (len < 0) {
l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
@@ -4776,7 +4782,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
}
@@ -6662,7 +6668,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf),
+ l2cap_build_conf_req(chan, buf, sizeof(buf)),
buf);
chan->num_conf_req++;
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index bbb634c3e7d..5482090f285 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -65,6 +65,10 @@ struct pfkey_sock {
} dump;
};
+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
+ xfrm_address_t *saddr, xfrm_address_t *daddr,
+ u16 *family);
+
static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
{
return (struct pfkey_sock *)sk;
@@ -1900,19 +1904,14 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
/* addresses present only in tunnel mode */
if (t->mode == XFRM_MODE_TUNNEL) {
- u8 *sa = (u8 *) (rq + 1);
- int family, socklen;
+ int err;
- family = pfkey_sockaddr_extract((struct sockaddr *)sa,
- &t->saddr);
- if (!family)
- return -EINVAL;
-
- socklen = pfkey_sockaddr_len(family);
- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
- &t->id.daddr) != family)
- return -EINVAL;
- t->encap_family = family;
+ err = parse_sockaddr_pair(
+ (struct sockaddr *)(rq + 1),
+ rq->sadb_x_ipsecrequest_len - sizeof(*rq),
+ &t->saddr, &t->id.daddr, &t->encap_family);
+ if (err)
+ return err;
} else
t->encap_family = xp->family;
@@ -1932,7 +1931,11 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
return -EINVAL;
- while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+ while (len >= sizeof(*rq)) {
+ if (len < rq->sadb_x_ipsecrequest_len ||
+ rq->sadb_x_ipsecrequest_len < sizeof(*rq))
+ return -EINVAL;
+
if ((err = parse_ipsecrequest(xp, rq)) < 0)
return err;
len -= rq->sadb_x_ipsecrequest_len;
@@ -2403,7 +2406,6 @@ out:
return err;
}
-#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_sockaddr_pair_size(sa_family_t family)
{
return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
@@ -2415,7 +2417,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
{
int af, socklen;
- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
+ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
return -EINVAL;
af = pfkey_sockaddr_extract(sa, saddr);
@@ -2431,6 +2433,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
return 0;
}
+#ifdef CONFIG_NET_KEY_MIGRATE
static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
struct xfrm_migrate *m)
{
@@ -2438,13 +2441,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
struct sadb_x_ipsecrequest *rq2;
int mode;
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
- len < rq1->sadb_x_ipsecrequest_len)
+ if (len < sizeof(*rq1) ||
+ len < rq1->sadb_x_ipsecrequest_len ||
+ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
return -EINVAL;
/* old endoints */
err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
- rq1->sadb_x_ipsecrequest_len,
+ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
&m->old_saddr, &m->old_daddr,
&m->old_family);
if (err)
@@ -2453,13 +2457,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
len -= rq1->sadb_x_ipsecrequest_len;
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
- len < rq2->sadb_x_ipsecrequest_len)
+ if (len <= sizeof(*rq2) ||
+ len < rq2->sadb_x_ipsecrequest_len ||
+ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
return -EINVAL;
/* new endpoints */
err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
- rq2->sadb_x_ipsecrequest_len,
+ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
&m->new_saddr, &m->new_daddr,
&m->new_family);
if (err)
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index b7960ba8616..2e1c0855159 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1714,18 +1714,9 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
}
MT_DEBUG("qtaguid[%d]: sk=%p got_sock=%d fam=%d proto=%d\n",
par->hooknum, sk, got_sock, par->family, ipx_proto(skb, par));
- if (sk != NULL) {
- set_sk_callback_lock = true;
- read_lock_bh(&sk->sk_callback_lock);
- MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n",
- par->hooknum, sk, sk->sk_socket,
- sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
- filp = sk->sk_socket ? sk->sk_socket->file : NULL;
- MT_DEBUG("qtaguid[%d]: filp...uid=%u\n",
- par->hooknum, filp ? filp->f_cred->fsuid : -1);
- }
- if (sk == NULL || sk->sk_socket == NULL) {
+
+ if (sk == NULL) {
/*
* Here, the qtaguid_find_sk() using connection tracking
* couldn't find the owner, so for now we just count them
@@ -1733,9 +1724,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
*/
if (do_tag_stat)
account_for_uid(skb, sk, 0, par);
- MT_DEBUG("qtaguid[%d]: leaving (sk?sk->sk_socket)=%p\n",
- par->hooknum,
- sk ? sk->sk_socket : NULL);
+ MT_DEBUG("qtaguid[%d]: leaving (sk=NULL)\n", par->hooknum);
res = (info->match ^ info->invert) == 0;
atomic64_inc(&qtu_events.match_no_sk);
goto put_sock_ret_res;
@@ -1743,45 +1732,56 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
res = false;
goto put_sock_ret_res;
}
- filp = sk->sk_socket->file;
- if (filp == NULL) {
- MT_DEBUG("qtaguid[%d]: leaving filp=NULL\n", par->hooknum);
- if (do_tag_stat)
- account_for_uid(skb, sk, 0, par);
- res = ((info->match ^ info->invert) &
- (XT_QTAGUID_UID | XT_QTAGUID_GID)) == 0;
- atomic64_inc(&qtu_events.match_no_sk_file);
- goto put_sock_ret_res;
- }
- sock_uid = filp->f_cred->fsuid;
+
if (do_tag_stat)
account_for_uid(skb, sk, sock_uid, par);
+ sock_uid = sk->sk_uid;
+
/*
* The following two tests fail the match when:
* id not in range AND no inverted condition requested
* or id in range AND inverted condition requested
* Thus (!a && b) || (a && !b) == a ^ b
*/
- if (info->match & XT_QTAGUID_UID)
- if ((filp->f_cred->fsuid >= info->uid_min &&
- filp->f_cred->fsuid <= info->uid_max) ^
+ if (info->match & XT_QTAGUID_UID) {
+ kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min);
+ kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max);
+
+ if ((uid_gte(sk->sk_uid, uid_min) &&
+ uid_lte(sk->sk_uid, uid_max)) ^
!(info->invert & XT_QTAGUID_UID)) {
MT_DEBUG("qtaguid[%d]: leaving uid not matching\n",
par->hooknum);
res = false;
goto put_sock_ret_res;
}
- if (info->match & XT_QTAGUID_GID)
- if ((filp->f_cred->fsgid >= info->gid_min &&
- filp->f_cred->fsgid <= info->gid_max) ^
+ }
+ if (info->match & XT_QTAGUID_GID) {
+ kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min);
+ kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
+ set_sk_callback_lock = true;
+ read_lock_bh(&sk->sk_callback_lock);
+ MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n",
+ par->hooknum, sk, sk->sk_socket,
+ sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
+ filp = sk->sk_socket ? sk->sk_socket->file : NULL;
+ if (!filp) {
+ res = ((info->match ^ info->invert) & XT_QTAGUID_GID) == 0;
+ atomic64_inc(&qtu_events.match_no_sk_gid);
+ goto put_sock_ret_res;
+ }
+ MT_DEBUG("qtaguid[%d]: filp...uid=%u\n",
+ par->hooknum, filp ? from_kuid(&init_user_ns, filp->f_cred->fsuid) : -1);
+ if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
+ gid_lte(filp->f_cred->fsgid, gid_max)) ^
!(info->invert & XT_QTAGUID_GID)) {
MT_DEBUG("qtaguid[%d]: leaving gid not matching\n",
par->hooknum);
res = false;
goto put_sock_ret_res;
}
-
+ }
MT_DEBUG("qtaguid[%d]: leaving matched\n", par->hooknum);
res = true;
@@ -1944,7 +1944,7 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
"match_found_sk_in_ct=%llu "
"match_found_no_sk_in_ct=%llu "
"match_no_sk=%llu "
- "match_no_sk_file=%llu\n",
+ "match_no_sk_gid=%llu\n",
(u64)atomic64_read(&qtu_events.sockets_tagged),
(u64)atomic64_read(&qtu_events.sockets_untagged),
(u64)atomic64_read(&qtu_events.counter_set_changes),
@@ -1956,7 +1956,7 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
(u64)atomic64_read(&qtu_events.match_found_sk_in_ct),
(u64)atomic64_read(&qtu_events.match_found_no_sk_in_ct),
(u64)atomic64_read(&qtu_events.match_no_sk),
- (u64)atomic64_read(&qtu_events.match_no_sk_file));
+ (u64)atomic64_read(&qtu_events.match_no_sk_gid));
/* Count the following as part of the last item_index. No need
* to lock the sock_tag_list here since it is already locked when
diff --git a/net/netfilter/xt_qtaguid_internal.h b/net/netfilter/xt_qtaguid_internal.h
index 8178fbdfb03..c7052707a6a 100644
--- a/net/netfilter/xt_qtaguid_internal.h
+++ b/net/netfilter/xt_qtaguid_internal.h
@@ -289,10 +289,10 @@ struct qtaguid_event_counts {
*/
atomic64_t match_no_sk;
/*
- * The file ptr in the sk_socket wasn't there.
+ * The file ptr in the sk_socket wasn't there and we couldn't get GID.
* This might happen for traffic while the socket is being closed.
*/
- atomic64_t match_no_sk_file;
+ atomic64_t match_no_sk_gid;
};
/* Track the set active_set for the given tag. */
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 0b02579354f..862e54de538 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1594,6 +1594,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
struct sk_buff *skb;
int err;
+ err = verify_policy_dir(dir);
+ if (err)
+ return ERR_PTR(err);
+
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!skb)
return ERR_PTR(-ENOMEM);
@@ -2140,6 +2144,10 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
int err;
int n = 0;
+ err = verify_policy_dir(pi->dir);
+ if (err)
+ return err;
+
if (attrs[XFRMA_MIGRATE] == NULL)
return -EINVAL;
@@ -2254,6 +2262,11 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
{
struct net *net = &init_net;
struct sk_buff *skb;
+ int err;
+
+ err = verify_policy_dir(dir);
+ if (err)
+ return err;
skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
if (skb == NULL)
@@ -2882,6 +2895,11 @@ out_free_skb:
static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
{
+ int err;
+
+ err = verify_policy_dir(dir);
+ if (err)
+ return err;
switch (c->event) {
case XFRM_MSG_NEWPOLICY:
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index d449dde1bf5..7b5a7902b7a 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1248,6 +1248,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
struct snd_seq_client_port *port;
struct snd_seq_port_info info;
struct snd_seq_port_callback *callback;
+ int port_idx;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
@@ -1261,7 +1262,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
return -ENOMEM;
if (client->type == USER_CLIENT && info.kernel) {
- snd_seq_delete_port(client, port->addr.port);
+ port_idx = port->addr.port;
+ snd_seq_port_unlock(port);
+ snd_seq_delete_port(client, port_idx);
return -EINVAL;
}
if (client->type == KERNEL_CLIENT) {
@@ -1283,6 +1286,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
snd_seq_set_port_info(port, &info);
snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
+ snd_seq_port_unlock(port);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index ee0522a8f73..a28d1acad57 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
}
-/* create a port, port number is returned (-1 on failure) */
+/* create a port, port number is returned (-1 on failure);
+ * the caller needs to unref the port via snd_seq_port_unlock() appropriately
+ */
struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
int port)
{
@@ -153,6 +155,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
snd_use_lock_init(&new_port->use_lock);
port_subs_info_init(&new_port->c_src);
port_subs_info_init(&new_port->c_dest);
+ snd_use_lock_use(&new_port->use_lock);
num = port >= 0 ? port : 0;
mutex_lock(&client->ports_mutex);
@@ -167,9 +170,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
list_add_tail(&new_port->list, &p->list);
client->num_ports++;
new_port->addr.port = num; /* store the port number in the port */
+ sprintf(new_port->name, "port-%d", num);
write_unlock_irqrestore(&client->ports_lock, flags);
mutex_unlock(&client->ports_mutex);
- sprintf(new_port->name, "port-%d", num);
return new_port;
}
diff --git a/sound/soc/msm/qdsp6v2/audio_calibration.c b/sound/soc/msm/qdsp6v2/audio_calibration.c
index c8806481ed0..8daf47be171 100644
--- a/sound/soc/msm/qdsp6v2/audio_calibration.c
+++ b/sound/soc/msm/qdsp6v2/audio_calibration.c
@@ -457,6 +457,12 @@ static long audio_cal_shared_ioctl(struct file *file, unsigned int cmd,
data->cal_type.cal_hdr.buffer_number);
ret = -EINVAL;
goto done;
+ } else if ((data->hdr.cal_type_size + sizeof(data->hdr)) > size) {
+ pr_err("%s: cal type hdr size %zd + cal type size %d is greater than user buffer size %d\n",
+ __func__, sizeof(data->hdr), data->hdr.cal_type_size,
+ size);
+ ret = -EFAULT;
+ goto done;
}
@@ -494,13 +500,7 @@ static long audio_cal_shared_ioctl(struct file *file, unsigned int cmd,
goto unlock;
if (data == NULL)
goto unlock;
- if ((sizeof(data->hdr) + data->hdr.cal_type_size) > size) {
- pr_err("%s: header size %zd plus cal type size %d are greater than data buffer size %d\n",
- __func__, sizeof(data->hdr),
- data->hdr.cal_type_size, size);
- ret = -EFAULT;
- goto unlock;
- } else if (copy_to_user((void *)arg, data,
+ if (copy_to_user(arg, data,
sizeof(data->hdr) + data->hdr.cal_type_size)) {
pr_err("%s: Could not copy cal type to user\n",
__func__);