diff options
| author | Ali Al-Asadi <alasadi56@gmail.com> | 2017-11-20 19:16:17 +0100 |
|---|---|---|
| committer | Ali Al-Asadi <alasadi56@gmail.com> | 2017-11-20 19:17:37 +0100 |
| commit | fbe6feeff76b5b11031a95c38f49125d979a310f (patch) | |
| tree | e6673c1faefaaa03ccee9580add98738bffa3c8c | |
| parent | ac647004adb3fa02d0900825aaffcaff496fafdc (diff) | |
| parent | 4d3a6849e576efbedc83a59095eecf305a57b1a2 (diff) | |
Merge https://github.com/LineageOS/android_kernel_motorola_msm8952 into n7.1n7.1
Change-Id: I0ff4601ef70e26a89871b5c200749e79569b6494
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(¤t->mm->mmap_sem); if (ia->ia_valid & ATTR_SIZE) { err = inode_newsize_ok(&tmp, ia->ia_size); if (err) { - if (current->mm) - up_write(¤t->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(¤t->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__); |
