From 08c52f8474ad4dbae32a255f238e38f2f724331e Mon Sep 17 00:00:00 2001 From: Balvinder Singh Date: Mon, 6 Nov 2017 11:50:46 +0530 Subject: [PATCH 01/45] [Bluetooth] - Fix for checking proper user-supplied buffers During patch download of devices, size validations & zero alloc the buffers to ensure values passed are in range CRs-fixed: 2084692 Change-Id: Ie1cd76fe68766d6d12d7262202e48c18ebe42274 Signed-off-by: Balvinder Singh Signed-off-by: Yasir Malik --- drivers/bluetooth/ath3k.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 4119a491ccd8..93bfa47b225a 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -213,13 +213,27 @@ static int ath3k_load_firmware(struct usb_device *udev, { u8 *send_buf; int err, pipe, len, size, sent = 0; - int count = firmware->size; + int count; BT_DBG("udev %p", udev); + if (!firmware || !firmware->data || firmware->size <= 0) { + err = -EINVAL; + BT_ERR("Not a valid FW file"); + return err; + } + + count = firmware->size; + + if (count < FW_HDR_SIZE) { + err = -EINVAL; + BT_ERR("ath3k loading invalid size of file"); + return err; + } + pipe = usb_sndctrlpipe(udev, 0); - send_buf = kmalloc(BULK_SIZE, GFP_KERNEL); + send_buf = kzalloc(BULK_SIZE, GFP_KERNEL); if (!send_buf) { BT_ERR("Can't allocate memory chunk for firmware"); return -ENOMEM; From 8e4f17c71f3e73b96e4cf5d405068b8d80d9edee Mon Sep 17 00:00:00 2001 From: Sreelakshmi Gownipalli Date: Mon, 18 Sep 2017 12:41:47 -0700 Subject: [PATCH 02/45] diag: Free the memory in diagfwd_peripheral_exit() In diagfwd_peripheral_exit() free the memory associated with early_init_info. Change-Id: I862b6d806d67dad38316f1608827a4bf6f5a691f Signed-off-by: Sreelakshmi Gownipalli --- drivers/char/diag/diagfwd_peripheral.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index 4da627d99c62..4b0fe68ca9fb 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -477,6 +477,7 @@ void diagfwd_peripheral_exit(void) uint8_t peripheral; uint8_t type; struct diagfwd_info *fwd_info = NULL; + int transport = 0; diag_smd_exit(); diag_socket_exit(); @@ -499,7 +500,10 @@ void diagfwd_peripheral_exit(void) driver->diagfwd_dci_cmd[peripheral] = NULL; } - kfree(early_init_info); + for (transport = 0; transport < NUM_TRANSPORT; transport++) { + kfree(early_init_info[transport]); + early_init_info[transport] = NULL; + } } int diagfwd_cntl_register(uint8_t transport, uint8_t peripheral, void *ctxt, From 51e74102184f378a267a5702e5f5582c850dddfb Mon Sep 17 00:00:00 2001 From: Sai Krishna Juturi Date: Wed, 22 Nov 2017 16:40:18 +0530 Subject: [PATCH 03/45] net: usb: rmnet_usb_ctrl: Fix use after free issue In rmnet_usb_ctrl_init dev is freed again it is dereferenced with in same block. Fix this issue by taking derefernced value into a local variable prior to freeing dev. Change-Id: Ic51accc8949e97c8aaeda558adcc9d404fb2a26d Signed-off-by: Sai Krishna Juturi --- drivers/net/usb/rmnet_usb_ctrl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c index 75e97832efa2..25ebe1361efd 100644 --- a/drivers/net/usb/rmnet_usb_ctrl.c +++ b/drivers/net/usb/rmnet_usb_ctrl.c @@ -1219,12 +1219,13 @@ skip_cudev_init: "%s%d", rmnet_dev_names[i], n); if (IS_ERR(dev->devicep)) { + long status = PTR_ERR(dev->devicep); pr_err("%s: device_create() returned %ld\n", - __func__, PTR_ERR(dev->devicep)); + __func__, status); cdev_del(&dev->cdev); free_rmnet_ctrl_udev(dev->cudev); kfree(dev); - return PTR_ERR(dev->devicep); + return status; } /*create /sys/class/hsicctl/hsicctlx/modem_wait*/ From 3c4adc243eca3378ff927d2bbaebbb8bf2e0f957 Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Mon, 17 Apr 2017 19:40:24 +0530 Subject: [PATCH 04/45] wcnss: fix the buffer overflow in MAC address store sysfs Invalid typecast in MAC address store sysfs entry method causing device crash due to the buffer overflow. To fix the above issue check the length of the userspace MAC address before write. Update the datatype and parsing method to store the userspace MAC address. CRs-Fixed: 2034549 Change-Id: I0d4709c5b623c8333a99991c042552df1e7da923 Signed-off-by: Sarada Prasanna Garnayak --- drivers/net/wireless/wcnss/wcnss_wlan.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index 97cafd39dec5..6961fc5be9f0 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -187,6 +187,8 @@ static DEFINE_SPINLOCK(reg_spinlock); #define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3) #define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" +#define SHOW_MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x\n" +#define WCNSS_USER_MAC_ADDR_LENGTH 18 /* message types */ #define WCNSS_CTRL_MSG_START 0x01000000 @@ -430,23 +432,28 @@ static struct { static ssize_t wcnss_wlan_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - char macAddr[WLAN_MAC_ADDR_SIZE]; + int index; + int macAddr[WLAN_MAC_ADDR_SIZE]; if (!penv) return -ENODEV; - pr_debug("%s: Receive MAC Addr From user space: %s\n", __func__, buf); + if (WCNSS_USER_MAC_ADDR_LENGTH != strlen(buf)) { + dev_err(dev, "%s: Invalid MAC addr length\n", __func__); + return -EINVAL; + } if (WLAN_MAC_ADDR_SIZE != sscanf(buf, MAC_ADDRESS_STR, - (int *)&macAddr[0], (int *)&macAddr[1], - (int *)&macAddr[2], (int *)&macAddr[3], - (int *)&macAddr[4], (int *)&macAddr[5])) { - + &macAddr[0], &macAddr[1], &macAddr[2], + &macAddr[3], &macAddr[4], &macAddr[5])) { pr_err("%s: Failed to Copy MAC\n", __func__); return -EINVAL; } - memcpy(penv->wlan_nv_macAddr, macAddr, sizeof(penv->wlan_nv_macAddr)); + for (index = 0; index < WLAN_MAC_ADDR_SIZE; index++) { + memcpy(&penv->wlan_nv_macAddr[index], + (char *)&macAddr[index], sizeof(char)); + } pr_info("%s: Write MAC Addr:" MAC_ADDRESS_STR "\n", __func__, penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1], @@ -462,7 +469,7 @@ static ssize_t wcnss_wlan_macaddr_show(struct device *dev, if (!penv) return -ENODEV; - return scnprintf(buf, PAGE_SIZE, MAC_ADDRESS_STR, + return scnprintf(buf, PAGE_SIZE, SHOW_MAC_ADDRESS_STR, penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1], penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3], penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]); From fee040aaa17f68a061ecb1a308b652c62a6104ff Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Tue, 14 Nov 2017 18:59:34 +0530 Subject: [PATCH 05/45] msm: sps: Update debug message format specifier Restrict printing of kernel virtual addresses in SPS driver. In debug code, %p is used to print virtual addresses of kernel objects, which can be exploited by attackers. It is replaced with %pK, which hides these values if kptr_restrict is set (default on Android). Change-Id: I57585fa655abc01b2e8d694c8f31b7617bbf4ec7 Signed-off-by: Jishnu Prakash --- drivers/platform/msm/sps/bam.c | 110 ++++++++++++++--------------- drivers/platform/msm/sps/sps.c | 4 +- drivers/platform/msm/sps/sps_bam.c | 8 +-- drivers/platform/msm/sps/sps_mem.c | 5 +- drivers/platform/msm/sps/sps_rm.c | 7 +- 5 files changed, 67 insertions(+), 67 deletions(-) diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c index e3b38fb9c5f8..7aefdcb5827d 100644 --- a/drivers/platform/msm/sps/bam.c +++ b/drivers/platform/msm/sps/bam.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -707,7 +707,7 @@ static inline u32 bam_get_register_offset(void *base, enum bam_regs reg, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } @@ -756,7 +756,7 @@ static inline u32 bam_read_reg(void *base, enum bam_regs reg, u32 param) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } @@ -767,7 +767,7 @@ static inline u32 bam_read_reg(void *base, enum bam_regs reg, u32 param) return offset; } val = ioread32(dev->base + offset); - SPS_DBG(dev, "sps:bam 0x%p(va) offset 0x%x reg 0x%x r_val 0x%x.\n", + SPS_DBG(dev, "sps:bam 0x%pK(va) offset 0x%x reg 0x%x r_val 0x%x.\n", dev->base, offset, reg, val); return val; } @@ -788,7 +788,7 @@ static inline u32 bam_read_reg_field(void *base, enum bam_regs reg, u32 param, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } @@ -802,7 +802,7 @@ static inline u32 bam_read_reg_field(void *base, enum bam_regs reg, u32 param, val = ioread32(dev->base + offset); val &= mask; /* clear other bits */ val >>= shift; - SPS_DBG(dev, "sps:bam 0x%p(va) read reg 0x%x mask 0x%x r_val 0x%x.\n", + SPS_DBG(dev, "sps:bam 0x%pK(va) read reg 0x%x mask 0x%x r_val 0x%x.\n", dev->base, offset, mask, val); return val; } @@ -823,7 +823,7 @@ static inline void bam_write_reg(void *base, enum bam_regs reg, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } @@ -834,7 +834,7 @@ static inline void bam_write_reg(void *base, enum bam_regs reg, return; } iowrite32(val, dev->base + offset); - SPS_DBG(dev, "sps:bam 0x%p(va) write reg 0x%x w_val 0x%x.\n", + SPS_DBG(dev, "sps:bam 0x%pK(va) write reg 0x%x w_val 0x%x.\n", dev->base, offset, val); } @@ -854,7 +854,7 @@ static inline void bam_write_reg_field(void *base, enum bam_regs reg, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } @@ -870,7 +870,7 @@ static inline void bam_write_reg_field(void *base, enum bam_regs reg, tmp &= ~mask; /* clear written bits */ val = tmp | (val << shift); iowrite32(val, dev->base + offset); - SPS_DBG(dev, "sps:bam 0x%p(va) write reg 0x%x w_val 0x%x.\n", + SPS_DBG(dev, "sps:bam 0x%pK(va) write reg 0x%x w_val 0x%x.\n", dev->base, offset, val); } @@ -888,28 +888,28 @@ int bam_init(void *base, u32 ee, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } - SPS_DBG3(dev, "sps:%s:bam=%pa 0x%p(va).ee=%d.", __func__, + SPS_DBG3(dev, "sps:%s:bam=%pa 0x%pK(va).ee=%d.", __func__, BAM_ID(dev), dev->base, ee); ver = bam_read_reg_field(base, REVISION, 0, BAM_REVISION); if ((ver < BAM_MIN_VERSION) || (ver > BAM_MAX_VERSION)) { - SPS_ERR(dev, "sps:bam 0x%p(va) Invalid BAM REVISION 0x%x.\n", + SPS_ERR(dev, "sps:bam 0x%pK(va) Invalid BAM REVISION 0x%x.\n", dev->base, ver); return -ENODEV; } else - SPS_DBG(dev, "sps:REVISION of BAM 0x%p is 0x%x.\n", + SPS_DBG(dev, "sps:REVISION of BAM 0x%pK is 0x%x.\n", dev->base, ver); if (summing_threshold == 0) { summing_threshold = 4; SPS_ERR(dev, - "sps:bam 0x%p(va) summing_threshold is zero,use default 4.\n", + "sps:bam 0x%pK(va) summing_threshold is zero,use default 4.\n", dev->base); } @@ -1009,12 +1009,12 @@ int bam_security_init(void *base, u32 ee, u32 vmid, u32 pipe_mask) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } - SPS_DBG3(dev, "sps:%s:bam=%pa 0x%p(va).", __func__, + SPS_DBG3(dev, "sps:%s:bam=%pa 0x%pK(va).", __func__, BAM_ID(dev), dev->base); /* @@ -1025,14 +1025,14 @@ int bam_security_init(void *base, u32 ee, u32 vmid, u32 pipe_mask) num_pipes = bam_read_reg_field(base, NUM_PIPES, 0, BAM_NUM_PIPES); if (version < 3 || version > 0x1F) { SPS_ERR(dev, - "sps:bam 0x%p(va) security is not supported for this BAM version 0x%x.\n", + "sps:bam 0x%pK(va) security is not supported for this BAM version 0x%x.\n", dev->base, version); return -ENODEV; } if (num_pipes > BAM_MAX_PIPES) { SPS_ERR(dev, - "sps:bam 0x%p(va) the number of pipes is more than the maximum number allowed.\n", + "sps:bam 0x%pK(va) the number of pipes is more than the maximum number allowed.\n", dev->base); return -ENODEV; } @@ -1080,12 +1080,12 @@ int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } - SPS_DBG3(dev, "sps:%s:bam=%pa 0x%p(va).", + SPS_DBG3(dev, "sps:%s:bam=%pa 0x%pK(va).", __func__, BAM_ID(dev), dev->base); if (!enhd_pipe) @@ -1094,7 +1094,7 @@ int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes) enabled = bam_get_pipe_attr(base, ee, true); if (!enabled) { - SPS_ERR(dev, "sps:%s:bam 0x%p(va) is not enabled.\n", + SPS_ERR(dev, "sps:%s:bam 0x%pK(va) is not enabled.\n", __func__, dev->base); return -ENODEV; } @@ -1110,7 +1110,7 @@ int bam_check(void *base, u32 *version, u32 ee, u32 *num_pipes) /* Check BAM version */ if ((ver < BAM_MIN_VERSION) || (ver > BAM_MAX_VERSION)) { - SPS_ERR(dev, "sps:%s:bam 0x%p(va) Invalid BAM version 0x%x.\n", + SPS_ERR(dev, "sps:%s:bam 0x%pK(va) Invalid BAM version 0x%x.\n", __func__, dev->base, ver); return -ENODEV; } @@ -1127,11 +1127,11 @@ void bam_exit(void *base, u32 ee) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG3(dev, "sps:%s:bam=%pa 0x%p(va).ee=%d.", + SPS_DBG3(dev, "sps:%s:bam=%pa 0x%pK(va).ee=%d.", __func__, BAM_ID(dev), dev->base, ee); bam_write_reg_field(base, IRQ_SRCS_MSK_EE, ee, BAM_IRQ, 0); @@ -1155,7 +1155,7 @@ void bam_output_register_content(void *base, u32 ee) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } @@ -1166,7 +1166,7 @@ void bam_output_register_content(void *base, u32 ee) num_pipes = bam_read_reg_field(base, NUM_PIPES, 0, BAM_NUM_PIPES); - SPS_INFO(dev, "sps:bam %pa 0x%p(va) has %d pipes.", + SPS_INFO(dev, "sps:bam %pa 0x%pK(va) has %d pipes.", BAM_ID(dev), dev->base, num_pipes); pipe_attr = enhd_pipe ? @@ -1193,7 +1193,7 @@ u32 bam_check_irq_source(void *base, u32 ee, u32 mask, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } @@ -1205,13 +1205,13 @@ u32 bam_check_irq_source(void *base, u32 ee, u32 mask, status = bam_read_reg(base, IRQ_STTS, 0); if (status & IRQ_STTS_BAM_ERROR_IRQ) { - SPS_ERR(dev, "sps:bam %pa 0x%p(va);bam irq status=" + SPS_ERR(dev, "sps:bam %pa 0x%pK(va);bam irq status=" "0x%x.\nsps: BAM_ERROR_IRQ\n", BAM_ID(dev), dev->base, status); bam_output_register_content(base, ee); *cb_case = SPS_CALLBACK_BAM_ERROR_IRQ; } else if (status & IRQ_STTS_BAM_HRESP_ERR_IRQ) { - SPS_ERR(dev, "sps:bam %pa 0x%p(va);bam irq status=" + SPS_ERR(dev, "sps:bam %pa 0x%pK(va);bam irq status=" "0x%x.\nsps: BAM_HRESP_ERR_IRQ\n", BAM_ID(dev), dev->base, status); bam_output_register_content(base, ee); @@ -1219,13 +1219,13 @@ u32 bam_check_irq_source(void *base, u32 ee, u32 mask, #ifdef CONFIG_SPS_SUPPORT_NDP_BAM } else if (status & IRQ_STTS_BAM_TIMER_IRQ) { SPS_DBG1(dev, - "sps:bam 0x%p(va);receive BAM_TIMER_IRQ\n", + "sps:bam 0x%pK(va);receive BAM_TIMER_IRQ\n", dev->base); *cb_case = SPS_CALLBACK_BAM_TIMER_IRQ; #endif } else SPS_INFO(dev, - "sps:bam %pa 0x%p(va);bam irq status=0x%x.\n", + "sps:bam %pa 0x%pK(va);bam irq status=0x%x.\n", BAM_ID(dev), dev->base, status); bam_write_reg(base, IRQ_CLR, 0, status); @@ -1243,11 +1243,11 @@ void bam_pipe_reset(void *base, u32 pipe) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG2(dev, "sps:%s:bam=%pa 0x%p(va).pipe=%d.", + SPS_DBG2(dev, "sps:%s:bam=%pa 0x%pK(va).pipe=%d.", __func__, BAM_ID(dev), dev->base, pipe); bam_write_reg(base, P_RST, pipe, 1); @@ -1264,11 +1264,11 @@ void bam_disable_pipe(void *base, u32 pipe) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG2(dev, "sps:%s:bam=0x%p(va).pipe=%d.", __func__, base, pipe); + SPS_DBG2(dev, "sps:%s:bam=0x%pK(va).pipe=%d.", __func__, base, pipe); bam_write_reg_field(base, P_CTRL, pipe, P_EN, 0); wmb(); /* ensure pipe is disabled */ } @@ -1281,20 +1281,20 @@ bool bam_pipe_check_zlt(void *base, u32 pipe) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return false; } if (bam_read_reg_field(base, P_HALT, pipe, P_HALT_P_LAST_DESC_ZLT)) { SPS_DBG(dev, - "sps:%s:bam=0x%p(va).pipe=%d: the last desc is ZLT.", + "sps:%s:bam=0x%pK(va).pipe=%d: the last desc is ZLT.", __func__, base, pipe); return true; } SPS_DBG(dev, - "sps:%s:bam=0x%p(va).pipe=%d: the last desc is not ZLT.", + "sps:%s:bam=0x%pK(va).pipe=%d: the last desc is not ZLT.", __func__, base, pipe); return false; } @@ -1307,20 +1307,20 @@ bool bam_pipe_check_pipe_empty(void *base, u32 pipe) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return false; } if (bam_read_reg_field(base, P_HALT, pipe, P_HALT_P_PIPE_EMPTY)) { SPS_DBG(dev, - "sps:%s:bam=0x%p(va).pipe=%d: desc FIFO is empty.", + "sps:%s:bam=0x%pK(va).pipe=%d: desc FIFO is empty.", __func__, base, pipe); return true; } SPS_DBG(dev, - "sps:%s:bam=0x%p(va).pipe=%d: desc FIFO is not empty.", + "sps:%s:bam=0x%pK(va).pipe=%d: desc FIFO is not empty.", __func__, base, pipe); return false; } @@ -1334,11 +1334,11 @@ int bam_pipe_init(void *base, u32 pipe, struct bam_pipe_parameters *param, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return SPS_ERROR; } - SPS_DBG2(dev, "sps:%s:bam=%pa 0x%p(va).pipe=%d.", + SPS_DBG2(dev, "sps:%s:bam=%pa 0x%pK(va).pipe=%d.", __func__, BAM_ID(dev), dev->base, pipe); /* Reset the BAM pipe */ @@ -1372,7 +1372,7 @@ int bam_pipe_init(void *base, u32 pipe, struct bam_pipe_parameters *param, bam_write_reg_field(base, P_CTRL, pipe, P_LOCK_GROUP, param->lock_group); - SPS_DBG(dev, "sps:bam=0x%p(va).pipe=%d.lock_group=%d.\n", + SPS_DBG(dev, "sps:bam=0x%pK(va).pipe=%d.lock_group=%d.\n", dev->base, pipe, param->lock_group); #endif @@ -1388,7 +1388,7 @@ int bam_pipe_init(void *base, u32 pipe, struct bam_pipe_parameters *param, bam_write_reg(base, P_EVNT_DEST_ADDR, pipe, peer_dest_addr); - SPS_DBG2(dev, "sps:bam=0x%p(va).pipe=%d.peer_bam=0x%x." + SPS_DBG2(dev, "sps:bam=0x%pK(va).pipe=%d.peer_bam=0x%x." "peer_pipe=%d.\n", dev->base, pipe, (u32) param->peer_phys_addr, @@ -1424,11 +1424,11 @@ void bam_pipe_exit(void *base, u32 pipe, u32 ee) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG2(dev, "sps:%s:bam=%pa 0x%p(va).pipe=%d.", + SPS_DBG2(dev, "sps:%s:bam=%pa 0x%pK(va).pipe=%d.", __func__, BAM_ID(dev), dev->base, pipe); bam_write_reg(base, P_IRQ_EN, pipe, 0); @@ -1449,15 +1449,15 @@ void bam_pipe_enable(void *base, u32 pipe) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG2(dev, "sps:%s:bam=%pa 0x%p(va).pipe=%d.", + SPS_DBG2(dev, "sps:%s:bam=%pa 0x%pK(va).pipe=%d.", __func__, BAM_ID(dev), dev->base, pipe); if (bam_read_reg_field(base, P_CTRL, pipe, P_EN)) - SPS_DBG2(dev, "sps:bam=0x%p(va).pipe=%d is already enabled.\n", + SPS_DBG2(dev, "sps:bam=0x%pK(va).pipe=%d is already enabled.\n", dev->base, pipe); else bam_write_reg_field(base, P_CTRL, pipe, P_EN, 1); @@ -1472,11 +1472,11 @@ void bam_pipe_disable(void *base, u32 pipe) struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG2(dev, "sps:%s:bam=%pa 0x%p(va).pipe=%d.", + SPS_DBG2(dev, "sps:%s:bam=%pa 0x%pK(va).pipe=%d.", __func__, BAM_ID(dev), dev->base, pipe); bam_write_reg_field(base, P_CTRL, pipe, P_EN, 0); @@ -1501,11 +1501,11 @@ void bam_pipe_set_irq(void *base, u32 pipe, enum bam_enable irq_en, struct sps_bam *dev = to_sps_bam_dev(base); if ((dev == NULL) || (&dev->base != base)) { - SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%p\n", + SPS_ERR(sps, "%s:Failed to get dev for base addr 0x%pK\n", __func__, base); return; } - SPS_DBG2(dev, "sps:%s:bam=%pa 0x%p(va).pipe=%d.", + SPS_DBG2(dev, "sps:%s:bam=%pa 0x%pK(va).pipe=%d.", __func__, BAM_ID(dev), dev->base, pipe); if (src_mask & BAM_PIPE_IRQ_RST_ERROR) { if (enhd_pipe) diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c index 061e15212d6a..36f87f59ebdd 100644 --- a/drivers/platform/msm/sps/sps.c +++ b/drivers/platform/msm/sps/sps.c @@ -912,7 +912,7 @@ static int sps_device_init(void) goto exit_err; } - SPS_DBG3(sps, "sps:bamdma_bam.phys=%pa.virt=0x%p.", + SPS_DBG3(sps, "sps:bamdma_bam.phys=%pa.virt=0x%pK.", &bamdma_props.phys_addr, bamdma_props.virt_addr); @@ -927,7 +927,7 @@ static int sps_device_init(void) goto exit_err; } - SPS_DBG3(sps, "sps:bamdma_dma.phys=%pa.virt=0x%p.", + SPS_DBG3(sps, "sps:bamdma_dma.phys=%pa.virt=0x%pK.", &bamdma_props.periph_phys_addr, bamdma_props.periph_virt_addr); diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c index b6a157947f28..e76e79521ce7 100644 --- a/drivers/platform/msm/sps/sps_bam.c +++ b/drivers/platform/msm/sps/sps_bam.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -495,12 +495,12 @@ int sps_bam_enable(struct sps_bam *dev) if (dev->props.logging_number > 0) dev->props.logging_number--; SPS_INFO(dev, - "sps:BAM %pa (va:0x%p) enabled: ver:0x%x, number of pipes:%d\n", + "sps:BAM %pa (va:0x%pK) enabled: ver:0x%x, number of pipes:%d\n", BAM_ID(dev), dev->base, dev->version, dev->props.num_pipes); } else SPS_DBG3(dev, - "sps:BAM %pa (va:0x%p) enabled: ver:0x%x, number of pipes:%d\n", + "sps:BAM %pa (va:0x%pK) enabled: ver:0x%x, number of pipes:%d\n", BAM_ID(dev), dev->base, dev->version, dev->props.num_pipes); @@ -2075,7 +2075,7 @@ int sps_bam_pipe_get_event(struct sps_bam *dev, if (pipe->sys.no_queue) { SPS_ERR(dev, - "sps:Invalid connection for event: BAM %pa pipe %d context 0x%p\n", + "sps:Invalid connection for event: BAM %pa pipe %d context 0x%pK\n", BAM_ID(dev), pipe_index, pipe); notify->event_id = SPS_EVENT_INVALID; return SPS_ERROR; diff --git a/drivers/platform/msm/sps/sps_mem.c b/drivers/platform/msm/sps/sps_mem.c index becb9a15882a..db36e64f96d8 100644 --- a/drivers/platform/msm/sps/sps_mem.c +++ b/drivers/platform/msm/sps/sps_mem.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2011-2013, 2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, 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 @@ -129,7 +130,7 @@ int sps_mem_init(phys_addr_t pipemem_phys_base, u32 pipemem_size) iomem_offset = 0; SPS_DBG(sps, - "sps:sps_mem_init.iomem_phys=%pa,iomem_virt=0x%p.", + "sps:sps_mem_init.iomem_phys=%pa,iomem_virt=0x%pK.", &iomem_phys, iomem_virt); } diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c index ec64e6c25465..db5db28d5f9e 100644 --- a/drivers/platform/msm/sps/sps_rm.c +++ b/drivers/platform/msm/sps/sps_rm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-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 @@ -723,8 +723,7 @@ int sps_rm_state_change(struct sps_pipe *pipe, u32 state) state == SPS_STATE_ALLOCATE) { if (sps_rm_alloc(pipe)) { SPS_ERR(pipe->bam, - "sps:Fail to allocate resource for" - " BAM 0x%p pipe %d.\n", + "sps:Fail to allocate resource for BAM 0x%pK pipe %d.\n", pipe->bam, pipe->pipe_index); return SPS_ERROR; } @@ -745,7 +744,7 @@ int sps_rm_state_change(struct sps_pipe *pipe, u32 state) result = sps_bam_pipe_connect(pipe, ¶ms); if (result) { SPS_ERR(pipe->bam, - "sps:Failed to connect BAM 0x%p pipe %d", + "sps:Failed to connect BAM 0x%pK pipe %d", pipe->bam, pipe->pipe_index); return SPS_ERROR; } From d31d4288a73cca4721b22e4a66455f3dd4beeacb Mon Sep 17 00:00:00 2001 From: Robb Glasser Date: Fri, 24 Mar 2017 16:23:37 -0700 Subject: [PATCH 06/45] Prevent potential double frees in sg driver sg_ioctl could be spammed by requests, leading to a double free in __free_pages. This protects the entry points of sg_ioctl where the memory could be corrupted by a double call to __free_pages if multiple requests are happening concurrently. Bug:35644812 Change-Id: Ie13f65beb6974430f90292e2742841b26aecb8b1 Signed-off-by: Robb Glasser Git-commit: 22d8e80738b5ce8784d59b48b0b051a520da4bec Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-3.10/commit Signed-off-by: Sayali Lokhande --- drivers/scsi/sg.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index eb81c98386b9..1af1865c7c08 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -170,6 +170,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ typedef struct sg_device { /* holds the state of each scsi generic device */ struct scsi_device *device; + struct mutex open_rel_lock; wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ int sg_tablesize; /* adapter's max scatter-gather table size */ u32 index; /* device index number */ @@ -486,7 +487,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) old_hdr->result = EIO; break; case DID_ERROR: - old_hdr->result = (srp->sense_b[0] == 0 && + old_hdr->result = (srp->sense_b[0] == 0 && hp->masked_status == GOOD) ? 0 : EIO; break; default: @@ -832,8 +833,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return -ENXIO; if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) return -EFAULT; + mutex_lock(&sfp->parentdp->open_rel_lock); result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, 1, read_only, 1, &srp); + mutex_unlock(&sfp->parentdp->open_rel_lock); if (result < 0) return result; result = wait_event_interruptible(sfp->read_wait, @@ -873,8 +876,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) sfp->low_dma = 1; if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { val = (int) sfp->reserve.bufflen; + mutex_lock(&sfp->parentdp->open_rel_lock); sg_remove_scat(&sfp->reserve); sg_build_reserve(sfp, val); + mutex_unlock(&sfp->parentdp->open_rel_lock); } } else { if (sdp->detached) @@ -942,15 +947,17 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) result = get_user(val, ip); if (result) return result; - if (val < 0) - return -EINVAL; + if (val < 0) + return -EINVAL; val = min_t(int, val, queue_max_sectors(sdp->device->request_queue) * 512); if (val != sfp->reserve.bufflen) { if (sg_res_in_use(sfp) || sfp->mmap_called) return -EBUSY; + mutex_lock(&sfp->parentdp->open_rel_lock); sg_remove_scat(&sfp->reserve); sg_build_reserve(sfp, val); + mutex_unlock(&sfp->parentdp->open_rel_lock); } return 0; case SG_GET_RESERVED_SIZE: @@ -1003,8 +1010,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if (srp) { rinfo[val].req_state = srp->done + 1; rinfo[val].problem = - srp->header.masked_status & - srp->header.host_status & + srp->header.masked_status & + srp->header.host_status & srp->header.driver_status; if (srp->done) rinfo[val].duration = @@ -1025,7 +1032,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) } } read_unlock_irqrestore(&sfp->rq_list_lock, iflags); - result = __copy_to_user(p, rinfo, + result = __copy_to_user(p, rinfo, SZ_SG_REQ_INFO * SG_MAX_QUEUE); result = result ? -EFAULT : 0; kfree(rinfo); @@ -1127,14 +1134,14 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon return -ENXIO; sdev = sdp->device; - if (sdev->host->hostt->compat_ioctl) { + if (sdev->host->hostt->compat_ioctl) { int ret; ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); return ret; } - + return -ENOIOCTLCMD; } #endif @@ -1415,6 +1422,7 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) disk->first_minor = k; sdp->disk = disk; sdp->device = scsidp; + mutex_init(&sdp->open_rel_lock); INIT_LIST_HEAD(&sdp->sfds); init_waitqueue_head(&sdp->o_excl_wait); sdp->sg_tablesize = queue_max_segments(q); @@ -1594,7 +1602,7 @@ init_sg(void) else def_reserved_size = sg_big_buff; - rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), + rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS, "sg"); if (rc) return rc; @@ -2231,7 +2239,7 @@ static const struct file_operations adio_fops = { }; static int sg_proc_single_open_dressz(struct inode *inode, struct file *file); -static ssize_t sg_proc_write_dressz(struct file *filp, +static ssize_t sg_proc_write_dressz(struct file *filp, const char __user *buffer, size_t count, loff_t *off); static const struct file_operations dressz_fops = { .owner = THIS_MODULE, @@ -2371,7 +2379,7 @@ static int sg_proc_single_open_adio(struct inode *inode, struct file *file) return single_open(file, sg_proc_seq_show_int, &sg_allow_dio); } -static ssize_t +static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer, size_t count, loff_t *off) { @@ -2392,7 +2400,7 @@ static int sg_proc_single_open_dressz(struct inode *inode, struct file *file) return single_open(file, sg_proc_seq_show_int, &sg_big_buff); } -static ssize_t +static ssize_t sg_proc_write_dressz(struct file *filp, const char __user *buffer, size_t count, loff_t *off) { @@ -2549,7 +2557,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) hp = &srp->header; new_interface = (hp->interface_id == '\0') ? 0 : 1; if (srp->res_used) { - if (new_interface && + if (new_interface && (SG_FLAG_MMAP_IO & hp->flags)) cp = " mmap>> "; else @@ -2563,7 +2571,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) seq_printf(s, cp); blen = srp->data.bufflen; usg = srp->data.k_use_sg; - seq_printf(s, srp->done ? + seq_printf(s, srp->done ? ((1 == srp->done) ? "rcv:" : "fin:") : "act:"); seq_printf(s, " id=%d blen=%d", From 8cbe6e6f2ddba3792f90fabd88bfcb9c4450b44e Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Sat, 3 Dec 2016 10:34:26 +0800 Subject: [PATCH 07/45] mmc: mmc-debugfs: add error state This change adds support to allow user space query if low level eMMC driver has encountered any error or not, this state can be read/cleared via debugfs. CRs-Fixed: 1056483 Change-Id: Idc4ea375e9f308446dec04d443d062fe502658bd Signed-off-by: Liangliang Lu --- drivers/mmc/core/debugfs.c | 31 +++++++++++++++++++++++++++++++ include/linux/mmc/host.h | 2 ++ 2 files changed, 33 insertions(+) diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 79d926bc455d..39fdb5c9584f 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -251,6 +251,33 @@ out: DEFINE_SIMPLE_ATTRIBUTE(mmc_max_clock_fops, mmc_max_clock_get, mmc_max_clock_set, "%llu\n"); +static int mmc_err_state_get(void *data, u64 *val) +{ + struct mmc_host *host = data; + + if (!host) + return -EINVAL; + + *val = host->err_occurred ? 1 : 0; + + return 0; +} + +static int mmc_err_state_clear(void *data, u64 val) +{ + struct mmc_host *host = data; + + if (!host) + return -EINVAL; + + host->err_occurred = false; + + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(mmc_err_state, mmc_err_state_get, + mmc_err_state_clear, "%llu\n"); + void mmc_add_host_debugfs(struct mmc_host *host) { struct dentry *root; @@ -277,6 +304,10 @@ void mmc_add_host_debugfs(struct mmc_host *host) &mmc_max_clock_fops)) goto err_node; + if (!debugfs_create_file("err_state", S_IRUSR | S_IWUSR, root, host, + &mmc_err_state)) + goto err_node; + #ifdef CONFIG_MMC_CLKGATE if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), root, &host->clk_delay)) diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index d38f025cc9f0..1cedeb3e1e55 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -473,6 +473,8 @@ struct mmc_host { struct dentry *debugfs_root; + bool err_occurred; + struct mmc_async_req *areq; /* active async req */ struct mmc_context_info context_info; /* async synchronization info */ From fefed65273a57527b290c8048133e226bcc8d124 Mon Sep 17 00:00:00 2001 From: Liangliang Lu Date: Wed, 21 Dec 2016 14:02:02 +0800 Subject: [PATCH 08/45] mmc: sdhci: add err_state to sdhci_dumpregs func This change sets err_state in sdhci_dumpregs func indicating driver errors captured, which can be read out from debugfs. CRs-Fixed: 1056483 Change-Id: If6323f4e2cf9c835139ea92753ae8407709b8a70 Signed-off-by: Liangliang Lu --- drivers/mmc/host/sdhci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1b72e9de35b8..c6aad4b1136a 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -172,6 +172,8 @@ static void sdhci_dumpregs(struct sdhci_host *host) readl(host->ioaddr + SDHCI_ADMA_ADDRESS_LOW)); } + host->mmc->err_occurred = true; + if (host->ops->dump_vendor_regs) host->ops->dump_vendor_regs(host); sdhci_dump_state(host); From 4353589c71ab6840dd015dc4aae655b7c24e2d02 Mon Sep 17 00:00:00 2001 From: Wang YanQing Date: Tue, 23 Jun 2015 18:38:54 +0800 Subject: [PATCH 09/45] time: Always make sure wall_to_monotonic isn't positive Two issues were found on an IMX6 development board without an enabled RTC device(resulting in the boot time and monotonic time being initialized to 0). Issue 1:exportfs -a generate: "exportfs: /opt/nfs/arm does not support NFS export" Issue 2:cat /proc/stat: "btime 4294967236" The same issues can be reproduced on x86 after running the following code: int main(void) { struct timeval val; int ret; val.tv_sec = 0; val.tv_usec = 0; ret = settimeofday(&val, NULL); return 0; } Two issues are different symptoms of same problem: The reason is a positive wall_to_monotonic pushes boot time back to the time before Epoch, and getboottime will return negative value. In symptom 1: negative boot time cause get_expiry() to overflow time_t when input expire time is 2147483647, then cache_flush() always clears entries just added in ip_map_parse. In symptom 2: show_stat() uses "unsigned long" to print negative btime value returned by getboottime. This patch fix the problem by prohibiting time from being set to a value which would cause a negative boot time. As a result one can't set the CLOCK_REALTIME time prior to (1970 + system uptime). Change-Id: I31c2093baf48f9cdef49a8ec515d6fb193de5ebc Cc: Prarit Bhargava Cc: Richard Cochran Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Wang YanQing [jstultz: reworded commit message] Signed-off-by: John Stultz Git-commit: e1d7ba8735551ed79c7a0463a042353574b96da3 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [neeraju@codeaurora.org: resolve merge conflicts] Signed-off-by: Neeraj Upadhyay --- kernel/time/timekeeping.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 76fefb1613b2..53bc7c6db4af 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -491,6 +491,7 @@ int do_settimeofday(const struct timespec *tv) struct timekeeper *tk = &timekeeper; struct timespec ts_delta, xt; unsigned long flags; + int ret = 0; if (!timespec_valid_strict(tv)) return -EINVAL; @@ -504,10 +505,15 @@ int do_settimeofday(const struct timespec *tv) ts_delta.tv_sec = tv->tv_sec - xt.tv_sec; ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec; + if (timespec_compare(&tk->wall_to_monotonic, &ts_delta) > 0) { + ret = -EINVAL; + goto out; + } + tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, ts_delta)); tk_set_xtime(tk, tv); - +out: timekeeping_update(tk, true, true); write_seqcount_end(&timekeeper_seq); @@ -516,7 +522,7 @@ int do_settimeofday(const struct timespec *tv) /* signal hrtimers about time change */ clock_was_set(); - return 0; + return ret; } EXPORT_SYMBOL(do_settimeofday); @@ -543,7 +549,8 @@ int timekeeping_inject_offset(struct timespec *ts) /* Make sure the proposed value is valid */ tmp = timespec_add(tk_xtime(tk), *ts); - if (!timespec_valid_strict(&tmp)) { + if (timespec_compare(&tk->wall_to_monotonic, ts) > 0 || + !timespec_valid_strict(&tmp)) { ret = -EINVAL; goto error; } From 75b11c7f007e4ed1ac340ab0d34f29e5a4d1a283 Mon Sep 17 00:00:00 2001 From: Manoj Prabhu B Date: Sat, 1 Jul 2017 10:01:11 +0530 Subject: [PATCH 10/45] diag: Clear masks upon logging exit This patch clears the peripheral masks upon the mdlog exit and USB disconnection. This enables to keep the data and cmd channel open for read. CRs-Fixed: 1057143 Change-Id: Ie6f19319b75f3bf389ddd5a8168fd3bcd3efbc8b Signed-off-by: Manoj Prabhu B --- drivers/char/diag/diag_masks.c | 11 +++++++++ drivers/char/diag/diag_usb.c | 8 ++++++- drivers/char/diag/diagchar.h | 3 +++ drivers/char/diag/diagchar_core.c | 38 +++++++++++++++++++++++++++++-- drivers/char/diag/diagfwd.c | 17 +++++++------- 5 files changed, 65 insertions(+), 12 deletions(-) diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 0103283a203d..95d1aacd1062 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -20,6 +20,7 @@ #include "diagfwd_cntl.h" #include "diag_masks.h" #include "diagfwd_peripheral.h" +#include "diag_ipc_logging.h" #define ALL_EQUIP_ID 100 #define ALL_SSID -1 @@ -1464,6 +1465,16 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count) if (!buf || count == 0) return -EINVAL; + + mutex_lock(&driver->diag_maskclear_mutex); + if (driver->mask_clear) { + DIAG_LOG(DIAG_DEBUG_USERSPACE, + "diag:%s: count = %zu\n", __func__, count); + mutex_unlock(&driver->diag_maskclear_mutex); + return -EIO; + } + mutex_unlock(&driver->diag_maskclear_mutex); + mutex_lock(&driver->msg_mask_lock); mutex_lock(&msg_mask.lock); mask = (struct diag_msg_mask_t *)(msg_mask.ptr); diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c index 1785168cf3cf..63ccbdeef363 100644 --- a/drivers/char/diag/diag_usb.c +++ b/drivers/char/diag/diag_usb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-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 @@ -215,6 +215,12 @@ static void usb_connect_work_fn(struct work_struct *work) */ static void usb_disconnect(struct diag_usb_info *ch) { + if (!ch) + return; + + if (!atomic_read(&ch->connected) && driver->usb_connected) + diag_clear_masks(); + if (ch && ch->ops && ch->ops->close) ch->ops->close(ch->ctxt, DIAG_USB_MODE); } diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 491f4fa3a14f..3d8a6c0c6ce1 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -432,6 +432,8 @@ struct diagchar_dev { struct class *diagchar_class; struct device *diag_dev; int ref_count; + int mask_clear; + struct mutex diag_maskclear_mutex; struct mutex diagchar_mutex; struct mutex diag_file_mutex; wait_queue_head_t wait_q; @@ -579,6 +581,7 @@ void diag_ws_on_copy_complete(int type); void diag_ws_reset(int type); void diag_ws_release(void); void chk_logging_wakeup(void); +void diag_clear_masks(void); int diag_cmd_add_reg(struct diag_cmd_reg_entry_t *new_entry, uint8_t proc, int pid); struct diag_cmd_reg_entry_t *diag_cmd_search( diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index faa07c92fbc9..9bb96045991c 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -354,6 +354,27 @@ fail: return -ENOMEM; } +void diag_clear_masks(void) +{ + int ret; + char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0}; + char cmd_disable_msg_mask[] = { 0x7D, 0x05, 0, 0, 0, 0, 0, 0}; + char cmd_disable_event_mask[] = { 0x60, 0}; + + DIAG_LOG(DIAG_DEBUG_USERSPACE, + "diag: %s: masks clear request upon USB Disconnection\n", + __func__); + + ret = diag_process_apps_masks(cmd_disable_log_mask, + sizeof(cmd_disable_log_mask)); + ret = diag_process_apps_masks(cmd_disable_msg_mask, + sizeof(cmd_disable_msg_mask)); + ret = diag_process_apps_masks(cmd_disable_event_mask, + sizeof(cmd_disable_event_mask)); + DIAG_LOG(DIAG_DEBUG_USERSPACE, + "diag:%s: masks cleared successfully\n", __func__); +} + static void diag_close_logging_process(int pid) { uint8_t i; @@ -426,6 +447,11 @@ static void diag_close_logging_process(int pid) break; } } + diag_clear_masks(); + + mutex_lock(&driver->diag_maskclear_mutex); + driver->mask_clear = 1; + mutex_unlock(&driver->diag_maskclear_mutex); if (switch_flag) { diag_switch_logging(USB_MODE); @@ -502,8 +528,15 @@ static int diag_remove_client_entry(struct file *file) } static int diagchar_close(struct inode *inode, struct file *file) { - DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n", current->comm); - return diag_remove_client_entry(file); + int ret; + + DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n", + current->comm); + ret = diag_remove_client_entry(file); + mutex_lock(&driver->diag_maskclear_mutex); + driver->mask_clear = 0; + mutex_unlock(&driver->diag_maskclear_mutex); + return ret; } void diag_record_stats(int type, int flag) @@ -3022,6 +3055,7 @@ static int __init diagchar_init(void) non_hdlc_data.len = 0; mutex_init(&driver->hdlc_disable_mutex); mutex_init(&driver->diagchar_mutex); + mutex_init(&driver->diag_maskclear_mutex); mutex_init(&driver->diag_file_mutex); mutex_init(&driver->delayed_rsp_mutex); mutex_init(&apps_data_mutex); diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index a25b93c26850..ef77416bb9b6 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -1170,8 +1170,6 @@ static int diagfwd_mux_open(int id, int mode) static int diagfwd_mux_close(int id, int mode) { - uint8_t i; - switch (mode) { case DIAG_USB_MODE: driver->usb_connected = 0; @@ -1187,15 +1185,16 @@ static int diagfwd_mux_close(int id, int mode) (mode == DIAG_MEMORY_DEVICE_MODE && driver->logging_mode == USB_MODE)) { /* - * In this case the channel must not be closed. This case - * indicates that the USB is removed but there is a client - * running in background with Memory Device mode + * This case indicates that the USB is removed + * but there is a client running in background + * with Memory Device mode. */ } else { - for (i = 0; i < NUM_PERIPHERALS; i++) { - diagfwd_close(i, TYPE_DATA); - diagfwd_close(i, TYPE_CMD); - } + /* + * With clearing of masks on ODL exit and + * USB disconnection, closing of the channel is + * not needed.This enables read and drop of stale packets. + */ /* Re enable HDLC encoding */ pr_debug("diag: In %s, re-enabling HDLC encoding\n", __func__); From faee7b6dcedeabeaf692bcdef43812aa42ed1c5c Mon Sep 17 00:00:00 2001 From: Raghavendra Kakarla Date: Thu, 21 Dec 2017 16:24:31 +0530 Subject: [PATCH 11/45] oc: qcom: rpm-smd-debug: Fix potential memory leaks Fix memory leak due to rpm request not freed during error conditions. Change-Id: I440a58bf452e76c8886f7bcd8f89b24698a301e9 Signed-off-by: Raghavendra Kakarla --- drivers/soc/qcom/rpm-smd-debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/qcom/rpm-smd-debug.c b/drivers/soc/qcom/rpm-smd-debug.c index 1c0a05c87eda..8194fe0cda5b 100644 --- a/drivers/soc/qcom/rpm-smd-debug.c +++ b/drivers/soc/qcom/rpm-smd-debug.c @@ -99,23 +99,23 @@ static ssize_t rsc_ops_write(struct file *fp, const char __user *user_buffer, cmp += pos; if (sscanf(cmp, "%5s %n", key_str, &pos) != 1) { pr_err("Invalid number of arguments passed\n"); - goto err; + goto err_request; } if (strlen(key_str) > 4) { pr_err("Key value cannot be more than 4 charecters"); - goto err; + goto err_request; } key = string_to_uint(key_str); if (!key) { pr_err("Key values entered incorrectly\n"); - goto err; + goto err_request; } cmp += pos; if (sscanf(cmp, "%u %n", &data, &pos) != 1) { pr_err("Invalid number of arguments passed\n"); - goto err; + goto err_request; } if (msm_rpm_add_kvp_data(req, key, From 7ae8565f29b065673017550e07157026a1974a6a Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Wed, 25 Oct 2017 16:16:36 +0530 Subject: [PATCH 12/45] soc: qcom: pil: Fix error handling during PIL driver probe During probe function of the Linux PIL kernel driver Initialization of various resources are done. This fix is for acquired resource cleanup, in case of error. CRs-Fixed: 2129451 Change-Id: I0b3511cff7e2917fe83bddfc15086e939f5c2abc Signed-off-by: Jitendra Sharma Signed-off-by: Swetha Chikkaboraiah --- drivers/soc/qcom/subsys-pil-tz.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c index de133f702855..a179b2adf35e 100644 --- a/drivers/soc/qcom/subsys-pil-tz.c +++ b/drivers/soc/qcom/subsys-pil-tz.c @@ -974,6 +974,7 @@ err_subsys: destroy_ramdump_device(d->ramdump_dev); err_ramdump: pil_desc_release(&d->desc); + platform_set_drvdata(pdev, NULL); return rc; } From 45c8b061e2bef9a4f43d2cb0742ea4cdc9b1736b Mon Sep 17 00:00:00 2001 From: Tanya Dixit Date: Thu, 26 Oct 2017 13:50:42 +0530 Subject: [PATCH 13/45] drivers: qdsp6v2: Add mutex unlock to properly release lock Add mutex unlock in function audio_effects_shared_ioctl at appropriate place to prevent use after free. CRs-Fixed: 2123291 Change-Id: Ie0d321dc8cc20a295d102a44faea7e5710834932 Signed-off-by: Tanya Dixit --- drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index 5543059ab64b..b0147396fbd0 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -161,7 +161,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Read buffer Allocation failed rc = %d\n", __func__, rc); rc = -ENOMEM; - mutex_unlock(&effects->lock); goto readbuf_fail; } atomic_set(&effects->out_count, effects->config.output.num_buf); @@ -176,7 +175,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (rc < 0) { pr_err("%s: pcm read block config failed\n", __func__); rc = -EINVAL; - mutex_unlock(&effects->lock); goto cfg_fail; } pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n", @@ -191,7 +189,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: pcm write format block config failed\n", __func__); rc = -EINVAL; - mutex_unlock(&effects->lock); goto cfg_fail; } @@ -325,6 +322,7 @@ ioctl_fail: readbuf_fail: q6asm_audio_client_buf_free_contiguous(IN, effects->ac); + mutex_unlock(&effects->lock); return rc; cfg_fail: q6asm_audio_client_buf_free_contiguous(IN, @@ -332,6 +330,7 @@ cfg_fail: q6asm_audio_client_buf_free_contiguous(OUT, effects->ac); effects->buf_alloc = 0; + mutex_unlock(&effects->lock); return rc; } From 8d16b4924ec17832eb70d67db2176486921e4318 Mon Sep 17 00:00:00 2001 From: Lior David Date: Tue, 17 Oct 2017 11:13:36 +0300 Subject: [PATCH 14/45] wil6210: add block size checks during FW load When loading FW from file add block size checks to ensure a corrupted FW file will not cause the driver to write outside the device memory. Change-Id: I6d7342cd33b2c47b701bcca4ee3cd84febbc56a2 Signed-off-by: Lior David --- drivers/net/wireless/ath/wil6210/fw_inc.c | 58 ++++++++++++++-------- drivers/net/wireless/ath/wil6210/wil6210.h | 1 + drivers/net/wireless/ath/wil6210/wmi.c | 11 +++- 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 157f5ef384e0..69109f0d4764 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -26,14 +26,17 @@ prefix_type, rowsize, \ groupsize, buf, len, ascii) -#define FW_ADDR_CHECK(ioaddr, val, msg) do { \ - ioaddr = wmi_buffer(wil, val); \ - if (!ioaddr) { \ - wil_err_fw(wil, "bad " msg ": 0x%08x\n", \ - le32_to_cpu(val)); \ - return -EINVAL; \ - } \ - } while (0) +static bool wil_fw_addr_check(struct wil6210_priv *wil, + void __iomem **ioaddr, __le32 val, + u32 size, const char *msg) +{ + *ioaddr = wmi_buffer_block(wil, val, size); + if (!(*ioaddr)) { + wil_err_fw(wil, "bad %s: 0x%08x\n", msg, le32_to_cpu(val)); + return false; + } + return true; +} /** * wil_fw_verify - verify firmware file validity @@ -138,7 +141,8 @@ static int fw_handle_data(struct wil6210_priv *wil, const void *data, return -EINVAL; } - FW_ADDR_CHECK(dst, d->addr, "address"); + if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) + return -EINVAL; wil_dbg_fw(wil, "write [0x%08x] <== %zu bytes\n", le32_to_cpu(d->addr), s); wil_memcpy_toio_32(dst, d->data, s); @@ -170,7 +174,8 @@ static int fw_handle_fill(struct wil6210_priv *wil, const void *data, return -EINVAL; } - FW_ADDR_CHECK(dst, d->addr, "address"); + if (!wil_fw_addr_check(wil, &dst, d->addr, s, "address")) + return -EINVAL; v = le32_to_cpu(d->value); wil_dbg_fw(wil, "fill [0x%08x] <== 0x%08x, %zu bytes\n", @@ -219,7 +224,8 @@ static int fw_handle_direct_write(struct wil6210_priv *wil, const void *data, u32 v = le32_to_cpu(block[i].value); u32 x, y; - FW_ADDR_CHECK(dst, block[i].addr, "address"); + if (!wil_fw_addr_check(wil, &dst, block[i].addr, 0, "address")) + return -EINVAL; x = ioread32(dst); y = (x & m) | (v & ~m); @@ -285,10 +291,15 @@ static int fw_handle_gateway_data(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd); - FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); - FW_ADDR_CHECK(gwa_val, d->gateway_value_addr, "gateway_value_addr"); - FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); - FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); + if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, + "gateway_addr_addr") || + !wil_fw_addr_check(wil, &gwa_val, d->gateway_value_addr, 0, + "gateway_value_addr") || + !wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, + "gateway_cmd_addr") || + !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, + "gateway_ctrl_address")) + return -EINVAL; wil_dbg_fw(wil, "gw addresses: addr 0x%08x val 0x%08x" " cmd 0x%08x ctl 0x%08x\n", @@ -344,12 +355,19 @@ static int fw_handle_gateway_data4(struct wil6210_priv *wil, const void *data, wil_dbg_fw(wil, "gw4 write record [%3d] blocks, cmd 0x%08x\n", n, gw_cmd); - FW_ADDR_CHECK(gwa_addr, d->gateway_addr_addr, "gateway_addr_addr"); + if (!wil_fw_addr_check(wil, &gwa_addr, d->gateway_addr_addr, 0, + "gateway_addr_addr")) + return -EINVAL; for (k = 0; k < ARRAY_SIZE(block->value); k++) - FW_ADDR_CHECK(gwa_val[k], d->gateway_value_addr[k], - "gateway_value_addr"); - FW_ADDR_CHECK(gwa_cmd, d->gateway_cmd_addr, "gateway_cmd_addr"); - FW_ADDR_CHECK(gwa_ctl, d->gateway_ctrl_address, "gateway_ctrl_address"); + if (!wil_fw_addr_check(wil, &gwa_val[k], + d->gateway_value_addr[k], + 0, "gateway_value_addr")) + return -EINVAL; + if (!wil_fw_addr_check(wil, &gwa_cmd, d->gateway_cmd_addr, 0, + "gateway_cmd_addr") || + !wil_fw_addr_check(wil, &gwa_ctl, d->gateway_ctrl_address, 0, + "gateway_ctrl_address")) + return -EINVAL; wil_dbg_fw(wil, "gw4 addresses: addr 0x%08x cmd 0x%08x ctl 0x%08x\n", le32_to_cpu(d->gateway_addr_addr), diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 2233355f14dd..efbf8fb85652 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -677,6 +677,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); int wil_find_cid(struct wil6210_priv *wil, const u8 *mac); void wil_set_ethtoolops(struct net_device *ndev); +void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr, u32 size); void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 879ccb03a802..c6574f22a3cf 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -113,13 +113,15 @@ static u32 wmi_addr_remap(u32 x) /** * Check address validity for WMI buffer; remap if needed * @ptr - internal (linker) fw/ucode address + * @size - if non zero, validate the block does not + * exceed the device memory (bar) * * Valid buffer should be DWORD aligned * * return address for accessing buffer from the host; * if buffer is not valid, return NULL. */ -void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) +void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size) { u32 off; u32 ptr = le32_to_cpu(ptr_); @@ -134,10 +136,17 @@ void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) off = HOSTADDR(ptr); if (off > WIL6210_MEM_SIZE - 4) return NULL; + if (size && ((off + size > WIL6210_MEM_SIZE) || (off + size < off))) + return NULL; return wil->csr + off; } +void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) +{ + return wmi_buffer_block(wil, ptr_, 0); +} + /** * Check address validity */ From bbaf6821f2bc5eab7bd36e7a256c3ecdf46a1833 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 May 2017 13:58:53 +0300 Subject: [PATCH 15/45] ipx: call ipxitf_put() in ioctl error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should call ipxitf_put() if the copy_to_user() fails. Change-Id: I365777e4a07923a2c96c5523d9046b9c9007f289 Reported-by: 李强 Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Git-commit: ee0d8d8482345ff97a75a7d747efc309f13b0d80 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git Signed-off-by: Srinivasa Rao Kuppala --- net/ipx/af_ipx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 2665bf4b8d05..f86f096aa16a 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1183,11 +1183,10 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) sipx->sipx_network = ipxif->if_netnum; memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node)); - rc = -EFAULT; - if (copy_to_user(arg, &ifr, sizeof(ifr))) - break; - ipxitf_put(ipxif); rc = 0; + if (copy_to_user(arg, &ifr, sizeof(ifr))) + rc = -EFAULT; + ipxitf_put(ipxif); break; } case SIOCAIPXITFCRT: From c660e17d92f3659396bb9da46da8533177d42c9d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 4 Feb 2017 23:18:55 -0800 Subject: [PATCH 16/45] ip6_gre: fix ip6gre_err() invalid reads Andrey Konovalov reported out of bound accesses in ip6gre_err() If GRE flags contains GRE_KEY, the following expression *(((__be32 *)p) + (grehlen / 4) - 1) accesses data ~40 bytes after the expected point, since grehlen includes the size of IPv6 headers. Let's use a "struct gre_base_hdr *greh" pointer to make this code more readable. p[1] becomes greh->protocol. grhlen is the GRE header length. Change-Id: I5e0ff2b03734a0251e5b687fe2630bea84a1e163 Fixes: c12b395a4664 ("gre: Support GRE over IPv6") Signed-off-by: Eric Dumazet Reported-by: Andrey Konovalov Signed-off-by: David S. Miller Git-commit: 7892032cfe67f4bde6fc2ee967e45a8fbaf33756 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git Signed-off-by: Srinivasa Rao Kuppala --- net/ipv6/ip6_gre.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 65156a73b3f3..02855b1c0642 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -364,36 +364,37 @@ static void ip6gre_tunnel_uninit(struct net_device *dev) static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - u8 type, u8 code, int offset, __be32 info) + u8 type, u8 code, int offset, __be32 info) { - const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data; - __be16 *p = (__be16 *)(skb->data + offset); - int grehlen = offset + 4; + const struct gre_base_hdr *greh; + const struct ipv6hdr *ipv6h; + int grehlen = sizeof(*greh); struct ip6_tnl *t; + int key_off = 0; __be16 flags; + __be32 key; - flags = p[0]; - if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { - if (flags&(GRE_VERSION|GRE_ROUTING)) - return; - if (flags&GRE_KEY) { - grehlen += 4; - if (flags&GRE_CSUM) - grehlen += 4; - } + if (!pskb_may_pull(skb, offset + grehlen)) + return; + greh = (const struct gre_base_hdr *)(skb->data + offset); + flags = greh->flags; + if (flags & (GRE_VERSION | GRE_ROUTING)) + return; + if (flags & GRE_CSUM) + grehlen += 4; + if (flags & GRE_KEY) { + key_off = grehlen + offset; + grehlen += 4; } - /* If only 8 bytes returned, keyed message will be dropped here */ - if (!pskb_may_pull(skb, grehlen)) + if (!pskb_may_pull(skb, offset + grehlen)) return; ipv6h = (const struct ipv6hdr *)skb->data; - p = (__be16 *)(skb->data + offset); + greh = (const struct gre_base_hdr *)(skb->data + offset); + key = key_off ? *(__be32 *)(skb->data + key_off) : 0; - t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, - flags & GRE_KEY ? - *(((__be32 *)p) + (grehlen / 4) - 1) : 0, - p[1]); - if (t == NULL) + t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr,key, greh->protocol); + if (!t) return; switch (type) { From be7412efebfdfd9f85accf44433c6833290a60f0 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 7 Dec 2015 15:09:35 -0500 Subject: [PATCH 17/45] ext4: provide ext4_issue_zeroout() Create new function ext4_issue_zeroout() to zeroout contiguous (both logically and physically) part of inode data. We will need to issue zeroout when extent structure is not readily available and this function will allow us to do it without making up fake extent structures. Change-Id: I5deb04b49d3ebdd1ac12f8bb950faf46d08f5d80 Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o Git-commit: 53085fac02d12fcd29a9cb074ec480ff0f77ae5c Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-4.4 [srkupp@codeaurora.org: Resolved minor conflict] Signed-off-by: Srinivasa Rao Kuppala --- fs/ext4/ext4.h | 2 ++ fs/ext4/extents.c | 8 ++------ fs/ext4/inode.c | 12 ++++++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index e5a77bb30ba3..5769d7bfc7b5 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2118,6 +2118,8 @@ extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); extern qsize_t *ext4_get_reserved_space(struct inode *inode); extern void ext4_da_update_reserve_space(struct inode *inode, int used, int quota_claim); +extern int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, + ext4_fsblk_t pblk, ext4_lblk_t len); /* indirect.c */ extern int ext4_ind_map_blocks(handle_t *handle, struct inode *inode, diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index df633bb25909..7bd604f411fa 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2982,16 +2982,12 @@ static int ext4_ext_zeroout(struct inode *inode, struct ext4_extent *ex) { ext4_fsblk_t ee_pblock; unsigned int ee_len; - int ret; ee_len = ext4_ext_get_actual_len(ex); ee_pblock = ext4_ext_pblock(ex); - ret = sb_issue_zeroout(inode->i_sb, ee_pblock, ee_len, GFP_NOFS); - if (ret > 0) - ret = 0; - - return ret; + return ext4_issue_zeroout(inode, le32_to_cpu(ex->ee_block), ee_pblock, + ee_len); } /* diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8a277505a3be..5f83204c1ec0 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -421,6 +421,18 @@ static int __check_block_validity(struct inode *inode, const char *func, return 0; } +int ext4_issue_zeroout(struct inode *inode, ext4_lblk_t lblk, ext4_fsblk_t pblk, + ext4_lblk_t len) +{ + int ret; + + ret = sb_issue_zeroout(inode->i_sb, pblk, len, GFP_NOFS); + if (ret > 0) + ret = 0; + + return ret; +} + #define check_block_validity(inode, map) \ __check_block_validity((inode), __func__, __LINE__, (map)) From d5a48ade03146f222c1c9f5af11d63335e3d9e56 Mon Sep 17 00:00:00 2001 From: Chris Salls Date: Fri, 13 Oct 2017 13:13:46 +0530 Subject: [PATCH 18/45] mm/mempolicy.c: fix error handling in set_mempolicy and mbind. In the case that compat_get_bitmap fails we do not want to copy the bitmap to the user as it will contain uninitialized stack data and leak sensitive data. Change-Id: I4f66a1c3ef7e616d06d3301b145973ed8cd9e449 Signed-off-by: Chris Salls Signed-off-by: Linus Torvalds Git-commit: cf01fb9985e8deb25ccf0ea54d916b8871ae0e62 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Arun KS --- mm/mempolicy.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 420e4b97ffab..063ed639e88a 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1537,7 +1537,6 @@ asmlinkage long compat_sys_get_mempolicy(int __user *policy, asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask, compat_ulong_t maxnode) { - long err = 0; unsigned long __user *nm = NULL; unsigned long nr_bits, alloc_size; DECLARE_BITMAP(bm, MAX_NUMNODES); @@ -1546,14 +1545,13 @@ asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask, alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; if (nmask) { - err = compat_get_bitmap(bm, nmask, nr_bits); + if(compat_get_bitmap(bm, nmask, nr_bits)) + return -EFAULT; nm = compat_alloc_user_space(alloc_size); - err |= copy_to_user(nm, bm, alloc_size); + if(copy_to_user(nm, bm, alloc_size)) + return -EFAULT; } - if (err) - return -EFAULT; - return sys_set_mempolicy(mode, nm, nr_bits+1); } @@ -1561,7 +1559,6 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len, compat_ulong_t mode, compat_ulong_t __user *nmask, compat_ulong_t maxnode, compat_ulong_t flags) { - long err = 0; unsigned long __user *nm = NULL; unsigned long nr_bits, alloc_size; nodemask_t bm; @@ -1570,14 +1567,13 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len, alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8; if (nmask) { - err = compat_get_bitmap(nodes_addr(bm), nmask, nr_bits); + if(compat_get_bitmap(nodes_addr(bm), nmask, nr_bits)) + return -EFAULT; nm = compat_alloc_user_space(alloc_size); - err |= copy_to_user(nm, nodes_addr(bm), alloc_size); + if(copy_to_user(nm, nodes_addr(bm), alloc_size)) + return -EFAULT; } - if (err) - return -EFAULT; - return sys_mbind(start, len, mode, nm, nr_bits+1, flags); } From 46b8412b06b5376287bd7e8193cc6c1be2c72e49 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 24 Apr 2016 00:56:03 -0400 Subject: [PATCH 19/45] BACKPORT: ext4: fix data exposure after a crash Huang has reported that in his powerfail testing he is seeing stale block contents in some of recently allocated blocks although he mounts ext4 in data=ordered mode. After some investigation I have found out that indeed when delayed allocation is used, we don't add inode to transaction's list of inodes needing flushing before commit. Originally we were doing that but commit f3b59291a69d removed the logic with a flawed argument that it is not needed. The problem is that although for delayed allocated blocks we write their contents immediately after allocating them, there is no guarantee that the IO scheduler or device doesn't reorder things and thus transaction allocating blocks and attaching them to inode can reach stable storage before actual block contents. Actually whenever we attach freshly allocated blocks to inode using a written extent, we should add inode to transaction's ordered inode list to make sure we properly wait for block contents to be written before committing the transaction. So that is what we do in this patch. This also handles other cases where stale data exposure was possible - like filling hole via mmap in data=ordered,nodelalloc mode. The only exception to the above rule are extending direct IO writes where blkdev_direct_IO() waits for IO to complete before increasing i_size and thus stale data exposure is not possible. For now we don't complicate the code with optimizing this special case since the overhead is pretty low. In case this is observed to be a performance problem we can always handle it using a special flag to ext4_map_blocks(). Change-Id: Idc78b64e4f23e6085301c60057af6029b49a8193 Git-commit: 1200efcca9b5174bc8de5ac8440f49fab3bcd0f8 Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-4.4 CC: stable@vger.kernel.org Fixes: f3b59291a69d0b734be1fc8be489fef2dd846d3d Reported-by: "HUANG Weller (CM/ESW12-CN)" Tested-by: "HUANG Weller (CM/ESW12-CN)" Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o Signed-off-by: Connor O'Brien Bug: 62198330 Signed-off-by: Srinivasa Rao Kuppala --- fs/ext4/inode.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8a277505a3be..a98380f9fcc9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -753,6 +753,20 @@ has_zeroout: int ret = check_block_validity(inode, map); if (ret != 0) return ret; + + /* + * Inodes with freshly allocated blocks where contents will be + * visible after transaction commit must be on transaction's + * ordered data list. + */ + if (map->m_flags & EXT4_MAP_NEW && + !(map->m_flags & EXT4_MAP_UNWRITTEN) && + !IS_NOQUOTA(inode) && + ext4_should_order_data(inode)) { + ret = ext4_jbd2_file_inode(handle, inode); + if (ret) + return ret; + } } return retval; } @@ -1113,15 +1127,6 @@ static int ext4_write_end(struct file *file, int i_size_changed = 0; trace_ext4_write_end(inode, pos, len, copied); - if (ext4_test_inode_state(inode, EXT4_STATE_ORDERED_MODE)) { - ret = ext4_jbd2_file_inode(handle, inode); - if (ret) { - unlock_page(page); - page_cache_release(page); - goto errout; - } - } - if (ext4_has_inline_data(inode)) { ret = ext4_write_inline_data_end(inode, pos, len, copied, page); From 46607534af4ad158f8ee73e69224313b4a64ff04 Mon Sep 17 00:00:00 2001 From: Depeng Shao Date: Fri, 12 May 2017 14:27:30 +0800 Subject: [PATCH 20/45] msm: camera: sensor: Validate sensor related name length Variable "slave_info->sensor_name", "slave_info->eeprom_name", "slave_info->actuator_name" and "slave_info->ois_name" are from user input, which may be not NULL terminated. OOB will be possible when accessing these variable. Add a validation for these name length. Change-Id: I9a570372707b7f8365a625d6b0662e87d1b4926e Signed-off-by: Depeng Shao --- .../msm/camera_v2/sensor/msm_sensor_driver.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index bf0ebfd9936e..7756bdfde839 100755 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2015,2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-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 @@ -746,6 +746,21 @@ int32_t msm_sensor_driver_probe(void *setting, } } + if (strlen(slave_info->sensor_name) >= MAX_SENSOR_NAME || + strlen(slave_info->eeprom_name) >= MAX_SENSOR_NAME || + strlen(slave_info->actuator_name) >= MAX_SENSOR_NAME || + strlen(slave_info->ois_name) >= MAX_SENSOR_NAME) { + pr_err("failed: name len greater than 32.\n"); + pr_err("sensor name len:%zu, eeprom name len: %zu.\n", + strlen(slave_info->sensor_name), + strlen(slave_info->eeprom_name)); + pr_err("actuator name len: %zu, ois name len:%zu.\n", + strlen(slave_info->actuator_name), + strlen(slave_info->ois_name)); + rc = -EINVAL; + goto free_slave_info; + } + /* Print slave info */ CDBG("camera id %d Slave addr 0x%X addr_type %d\n", slave_info->camera_id, slave_info->slave_addr, From 26020077ec2ffd23b1d2f5d902e94533b4c989a5 Mon Sep 17 00:00:00 2001 From: Odelu Kukatla Date: Wed, 13 Dec 2017 21:17:22 +0530 Subject: [PATCH 21/45] msm: msm_bus: Add mutex lock for floor vote data Floor vote data needs to be protected with mutex lock to avoid double free of memory due to race condtion. Change-Id: Ifaa01a14d273ccba6b9463aff3a41c0038b05f06 Signed-off-by: Odelu Kukatla --- drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c index a876484859eb..a69c04368ff7 100644 --- a/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c +++ b/drivers/platform/msm/msm_bus/msm_bus_dbg_voter.c @@ -27,6 +27,7 @@ struct msm_bus_floor_client_type { }; static struct class *bus_floor_class; +static DEFINE_RT_MUTEX(msm_bus_floor_vote_lock); #define MAX_VOTER_NAME (50) #define DEFAULT_NODE_WIDTH (8) #define DBG_NAME(s) (strnstr(s, "-", 7) + 1) @@ -64,18 +65,22 @@ static ssize_t bus_floor_active_only_store(struct device *dev, { struct msm_bus_floor_client_type *cl; + rt_mutex_lock(&msm_bus_floor_vote_lock); cl = dev_get_drvdata(dev); if (!cl) { pr_err("%s: Can't find cl", __func__); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return 0; } if (sscanf(buf, "%d", &cl->active_only) != 1) { pr_err("%s:return error", __func__); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return -EINVAL; } + rt_mutex_unlock(&msm_bus_floor_vote_lock); return n; } @@ -100,20 +105,24 @@ static ssize_t bus_floor_vote_store(struct device *dev, struct msm_bus_floor_client_type *cl; int ret = 0; + rt_mutex_lock(&msm_bus_floor_vote_lock); cl = dev_get_drvdata(dev); if (!cl) { pr_err("%s: Can't find cl", __func__); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return 0; } if (sscanf(buf, "%llu", &cl->cur_vote_hz) != 1) { pr_err("%s:return error", __func__); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return -EINVAL; } ret = msm_bus_floor_vote_context(dev_name(dev), cl->cur_vote_hz, cl->active_only); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return n; } @@ -126,15 +135,18 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, char name[10]; u64 vote_khz = 0; + rt_mutex_lock(&msm_bus_floor_vote_lock); cl = dev_get_drvdata(dev); if (!cl) { pr_err("%s: Can't find cl", __func__); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return 0; } if (sscanf(buf, "%9s %llu", name, &vote_khz) != 2) { pr_err("%s:return error", __func__); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return -EINVAL; } @@ -142,6 +154,7 @@ static ssize_t bus_floor_vote_store_api(struct device *dev, __func__, name, vote_khz); ret = msm_bus_floor_vote(name, vote_khz); + rt_mutex_unlock(&msm_bus_floor_vote_lock); return n; } From 5d5e1e83fa74fa6334c1edb8c2fc1038386f9817 Mon Sep 17 00:00:00 2001 From: c_mtharu Date: Fri, 1 Dec 2017 13:43:48 +0530 Subject: [PATCH 22/45] msm: ADSPRPC: validate context pointer with magic number Validate context pointer using magic number instead of searching through context list. It removes the usage of spin lock in interrupt handler for avoiding deadlock and reducing latency. Change-Id: I2492a7984a8d6545618a9cfb7a2d239d03ddd5a2 Acked-by: Viswanatham Paduchuri Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 13ce1f9a0a3f..1ed7610efa57 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -54,6 +54,7 @@ #define RPC_TIMEOUT (5 * HZ) #define BALIGN 32 #define NUM_CHANNELS 1 /*8 compute 2 cpz 1 modem*/ +#define FASTRPC_CTX_MAGIC (0xbeeddeed) #define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0) @@ -134,6 +135,7 @@ struct smq_invoke_ctx { uint32_t sc; struct overlap *overs; struct overlap **overps; + unsigned int magic; }; struct fastrpc_ctx_lst { @@ -572,6 +574,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, ctx->pid = current->pid; ctx->tgid = current->tgid; init_completion(&ctx->work); + ctx->magic = FASTRPC_CTX_MAGIC; spin_lock(&fl->hlock); hlist_add_head(&ctx->hn, &clst->pending); @@ -606,6 +609,7 @@ static void context_free(struct smq_invoke_ctx *ctx) for (i = 0; i < nbufs; ++i) fastrpc_mmap_free(ctx->maps[i]); fastrpc_buf_free(ctx->buf, 1); + ctx->magic = 0; kfree(ctx); } @@ -1007,15 +1011,23 @@ static void fastrpc_read_handler(int cid) { struct fastrpc_apps *me = &gfa; struct smq_invoke_rsp rsp = {0}; - int ret = 0; + struct smq_invoke_ctx *ctx; + int ret = 0, err = 0; do { ret = smd_read_from_cb(me->channel[cid].chan, &rsp, sizeof(rsp)); if (ret != sizeof(rsp)) break; + ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rsp.ctx)); + VERIFY(err, (ctx && ctx->magic == FASTRPC_CTX_MAGIC)); + if (err) + goto bail; context_notify_user(uint64_to_ptr(rsp.ctx), rsp.retval); } while (ret == sizeof(rsp)); +bail: + if (err) + pr_err("adsprpc: invalid response or context\n"); } static void smd_event_handler(void *priv, unsigned event) From e155cf8e28685f61f6d172c29c7bd78966f5fc21 Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Mon, 2 Oct 2017 16:56:55 -0700 Subject: [PATCH 23/45] ALSA: pcm: remove SNDRV_PCM_IOCTL1_INFO internal command Drivers can implement 'struct snd_pcm_ops.ioctl' to handle some requests from ALSA PCM core. These requests are internal purpose in kernel land. Usually common set of operations are used for it. SNDRV_PCM_IOCTL1_INFO is one of the requests. According to code comment, it has been obsoleted in the old days. We can see old releases in ftp.alsa-project.org. The command was firstly introduced in v0.5.0 release as SND_PCM_IOCTL1_INFO, to allow drivers to fill data of 'struct snd_pcm_channel_info' type. In v0.9.0 release, this was obsoleted by the other commands for ioctl(2) such as SNDRV_PCM_IOCTL_CHANNEL_INFO. This commit removes the long-abandoned command, bye. CRs-fixed: 2112663 Change-Id: I17d9c0a759fce81d3dc9b9375f5d5f35dac583b8 Signed-off-by: Takashi Sakamoto Signed-off-by: Takashi Iwai Git-commit: e11f0f90a626f93899687b1cc909ee37dd6c5809 Git-repo: git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git Signed-off-by: Karthikeyan Mani --- include/sound/pcm.h | 2 +- sound/core/pcm_lib.c | 2 -- sound/core/pcm_native.c | 6 +----- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b9c66ec0cf2a..4fc1d9716750 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -102,7 +102,7 @@ struct snd_pcm_ops { #define SNDRV_PCM_IOCTL1_TRUE ((void *)1) #define SNDRV_PCM_IOCTL1_RESET 0 -#define SNDRV_PCM_IOCTL1_INFO 1 +/* 1 is absent slot. */ #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 #define SNDRV_PCM_IOCTL1_GSTATE 3 #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 33d8c08e564f..d24bc5fe77ea 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1830,8 +1830,6 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { switch (cmd) { - case SNDRV_PCM_IOCTL1_INFO: - return 0; case SNDRV_PCM_IOCTL1_RESET: return snd_pcm_lib_ioctl_reset(substream, arg); case SNDRV_PCM_IOCTL1_CHANNEL_INFO: diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f89f790b3c61..89fe0c712a97 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -113,11 +113,7 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) info->subdevices_avail = pstr->substream_count - pstr->substream_opened; strlcpy(info->subname, substream->name, sizeof(info->subname)); runtime = substream->runtime; - /* AB: FIXME!!! This is definitely nonsense */ - if (runtime) { - info->sync = runtime->sync; - substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info); - } + return 0; } From 5b2b7b3caf935faf7f5b7247fa73c98d8cb4489a Mon Sep 17 00:00:00 2001 From: Banajit Goswami Date: Mon, 2 Oct 2017 15:28:10 -0700 Subject: [PATCH 24/45] ALSA: pcm: remove unused variable from snd_pcm_info() Remove unused 'runtime' variable from function snd_pcm_info(). The last usage of this variable was removed with the 'commit e11f0f90a626f9 ("ALSA: pcm: remove SNDRV_PCM_IOCTL1_INFO internal command")'. Change-Id: I3964d84f7cced811d15ff45a1c31cc28d20dc721 Signed-off-by: Banajit Goswami --- sound/core/pcm_native.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 89fe0c712a97..7bda6508d9fd 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -96,7 +96,6 @@ static inline void snd_leave_user(mm_segment_t fs) int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) { - struct snd_pcm_runtime *runtime; struct snd_pcm *pcm = substream->pcm; struct snd_pcm_str *pstr = substream->pstr; @@ -112,7 +111,6 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info) info->subdevices_count = pstr->substream_count; info->subdevices_avail = pstr->substream_count - pstr->substream_opened; strlcpy(info->subname, substream->name, sizeof(info->subname)); - runtime = substream->runtime; return 0; } From 976dce7632d1ff37236612fb2a5606bf869ac488 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Mon, 11 Dec 2017 14:44:39 +0530 Subject: [PATCH 25/45] ASoC: msm: qdsp6v2: Set freed pointers to NULL Set freed pointers to NULL to avoid double free in msm_compr_playback_open and msm_compr_playback_free functions of the compress driver. CRs-Fixed: 2142216 Change-Id: Ifd011dd85dd9f610c7b69dd460f73d26e006cd66 Signed-off-by: Aditya Bavanari --- sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c | 32 ++++++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 132795703165..c1da2b78e0b5 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -99,6 +99,7 @@ struct msm_compr_pdata { bool use_dsp_gapless_mode; struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX]; struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX]; + bool is_in_use[MSM_FRONTEND_DAI_MAX]; }; struct msm_compr_audio { @@ -1051,11 +1052,16 @@ static int msm_compr_open(struct snd_compr_stream *cstream) { struct snd_compr_runtime *runtime = cstream->runtime; struct snd_soc_pcm_runtime *rtd = cstream->private_data; - struct msm_compr_audio *prtd; + struct msm_compr_audio *prtd = NULL; struct msm_compr_pdata *pdata = snd_soc_platform_get_drvdata(rtd->platform); pr_debug("%s\n", __func__); + if (pdata->is_in_use[rtd->dai_link->be_id] == true) { + pr_err("%s: %s is already in use,err: %d ", + __func__, rtd->dai_link->cpu_dai_name, -EBUSY); + return -EBUSY; + } prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL); if (prtd == NULL) { pr_err("Failed to allocate memory for msm_compr_audio\n"); @@ -1067,7 +1073,7 @@ static int msm_compr_open(struct snd_compr_stream *cstream) pdata->cstream[rtd->dai_link->be_id] = cstream; pdata->audio_effects[rtd->dai_link->be_id] = kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL); - if (!pdata->audio_effects[rtd->dai_link->be_id]) { + if (pdata->audio_effects[rtd->dai_link->be_id] == NULL) { pr_err("%s: Could not allocate memory for effects\n", __func__); pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); @@ -1075,10 +1081,11 @@ static int msm_compr_open(struct snd_compr_stream *cstream) } pdata->dec_params[rtd->dai_link->be_id] = kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL); - if (!pdata->dec_params[rtd->dai_link->be_id]) { + if (pdata->dec_params[rtd->dai_link->be_id] == NULL) { pr_err("%s: Could not allocate memory for dec params\n", __func__); kfree(pdata->audio_effects[rtd->dai_link->be_id]); + pdata->audio_effects[rtd->dai_link->be_id] = NULL; pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); return -ENOMEM; @@ -1088,7 +1095,9 @@ static int msm_compr_open(struct snd_compr_stream *cstream) if (!prtd->audio_client) { pr_err("%s: Could not allocate memory for client\n", __func__); kfree(pdata->audio_effects[rtd->dai_link->be_id]); + pdata->audio_effects[rtd->dai_link->be_id] = NULL; kfree(pdata->dec_params[rtd->dai_link->be_id]); + pdata->dec_params[rtd->dai_link->be_id] = NULL; pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); return -ENOMEM; @@ -1146,7 +1155,7 @@ static int msm_compr_open(struct snd_compr_stream *cstream) } else { pr_err("%s: Unsupported stream type", __func__); } - + pdata->is_in_use[rtd->dai_link->be_id] = true; return 0; } @@ -1241,11 +1250,15 @@ static int msm_compr_free(struct snd_compr_stream *cstream) q6asm_audio_client_buf_free_contiguous(dir, ac); q6asm_audio_client_free(ac); - - kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]); - pdata->audio_effects[soc_prtd->dai_link->be_id] = NULL; - kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); - pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; + if (pdata->audio_effects[soc_prtd->dai_link->be_id] != NULL) { + kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]); + pdata->audio_effects[soc_prtd->dai_link->be_id] = NULL; + } + if (pdata->dec_params[soc_prtd->dai_link->be_id] != NULL) { + kfree(pdata->dec_params[soc_prtd->dai_link->be_id]); + pdata->dec_params[soc_prtd->dai_link->be_id] = NULL; + } + pdata->is_in_use[soc_prtd->dai_link->be_id] = false; kfree(prtd); runtime->private_data = NULL; @@ -2779,6 +2792,7 @@ static int msm_compr_probe(struct snd_soc_platform *platform) pdata->dec_params[i] = NULL; pdata->cstream[i] = NULL; pdata->ch_map[i] = NULL; + pdata->is_in_use[i] = false; } /* From e5f1ad44142582524274cd90890c50f29c460552 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 17 May 2017 07:16:40 -0700 Subject: [PATCH 26/45] sctp: do not inherit ipv6_{mc|ac|fl}_list from parent SCTP needs fixes similar to 83eaddab4378 ("ipv6/dccp: do not inherit ipv6_mc_list from parent"), otherwise bad things can happen. Change-Id: I45e2427c0a7ad58264833c360e709b81c9634a76 Signed-off-by: Eric Dumazet Reported-by: Andrey Konovalov Tested-by: Andrey Konovalov Signed-off-by: David S. Miller Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git Git-commit: fdcee2cbb8438702ea1b328fb6e0ac5e9a40c7f8 Signed-off-by: Ashwanth Goli --- net/sctp/ipv6.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 422d8bdacc0d..154a123647eb 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -657,6 +657,9 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, newnp = inet6_sk(newsk); memcpy(newnp, np, sizeof(struct ipv6_pinfo)); + newnp->ipv6_mc_list = NULL; + newnp->ipv6_ac_list = NULL; + newnp->ipv6_fl_list = NULL; /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() * and getpeername(). From de13ed16e8e4e4daea128220c3b7bbd1691d73d2 Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Thu, 28 Sep 2017 10:54:21 -0700 Subject: [PATCH 27/45] ALSA: pcm: add locks for accessing runtime resource Add spin lock to resolve race conditions while accessing substream runtime resource CRs-fixed: 2112713 Change-Id: I8db743303ceb50205d62adfc02caf6ecab635d47 Signed-off-by: Karthikeyan Mani --- include/sound/pcm.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b9c66ec0cf2a..9f902b67feaf 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -399,6 +399,7 @@ struct snd_pcm_substream { struct snd_pcm_ops *ops; /* -- runtime information -- */ struct snd_pcm_runtime *runtime; + spinlock_t runtime_lock; /* -- timer section -- */ struct snd_timer *timer; /* timer */ unsigned timer_running: 1; /* time is running */ From 2c41ba8f5995b5cc653b03b7a5c06846a22787bd Mon Sep 17 00:00:00 2001 From: Karthikeyan Mani Date: Thu, 28 Sep 2017 11:06:55 -0700 Subject: [PATCH 28/45] ALSA: pcm: use lock to protect substream runtime resource Use a spinlock to protect runtime resource in substream against race conditions which may lead to use-after-free CRs-fixed: 2112713 Change-Id: I37dee68cad5eae05b21cfade3dabc0c2b79be6b8 Signed-off-by: Karthikeyan Mani --- sound/core/pcm.c | 4 ++++ sound/core/pcm_timer.c | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 9b6dde596291..9c2b7bdafdb8 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -696,6 +696,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) } substream->group = &substream->self_group; spin_lock_init(&substream->self_group.lock); + spin_lock_init(&substream->runtime_lock); INIT_LIST_HEAD(&substream->self_group.substreams); list_add_tail(&substream->link_list, &substream->self_group.substreams); atomic_set(&substream->mmap_count, 0); @@ -992,9 +993,11 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, void snd_pcm_detach_substream(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime; + unsigned long flags = 0; if (PCM_RUNTIME_CHECK(substream)) return; + spin_lock_irqsave(&substream->runtime_lock, flags); runtime = substream->runtime; if (runtime->private_free != NULL) runtime->private_free(runtime); @@ -1011,6 +1014,7 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) put_pid(substream->pid); substream->pid = NULL; substream->pstr->substream_opened--; + spin_unlock_irqrestore(&substream->runtime_lock, flags); } static ssize_t show_pcm_class(struct device *dev, diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c index b01d9481d632..00c106c71378 100644 --- a/sound/core/pcm_timer.c +++ b/sound/core/pcm_timer.c @@ -63,9 +63,16 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer) { struct snd_pcm_substream *substream; + unsigned long ret = 0, flags = 0; substream = timer->private_data; - return substream->runtime ? substream->runtime->timer_resolution : 0; + spin_lock_irqsave(&substream->runtime_lock, flags); + if (substream->runtime) + ret = substream->runtime->timer_resolution; + else + ret = 0; + spin_unlock_irqrestore(&substream->runtime_lock, flags); + return ret; } static int snd_pcm_timer_start(struct snd_timer * timer) From 419cc0131185602da18f4e7a0ffed2dddf46521f Mon Sep 17 00:00:00 2001 From: Trishansh Bhardwaj Date: Fri, 22 Dec 2017 11:53:26 +0530 Subject: [PATCH 29/45] msm: camera: Prevent buffer overread in write_logsync. If userspace issues write with string of length 21 or more then there is a chance that kernel will overread lbuf array. This change makes sure that lbuf is NULL terminated. Change-Id: I9ad6d5a607b2ff1f293512be9746ee554b076b10 Signed-off-by: Trishansh Bhardwaj --- drivers/media/platform/msm/camera_v2/msm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c index cd13d0ec81ca..63be32b65a77 100644 --- a/drivers/media/platform/msm/camera_v2/msm.c +++ b/drivers/media/platform/msm/camera_v2/msm.c @@ -1124,7 +1124,7 @@ static ssize_t write_logsync(struct file *file, const char __user *buf, uint64_t seq_num = 0; int ret; - if (copy_from_user(lbuf, buf, sizeof(lbuf))) + if (copy_from_user(lbuf, buf, sizeof(lbuf) - 1)) return -EFAULT; ret = sscanf(lbuf, "%llu", &seq_num); From e216179f9a902bab64d1530c8829f1806d5ec91d Mon Sep 17 00:00:00 2001 From: Ghanim Fodi Date: Tue, 19 Dec 2017 19:15:19 +0200 Subject: [PATCH 30/45] msm: ipa: Fix the handling of default IPA header Default IPA header is added or deleted from the driver directly and not by user space application. This change prevents adding/deleting it from user application which may cause inconsistencies in the driver. Also the change fixes the header reset function to skip on the correct default header. Change-Id: Ic813433655411f1447db8b0c15efdf64038d8c26 CRs-fixed: 2151146 Signed-off-by: Ghanim Fodi --- drivers/platform/msm/ipa/ipa_hdr.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_hdr.c index b82690e43f48..7ae31b8875b1 100644 --- a/drivers/platform/msm/ipa/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_hdr.c @@ -821,8 +821,17 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) return -EINVAL; } - if (by_user) + if (by_user) { + if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME)) { + IPADBG("Trying to delete hdr %s offset=%u\n", + entry->name, entry->offset_entry->offset); + if (!entry->offset_entry->offset) { + IPAERR("User cannot delete default header\n"); + return -EPERM; + } + } entry->user_deleted = true; + } if (--entry->ref_cnt) { IPADBG("hdr_hdl %x ref_cnt %d\n", hdr_hdl, entry->ref_cnt); @@ -1149,8 +1158,19 @@ int ipa_reset_hdr(void) &ipa_ctx->hdr_tbl.head_hdr_entry_list, link) { /* do not remove the default header */ - if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME)) - continue; + if (!strcmp(entry->name, IPA_LAN_RX_HDR_NAME)) { + IPADBG("Trying to remove hdr %s offset=%u\n", + entry->name, entry->offset_entry->offset); + if (!entry->offset_entry->offset) { + if (entry->is_hdr_proc_ctx) { + mutex_unlock(&ipa_ctx->lock); + WARN_ON(1); + return -EFAULT; + } + IPADBG("skip default header\n"); + continue; + } + } if (ipa_id_find(entry->id) == NULL) { WARN_ON(1); From 387d964b4c06f406d3fc5b75b993d165685c17ae Mon Sep 17 00:00:00 2001 From: Steve Pfetsch Date: Fri, 14 Oct 2016 15:36:59 -0700 Subject: [PATCH 31/45] drivers: video: Add bounds checking in fb_cmap_to_user Verify that unsigned int value will not become negative before cast to signed int.. Bug: 31651010 Change-Id: I548a200f678762042617f11100b6966a405a3920 Git-commit:834c0fa0f4ec6a0ae75b8ce718e51cece90dc9cd Git-repo: https://android.googlesource.com/kernel/msm Signed-off-by: Yogendra Charya Tangalapally --- drivers/video/fbcmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index 008212069ac6..520276154d7a 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -196,7 +196,7 @@ int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to) int tooff = 0, fromoff = 0; int size; - if (!to || !from) + if (!to || !from || (int)(to->start) < 0) return -EINVAL; if (to->start > from->start) From 4676b98b74a33b1df4e22b77c2acb4c82564fae6 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 1 Feb 2017 11:48:58 +0000 Subject: [PATCH 32/45] BACKPORT: arm64: Add CNTVCT_EL0 trap handler Since people seem to make a point in breaking the userspace visible counter, we have no choice but to trap the access. Add the required handler. Acked-by: Thomas Gleixner Acked-by: Mark Rutland Signed-off-by: Marc Zyngier (cherry picked from commit 6126ce0588eb5a0752d5c8b5796a7fca324fd887) Change-Id: I0705f47c85a78040df38df18f51a4a22500b904d Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/esr.h | 37 ++++++++++++++++++++++++++++++++++++ arch/arm64/kernel/entry.S | 11 ++++++++++- arch/arm64/kernel/traps.c | 21 ++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 72674f4c3871..0cfad81d93f1 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -54,4 +54,41 @@ #define ESR_EL1_EC_BKPT32 (0x38) #define ESR_EL1_EC_BRK64 (0x3C) +/* ISS field definitions for System instruction traps */ +#define ESR_ELx_SYS64_ISS_RES0_SHIFT 22 +#define ESR_ELx_SYS64_ISS_RES0_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_RES0_SHIFT) +#define ESR_ELx_SYS64_ISS_DIR_MASK 0x1 +#define ESR_ELx_SYS64_ISS_DIR_READ 0x1 +#define ESR_ELx_SYS64_ISS_DIR_WRITE 0x0 + +#define ESR_ELx_SYS64_ISS_RT_SHIFT 5 +#define ESR_ELx_SYS64_ISS_RT_MASK (UL(0x1f) << ESR_ELx_SYS64_ISS_RT_SHIFT) +#define ESR_ELx_SYS64_ISS_CRM_SHIFT 1 +#define ESR_ELx_SYS64_ISS_CRM_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRM_SHIFT) +#define ESR_ELx_SYS64_ISS_CRN_SHIFT 10 +#define ESR_ELx_SYS64_ISS_CRN_MASK (UL(0xf) << ESR_ELx_SYS64_ISS_CRN_SHIFT) +#define ESR_ELx_SYS64_ISS_OP1_SHIFT 14 +#define ESR_ELx_SYS64_ISS_OP1_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP1_SHIFT) +#define ESR_ELx_SYS64_ISS_OP2_SHIFT 17 +#define ESR_ELx_SYS64_ISS_OP2_MASK (UL(0x7) << ESR_ELx_SYS64_ISS_OP2_SHIFT) +#define ESR_ELx_SYS64_ISS_OP0_SHIFT 20 +#define ESR_ELx_SYS64_ISS_OP0_MASK (UL(0x3) << ESR_ELx_SYS64_ISS_OP0_SHIFT) +#define ESR_ELx_SYS64_ISS_SYS_MASK (ESR_ELx_SYS64_ISS_OP0_MASK | \ + ESR_ELx_SYS64_ISS_OP1_MASK | \ + ESR_ELx_SYS64_ISS_OP2_MASK | \ + ESR_ELx_SYS64_ISS_CRN_MASK | \ + ESR_ELx_SYS64_ISS_CRM_MASK) +#define ESR_ELx_SYS64_ISS_SYS_VAL(op0, op1, op2, crn, crm) \ + (((op0) << ESR_ELx_SYS64_ISS_OP0_SHIFT) | \ + ((op1) << ESR_ELx_SYS64_ISS_OP1_SHIFT) | \ + ((op2) << ESR_ELx_SYS64_ISS_OP2_SHIFT) | \ + ((crn) << ESR_ELx_SYS64_ISS_CRN_SHIFT) | \ + ((crm) << ESR_ELx_SYS64_ISS_CRM_SHIFT)) + +#define ESR_ELx_SYS64_ISS_SYS_OP_MASK (ESR_ELx_SYS64_ISS_SYS_MASK | \ + ESR_ELx_SYS64_ISS_DIR_MASK) + +#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #endif /* __ASM_ESR_H */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 6db6c3b56a3d..94dfc936358d 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -378,7 +378,7 @@ el0_sync: cmp x24, #ESR_EL1_EC_FP_EXC64 // FP/ASIMD exception b.eq el0_fpsimd_exc cmp x24, #ESR_EL1_EC_SYS64 // configurable trap - b.eq el0_undef + b.eq el0_sys cmp x24, #ESR_EL1_EC_SP_ALIGN // stack alignment exception b.eq el0_sp_pc cmp x24, #ESR_EL1_EC_PC_ALIGN // pc alignment exception @@ -491,6 +491,15 @@ el0_undef: enable_dbg_and_irq mov x0, sp b do_undefinstr +el0_sys: + /* + * System instructions, for trapped cache maintenance instructions + */ + enable_dbg + enable_irq + mov x0, x25 + mov x1, sp + b do_sysinstr el0_dbg: /* * Debug exception handling diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 2198961ebad5..464cb408e411 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -32,8 +32,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -381,6 +383,25 @@ die_sig: arm64_notify_die("Oops - undefined instruction", regs, &info, 0); } +static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + if (rt != 31) + regs->regs[rt] = arch_counter_get_cntvct(); + regs->pc += 4; +} + +asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) +{ + if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) { + cntvct_read_handler(esr, regs); + return; + } + + do_undefinstr(regs); +} + long compat_arm_syscall(struct pt_regs *regs); asmlinkage long do_ni_syscall(struct pt_regs *regs) From 73551deddc300332be75ae0e679d639f842a8311 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 24 Apr 2017 09:04:03 +0100 Subject: [PATCH 33/45] BACKPORT: arm64: Add CNTFRQ_EL0 trap handler We now trap accesses to CNTVCT_EL0 when the counter is broken enough to require the kernel to mediate the access. But it turns out that some existing userspace (such as OpenMPI) do probe for the counter frequency, leading to an UNDEF exception as CNTVCT_EL0 and CNTFRQ_EL0 share the same control bit. The fix is to handle the exception the same way we do for CNTVCT_EL0. Fixes: a86bd139f2ae ("arm64: arch_timer: Enable CNTVCT_EL0 trap if workaround is enabled") Reported-by: Hanjun Guo Tested-by: Hanjun Guo Reviewed-by: Hanjun Guo Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas (cherry picked from commit 9842119a238bfb92cbab63258dabb54f0e7b111b) Change-Id: Ie5a9a93fcca238d6097ecacd6df0e540be90220b Signed-off-by: Neeraj Upadhyay --- arch/arm64/include/asm/esr.h | 3 +++ arch/arm64/kernel/traps.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 0cfad81d93f1..59aae93ab823 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -91,4 +91,7 @@ #define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ ESR_ELx_SYS64_ISS_DIR_READ) +#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #endif /* __ASM_ESR_H */ diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 464cb408e411..8d07c1f19914 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -392,11 +392,23 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) +{ + int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + + if (rt != 31) + asm volatile("mrs %0, cntfrq_el0" : "=r" (regs->regs[rt])); + regs->pc += 4; +} + asmlinkage void __exception do_sysinstr(unsigned int esr, struct pt_regs *regs) { if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTVCT) { cntvct_read_handler(esr, regs); return; + } else if ((esr & ESR_ELx_SYS64_ISS_SYS_OP_MASK) == ESR_ELx_SYS64_ISS_SYS_CNTFRQ) { + cntfrq_read_handler(esr, regs); + return; } do_undefinstr(regs); From e6da57e2ea1340dc187c0ab27459e65af45b5950 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Wed, 4 Oct 2017 09:31:34 -0700 Subject: [PATCH 34/45] arm64: issue isb when trapping CNTVCT_EL0 access Change-Id: I6005a6e944494257bfc2243fde2f7a09c3fd76c6 Signed-off-by: Neeraj Upadhyay --- arch/arm64/kernel/traps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 8d07c1f19914..2bd4543b6d8c 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -387,6 +388,7 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) { int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; + isb(); if (rt != 31) regs->regs[rt] = arch_counter_get_cntvct(); regs->pc += 4; From 18932e6820501acce64f47ed1ae9f8633c475c05 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 19 Sep 2017 10:55:17 -0700 Subject: [PATCH 35/45] clocksource: arch_timer: make virtual counter access configurable Change-Id: Ibdb1fd768b748002b90bfc165612c12c8311f8a2 Signed-off-by: Neeraj Upadhyay --- drivers/clocksource/Kconfig | 8 ++++++++ drivers/clocksource/arm_arch_timer.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 593485b02ee5..e05e8e9a2fe7 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -82,6 +82,14 @@ config ARM_ARCH_TIMER_EVTSTREAM This must be disabled for hardware validation purposes to detect any hardware anomalies of missing events. +config ARM_ARCH_TIMER_VCT_ACCESS + bool "Support for ARM architected timer virtual counter access in userspace" + default !ARM64 + depends on ARM_ARCH_TIMER + help + This option enables support for reading the ARM architected timer's + virtual counter in userspace. + config CLKSRC_METAG_GENERIC def_bool y if METAG help diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 8ec3739e26c6..efffeedfb7c2 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -319,8 +319,14 @@ static void arch_counter_set_user_access(void) | ARCH_TIMER_USR_VT_ACCESS_EN | ARCH_TIMER_VIRT_EVT_EN); - /* Enable user access to the virtual and physical counters */ - cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN | ARCH_TIMER_USR_PCT_ACCESS_EN; + /* Enable user access to the physical counter */ + cntkctl |= ARCH_TIMER_USR_PCT_ACCESS_EN; + + /* Enable user access to the virtual counter */ + if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) + cntkctl |= ARCH_TIMER_USR_VCT_ACCESS_EN; + else + cntkctl &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; arch_timer_set_cntkctl(cntkctl); } From 438657bc78ad6d4decbef6c2b8f1573703d3588c Mon Sep 17 00:00:00 2001 From: Yasir Malik Date: Thu, 30 Nov 2017 16:17:12 -0500 Subject: [PATCH 36/45] scsi: ufs: Fix off-by-one bug in ufs debugfs driver When getting string from userspace by simple_write_to_buffer in ufs_qcom_dbg_testbus_cfg_write() function, null byte may be written out of bounds of configuration buffer if return value is same as size of buffer, causing off-by-one bug. This change passes correct available size of configuration buffer to simple_write_to_buffer function. Change-Id: I99d4223ba7ac191e7a931c1c0c7be8bcda6263a6 CRs-Fixed: 2143495 Signed-off-by: Yasir Malik Signed-off-by: Sayali Lokhande --- drivers/scsi/ufs/qcom-debugfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/qcom-debugfs.c b/drivers/scsi/ufs/qcom-debugfs.c index e9ac7c8e81c1..32eb7fb62a96 100644 --- a/drivers/scsi/ufs/qcom-debugfs.c +++ b/drivers/scsi/ufs/qcom-debugfs.c @@ -113,7 +113,8 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file, unsigned long flags; struct ufs_hba *hba = host->hba; - cnt = simple_write_to_buffer(configuration, TESTBUS_CFG_BUFF_LINE_SIZE, + cnt = simple_write_to_buffer(configuration, + TESTBUS_CFG_BUFF_LINE_SIZE - 1, &buff_pos, ubuf, cnt); if (cnt < 0) { dev_err(host->hba->dev, "%s: failed to read user data\n", From fe1bc3cf6898cad2526ee0df7b0517e89c849eab Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Tue, 3 Jun 2014 13:18:18 -0400 Subject: [PATCH 37/45] sg: relax 16 byte cdb restriction - remove the 16 byte CDB (SCSI command) length limit from the sg driver by handling longer CDBs the same way as the bsg driver. Remove comment from sg.h public interface about the cmd_len field being limited to 16 bytes. - remove some dead code caused by this change - cleanup comment block at the top of sg.h, fix urls Change-Id: I4152a4ebb8c17140bf47e61a8b5b906e9ec4d945 Signed-off-by: Douglas Gilbert Reviewed-by: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Christoph Hellwig Git-commit: 65c26a0f39695ba01d9693754f27ca76cc8a3ab5 Git-repo: https://android.googlesource.com/kernel/msm Signed-off-by: Sayali Lokhande --- drivers/scsi/sg.c | 49 ++++++++++++++--------- include/uapi/scsi/sg.h | 91 +++++++++++------------------------------- 2 files changed, 54 insertions(+), 86 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 1af1865c7c08..d7ab20c78451 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -7,9 +7,7 @@ * Original driver (sg.c): * Copyright (C) 1992 Lawrence Foard * Version 2 and 3 extensions to driver: - * Copyright (C) 1998 - 2005 Douglas Gilbert - * - * Modified 19-JAN-1998 Richard Gooch Devfs support + * Copyright (C) 1998 - 2014 Douglas Gilbert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,11 +16,11 @@ * */ -static int sg_version_num = 30534; /* 2 digits for each component */ -#define SG_VERSION_STR "3.5.34" +static int sg_version_num = 30536; /* 2 digits for each component */ +#define SG_VERSION_STR "3.5.36" /* - * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: + * D. P. Gilbert (dgilbert@interlog.com), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First * the kernel/module needs to be built with CONFIG_SCSI_LOGGING * (otherwise the macros compile to empty statements). @@ -64,7 +62,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #ifdef CONFIG_SCSI_PROC_FS #include -static char *sg_version_date = "20061027"; +static char *sg_version_date = "20140603"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -74,6 +72,12 @@ static void sg_proc_cleanup(void); #define SG_MAX_DEVS 32768 +/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type + * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater + * than 16 bytes are "variable length" whose length is a multiple of 4 + */ +#define SG_MAX_CDB_SIZE 252 + /* * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) * Then when using 32 bit integers x * m may overflow during the calculation. @@ -161,7 +165,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ char low_dma; /* as in parent but possibly overridden to 1 */ char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ - char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ + unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ char mmap_called; /* 0 -> mmap() never called on this fd */ struct kref f_ref; @@ -567,7 +571,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) Sg_request *srp; struct sg_header old_hdr; sg_io_hdr_t *hp; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char cmnd[SG_MAX_CDB_SIZE]; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; @@ -599,12 +603,6 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) buf += SZ_SG_HEADER; __get_user(opcode, buf); if (sfp->next_cmd_len > 0) { - if (sfp->next_cmd_len > MAX_COMMAND_SIZE) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n")); - sfp->next_cmd_len = 0; - sg_remove_request(sfp, srp); - return -EIO; - } cmd_size = sfp->next_cmd_len; sfp->next_cmd_len = 0; /* reset so only this write() effected */ } else { @@ -676,7 +674,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, int k; Sg_request *srp; sg_io_hdr_t *hp; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char cmnd[SG_MAX_CDB_SIZE]; int timeout; unsigned long ul_timeout; @@ -1653,14 +1651,25 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) struct request_queue *q = sfp->parentdp->device->request_queue; struct rq_map_data *md, map_data; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; + unsigned char *long_cmdp = NULL; SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", dxfer_len)); - rq = blk_get_request(q, rw, GFP_ATOMIC); - if (!rq) - return -ENOMEM; + if (hp->cmd_len > BLK_MAX_CDB) { + long_cmdp = kzalloc(hp->cmd_len, GFP_KERNEL); + if (!long_cmdp) + return -ENOMEM; + } + rq = blk_get_request(q, rw, GFP_ATOMIC); + if (!rq) { + kfree(long_cmdp); + return -ENOMEM; + } + + if (hp->cmd_len > BLK_MAX_CDB) + rq->cmd = long_cmdp; memcpy(rq->cmd, cmd, hp->cmd_len); rq->cmd_len = hp->cmd_len; @@ -1747,6 +1756,8 @@ static int sg_finish_rem_req(Sg_request * srp) if (srp->bio) ret = blk_rq_unmap_user(srp->bio); + if (srp->rq->cmd != srp->rq->__cmd) + kfree(srp->rq->cmd); blk_put_request(srp->rq); } diff --git a/include/uapi/scsi/sg.h b/include/uapi/scsi/sg.h index a9f3c6fc3f57..d8c0c4307fca 100644 --- a/include/uapi/scsi/sg.h +++ b/include/uapi/scsi/sg.h @@ -4,77 +4,34 @@ #include /* - History: - Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user - process control of SCSI devices. - Development Sponsored by Killy Corp. NY NY -Original driver (sg.h): -* Copyright (C) 1992 Lawrence Foard -Version 2 and 3 extensions to driver: -* Copyright (C) 1998 - 2006 Douglas Gilbert - - Version: 3.5.34 (20060920) - This version is for 2.6 series kernels. - - For a full changelog see http://www.torque.net/sg - -Map of SG verions to the Linux kernels in which they appear: - ---------- ---------------------------------- - original all kernels < 2.2.6 - 2.1.40 2.2.20 - 3.0.x optional version 3 sg driver for 2.2 series - 3.1.17++ 2.4.0++ - 3.5.30++ 2.6.0++ - -Major new features in SG 3.x driver (cf SG 2.x drivers) - - SG_IO ioctl() combines function if write() and read() - - new interface (sg_io_hdr_t) but still supports old interface - - scatter/gather in user space, direct IO, and mmap supported - - The normal action of this driver is to use the adapter (HBA) driver to DMA - data into kernel buffers and then use the CPU to copy the data into the - user space (vice versa for writes). That is called "indirect" IO due to - the double handling of data. There are two methods offered to remove the - redundant copy: 1) direct IO and 2) using the mmap() system call to map - the reserve buffer (this driver has one reserve buffer per fd) into the - user space. Both have their advantages. - In terms of absolute speed mmap() is faster. If speed is not a concern, - indirect IO should be fine. Read the documentation for more information. - - ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' or - 'echo 1 > /sys/module/sg/parameters/allow_dio' is needed. - That attribute is 0 by default. ** - - Historical note: this SCSI pass-through driver has been known as "sg" for - a decade. In broader kernel discussions "sg" is used to refer to scatter - gather techniques. The context should clarify which "sg" is referred to. - - Documentation - ============= - A web site for the SG device driver can be found at: - http://www.torque.net/sg [alternatively check the MAINTAINERS file] - The documentation for the sg version 3 driver can be found at: - http://www.torque.net/sg/p/sg_v3_ho.html - This is a rendering from DocBook source [change the extension to "sgml" - or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon). - The SG_IO ioctl is now found in other parts kernel (e.g. the block layer). - For more information see http://www.torque.net/sg/sg_io.html - - The older, version 2 documents discuss the original sg interface in detail: - http://www.torque.net/sg/p/scsi-generic.txt - http://www.torque.net/sg/p/scsi-generic_long.txt - Also available: /Documentation/scsi/scsi-generic.txt - - Utility and test programs are available at the sg web site. They are - packaged as sg3_utils (for the lk 2.4 and 2.6 series) and sg_utils - (for the lk 2.2 series). -*/ + * History: + * Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user + * process control of SCSI devices. + * Development Sponsored by Killy Corp. NY NY + * + * Original driver (sg.h): + * Copyright (C) 1992 Lawrence Foard + * Version 2 and 3 extensions to driver: + * Copyright (C) 1998 - 2014 Douglas Gilbert + * + * Version: 3.5.36 (20140603) + * This version is for 2.6 and 3 series kernels. + * + * Documentation + * ============= + * A web site for the SG device driver can be found at: + * http://sg.danny.cz/sg [alternatively check the MAINTAINERS file] + * The documentation for the sg version 3 driver can be found at: + * http://sg.danny.cz/sg/p/sg_v3_ho.html + * Also see: /Documentation/scsi/scsi-generic.txt + * + * For utility and test programs see: http://sg.danny.cz/sg/sg3_utils.html + */ #ifdef __KERNEL__ extern int sg_big_buff; /* for sysctl */ #endif -/* New interface introduced in the 3.x SG drivers follows */ typedef struct sg_iovec /* same structure as used by readv() Linux system */ { /* call. It defines one scatter-gather element. */ @@ -87,7 +44,7 @@ typedef struct sg_io_hdr { int interface_id; /* [i] 'S' for SCSI generic (required) */ int dxfer_direction; /* [i] data transfer direction */ - unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char cmd_len; /* [i] SCSI command length */ unsigned char mx_sb_len; /* [i] max length to write to sbp */ unsigned short iovec_count; /* [i] 0 implies no scatter gather */ unsigned int dxfer_len; /* [i] byte count of data transfer */ From afa4ec80b774f0b241493d55a9aa9eba121d35a8 Mon Sep 17 00:00:00 2001 From: peter chang Date: Wed, 15 Feb 2017 14:11:54 -0800 Subject: [PATCH 38/45] scsi: sg: check length passed to SG_NEXT_CMD_LEN commit bf33f87dd04c371ea33feb821b60d63d754e3124 upstream. The user can control the size of the next command passed along, but the value passed to the ioctl isn't checked against the usable max command size. Change-Id: Ib063fb80955665638b3e402993cbbd8c41932fac Signed-off-by: Peter Chang Acked-by: Douglas Gilbert Signed-off-by: Martin K. Petersen Signed-off-by: Greg Kroah-Hartman Git-commit: bf33f87dd04c371ea33feb821b60d63d754e3124 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Sayali Lokhande --- drivers/scsi/sg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 1af1865c7c08..e1774655db3c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -984,6 +984,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) result = get_user(val, ip); if (result) return result; + if (val > SG_MAX_CDB_SIZE) + return -ENOMEM; sfp->next_cmd_len = (val > 0) ? val : 0; return 0; case SG_GET_VERSION_NUM: From 4593c1e97dcf1ed4fe8c9e0899db5e995014acfe Mon Sep 17 00:00:00 2001 From: Liam Mark Date: Mon, 4 Dec 2017 10:58:55 -0800 Subject: [PATCH 39/45] ion: ensure CMO target is valid Cleanup ION cache maintenance code to properly validate the target of userspace cache maintenance requests. Change-Id: I55b8e3584c59634f95250bc7c0bce5d8d70e6a13 Signed-off-by: Liam Mark Signed-off-by: Swetha Chikkaboraiah --- drivers/staging/android/ion/ion.c | 5 +++++ drivers/staging/android/ion/ion_system_secure_heap.c | 4 ++-- drivers/staging/android/ion/msm/msm_ion.c | 12 ++++++------ drivers/staging/android/ion/msm_ion_priv.h | 3 ++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a90595bb8d54..0c54c333fc63 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -1520,6 +1520,11 @@ static int ion_sync_for_device(struct ion_client *client, int fd) } buffer = dmabuf->priv; + if ((buffer->flags & ION_FLAG_SECURE) || (get_secure_vmid(buffer->flags) > 0)) { + pr_err("%s: cannot sync a secure dmabuf\n", __func__); + dma_buf_put(dmabuf); + return -EINVAL; + } dma_sync_sg_for_device(NULL, buffer->sg_table->sgl, buffer->sg_table->nents, DMA_BIDIRECTIONAL); dma_buf_put(dmabuf); diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c index b7f765715980..6b55611dcd0d 100644 --- a/drivers/staging/android/ion/ion_system_secure_heap.c +++ b/drivers/staging/android/ion/ion_system_secure_heap.c @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, 2018 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 @@ -40,7 +40,7 @@ static bool is_cp_flag_present(unsigned long flags) ION_FLAG_CP_CAMERA); } -static int get_secure_vmid(unsigned long flags) +int get_secure_vmid(unsigned long flags) { if (flags & ION_FLAG_CP_TOUCH) return VMID_CP_TOUCH; diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index fd67158512a5..3ba65cd3dbea 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2014,2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2014,2016,2018 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 @@ -281,7 +281,7 @@ int ion_do_cache_op(struct ion_client *client, struct ion_handle *handle, if (!ION_IS_CACHED(flags)) return 0; - if (flags & ION_FLAG_SECURE) + if ((flags & ION_FLAG_SECURE) || (get_secure_vmid(flags) > 0)) return 0; table = ion_sg_table(client, handle); @@ -732,11 +732,11 @@ long msm_ion_custom_ioctl(struct ion_client *client, down_read(&mm->mmap_sem); - start = (unsigned long) data.flush_data.vaddr; - end = (unsigned long) data.flush_data.vaddr - + data.flush_data.length; + start = (unsigned long)data.flush_data.vaddr + + data.flush_data.offset; + end = start + data.flush_data.length; - if (start && check_vaddr_bounds(start, end)) { + if (check_vaddr_bounds(start, end)) { pr_err("%s: virtual address %pK is out of bounds\n", __func__, data.flush_data.vaddr); ret = -EINVAL; diff --git a/drivers/staging/android/ion/msm_ion_priv.h b/drivers/staging/android/ion/msm_ion_priv.h index c2e97ef39fc6..9256758c46bd 100644 --- a/drivers/staging/android/ion/msm_ion_priv.h +++ b/drivers/staging/android/ion/msm_ion_priv.h @@ -2,7 +2,7 @@ * drivers/gpu/ion/ion_priv.h * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2014, 2018 The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -117,6 +117,7 @@ int ion_heap_allow_heap_secure(enum ion_heap_type type); int ion_heap_allow_handle_secure(enum ion_heap_type type); +int get_secure_vmid(unsigned long flags); /** * ion_create_chunked_sg_table - helper function to create sg table * with specified chunk size From f26d7265521642e77b262c1bce41eae7682e828f Mon Sep 17 00:00:00 2001 From: Mahesh Sivasubramanian Date: Tue, 28 Nov 2017 10:06:17 -0700 Subject: [PATCH 40/45] drivers: cpuidle: lpm-levels: Fix untrusted pointer dereference. The list_for_each macro was not used correctly, where the intermediate variable would be LIST_POISON, resulting in a untrusted pointer dereference. Switch to using list_for_each_entry_safe to for safe removal of a list entry. Change-Id: I0e0fd5dd9f251b5093d6e9d6335387512ec59249 Signed-off-by: Mahesh Sivasubramanian --- drivers/cpuidle/lpm-levels-of.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c index 2d7488ad0feb..bd41a76a0c68 100644 --- a/drivers/cpuidle/lpm-levels-of.c +++ b/drivers/cpuidle/lpm-levels-of.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014, 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 @@ -820,14 +820,12 @@ failed: void free_cluster_node(struct lpm_cluster *cluster) { - struct list_head *list; int i; + struct lpm_cluster *cl, *m; - list_for_each(list, &cluster->child) { - struct lpm_cluster *n; - n = list_entry(list, typeof(*n), list); - list_del(list); - free_cluster_node(n); + list_for_each_entry_safe(cl, m, &cluster->child, list) { + list_del(&cl->list); + free_cluster_node(cl); }; if (cluster->cpu) { From 65cad978de88ee9ee23a1165b67c25201aef48a6 Mon Sep 17 00:00:00 2001 From: Tharun Kumar Merugu Date: Tue, 19 Dec 2017 11:56:20 +0530 Subject: [PATCH 41/45] msm: adsprpc: Use unsigned integer for length values As the length datatype is signed, an attacker can both overflow the calculation or supply a negative number to trick the check into returning an chosen chunk. This can have undesired consequences. Always use unsigned integer types for length values. Change-Id: Ifde2f0d35129014b976507f7723a319c53fabddf Acked-by: Thyagarajan Venkatanarayanan Signed-off-by: Tharun Kumar Merugu --- drivers/char/adsprpc.c | 165 +++++++++++++++++----------------- drivers/char/adsprpc_compat.c | 14 +-- drivers/char/adsprpc_shared.h | 23 ++--- 3 files changed, 103 insertions(+), 99 deletions(-) diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 1ed7610efa57..64661b789980 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -70,11 +70,11 @@ static inline uint64_t buf_page_offset(uint64_t buf) return offset; } -static inline int buf_num_pages(uint64_t buf, ssize_t len) +static inline uint64_t buf_num_pages(uint64_t buf, size_t len) { uint64_t start = buf_page_start(buf) >> PAGE_SHIFT; uint64_t end = (((uint64_t) buf + len - 1) & PAGE_MASK) >> PAGE_SHIFT; - int nPages = end - start + 1; + uint64_t nPages = end - start + 1; return nPages; } @@ -103,7 +103,7 @@ struct fastrpc_buf { struct fastrpc_file *fl; void *virt; dma_addr_t phys; - ssize_t size; + size_t size; struct ion_handle *handle; struct ion_client *client; }; @@ -130,7 +130,7 @@ struct smq_invoke_ctx { int *fds; struct fastrpc_mmap **maps; struct fastrpc_buf *buf; - ssize_t used; + size_t used; struct fastrpc_file *fl; uint32_t sc; struct overlap *overs; @@ -186,9 +186,9 @@ struct fastrpc_mmap { struct sg_table *table; struct dma_buf_attachment *attach; uintptr_t phys; - ssize_t size; + size_t size; uintptr_t va; - ssize_t len; + size_t len; int refs; uintptr_t raddr; struct ion_handle *handle; @@ -231,7 +231,7 @@ static const struct fastrpc_channel_info gcinfo[NUM_CHANNELS] = { static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) { int err = 0; - struct fastrpc_file *fl = buf == 0 ? 0 : buf->fl; + struct fastrpc_file *fl = buf == NULL ? NULL : buf->fl; if (!fl) return; if (cache) { @@ -256,7 +256,8 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl) struct fastrpc_buf *buf, *free; do { struct hlist_node *n; - free = 0; + + free = NULL; spin_lock(&fl->hlock); hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { hlist_del_init(&buf->hn); @@ -285,10 +286,10 @@ static void fastrpc_mmap_add(struct fastrpc_mmap *map) } static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, - ssize_t len, struct fastrpc_mmap **ppmap) + size_t len, struct fastrpc_mmap **ppmap) { - struct fastrpc_mmap *match = 0, *map; - struct hlist_node *n; + struct fastrpc_mmap *match = NULL, *map = NULL; + struct hlist_node *n = NULL; struct fastrpc_apps *me = &gfa; spin_lock(&me->hlock); hlist_for_each_entry_safe(map, n, &me->maps, hn) { @@ -326,7 +327,7 @@ static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, static void fastrpc_mmap_free(struct fastrpc_mmap *map) { struct fastrpc_apps *me = &gfa; - struct fastrpc_file *fl; + struct fastrpc_file *fl = NULL; if (!map) return; if (map->flags == ADSP_MMAP_HEAP_ADDR) { @@ -361,12 +362,12 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map) kfree(map); } -static int fastrpc_buf_alloc(struct fastrpc_file *fl, ssize_t size, +static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, struct fastrpc_buf **obuf) { int err = 0; - struct fastrpc_buf *buf = 0, *fr = 0; - struct hlist_node *n; + struct fastrpc_buf *buf = NULL, *fr = NULL; + struct hlist_node *n = NULL; size_t len = 0; VERIFY(err, size > 0); @@ -386,7 +387,7 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, ssize_t size, *obuf = fr; return 0; } - VERIFY(err, buf = kzalloc(sizeof(*buf), GFP_KERNEL)); + VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL))); if (err) goto bail; INIT_HLIST_NODE(&buf->hn); @@ -394,7 +395,7 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, ssize_t size, buf->handle = NULL; buf->client = NULL; buf->fl = fl; - buf->virt = 0; + buf->virt = NULL; buf->phys = 0; buf->size = size; @@ -424,8 +425,8 @@ static int context_restore_interrupted(struct fastrpc_file *fl, struct smq_invoke_ctx **po) { int err = 0; - struct smq_invoke_ctx *ctx = 0, *ictx = 0; - struct hlist_node *n; + struct smq_invoke_ctx *ctx = NULL, *ictx = NULL; + struct hlist_node *n = NULL; struct fastrpc_ioctl_invoke *invoke = &invokefd->inv; spin_lock(&fl->hlock); hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { @@ -477,7 +478,7 @@ static int context_build_overlap(struct smq_invoke_ctx *ctx) ctx->overs[i].raix = i; ctx->overps[i] = &ctx->overs[i]; } - sort(ctx->overps, nbufs, sizeof(*ctx->overps), overlap_ptr_cmp, 0); + sort(ctx->overps, nbufs, sizeof(*ctx->overps), overlap_ptr_cmp, NULL); max.start = 0; max.end = 0; for (i = 0; i < nbufs; ++i) { @@ -506,7 +507,8 @@ bail: #define K_COPY_FROM_USER(err, kernel, dst, src, size) \ do {\ if (!(kernel))\ - VERIFY(err, 0 == copy_from_user((dst), (src),\ + VERIFY(err, 0 == copy_from_user((dst),\ + (void const __user *)(src),\ (size)));\ else\ memmove((dst), (src), (size));\ @@ -515,8 +517,8 @@ bail: #define K_COPY_TO_USER(err, kernel, dst, src, size) \ do {\ if (!(kernel))\ - VERIFY(err, 0 == copy_to_user((dst), (src),\ - (size)));\ + VERIFY(err, 0 == copy_to_user((void __user *)(dst), \ + (src), (size)));\ else\ memmove((dst), (src), (size));\ } while (0) @@ -529,7 +531,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, struct smq_invoke_ctx **po) { int err = 0, bufs, size = 0; - struct smq_invoke_ctx *ctx = 0; + struct smq_invoke_ctx *ctx = NULL; struct fastrpc_ctx_lst *clst = &fl->clst; struct fastrpc_ioctl_invoke *invoke = &invokefd->inv; @@ -540,7 +542,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, sizeof(*ctx->overs) * (bufs) + sizeof(*ctx->overps) * (bufs); - VERIFY(err, ctx = kzalloc(sizeof(*ctx) + size, GFP_KERNEL)); + VERIFY(err, NULL != (ctx = kzalloc(sizeof(*ctx) + size, GFP_KERNEL))); if (err) goto bail; @@ -553,7 +555,7 @@ static int context_alloc(struct fastrpc_file *fl, uint32_t kernel, ctx->overs = (struct overlap *)(&ctx->fds[bufs]); ctx->overps = (struct overlap **)(&ctx->overs[bufs]); - K_COPY_FROM_USER(err, kernel, ctx->lpra, invoke->pra, + K_COPY_FROM_USER(err, kernel, (void *)ctx->lpra, invoke->pra, bufs * sizeof(*ctx->lpra)); if (err) goto bail; @@ -656,10 +658,10 @@ static void context_list_ctor(struct fastrpc_ctx_lst *me) static void fastrpc_context_list_dtor(struct fastrpc_file *fl) { struct fastrpc_ctx_lst *clst = &fl->clst; - struct smq_invoke_ctx *ictx = 0, *ctxfree; + struct smq_invoke_ctx *ictx = NULL, *ctxfree = NULL; struct hlist_node *n; do { - ctxfree = 0; + ctxfree = NULL; spin_lock(&fl->hlock); hlist_for_each_entry_safe(ictx, n, &clst->interrupted, hn) { hlist_del_init(&ictx->hn); @@ -671,7 +673,7 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) context_free(ctxfree); } while (ctxfree); do { - ctxfree = 0; + ctxfree = NULL; spin_lock(&fl->hlock); hlist_for_each_entry_safe(ictx, n, &clst->pending, hn) { hlist_del_init(&ictx->hn); @@ -690,7 +692,7 @@ static void fastrpc_file_list_dtor(struct fastrpc_apps *me) struct fastrpc_file *fl, *free; struct hlist_node *n; do { - free = 0; + free = NULL; spin_lock(&me->hlock); hlist_for_each_entry_safe(fl, n, &me->drivers, hn) { hlist_del_init(&fl->hn); @@ -704,7 +706,7 @@ static void fastrpc_file_list_dtor(struct fastrpc_apps *me) } static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va, - ssize_t len, int mflags, struct fastrpc_mmap **ppmap); + size_t len, int mflags, struct fastrpc_mmap **ppmap); static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) { @@ -717,20 +719,20 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) int outbufs = REMOTE_SCALARS_OUTBUFS(sc); int bufs = inbufs + outbufs; uintptr_t args; - ssize_t rlen = 0, copylen = 0, metalen = 0; + size_t rlen = 0, copylen = 0, metalen = 0; int i, inh, oix; int err = 0; int mflags = 0; /* calculate size of the metadata */ - rpra = 0; + rpra = NULL; list = smq_invoke_buf_start(rpra, sc); pages = smq_phy_page_start(sc, list); ipage = pages; for (i = 0; i < bufs; ++i) { uintptr_t buf = (uintptr_t)lpra[i].buf.pv; - ssize_t len = lpra[i].buf.len; + size_t len = lpra[i].buf.len; if (ctx->fds[i] > 0) { VERIFY(err, !fastrpc_mmap_create(ctx->fl, ctx->fds[i], buf, len, mflags, @@ -742,12 +744,13 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) } ipage += 1; } - metalen = copylen = (ssize_t)&ipage[0]; + metalen = copylen = (size_t)&ipage[0]; /* calculate len requreed for copying */ for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; uintptr_t mstart, mend; - ssize_t len = lpra[i].buf.len; + size_t len = lpra[i].buf.len; + if (!len) continue; if (ctx->maps[i]) @@ -780,7 +783,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) ipage = pages; args = (uintptr_t)ctx->buf->virt + metalen; for (i = 0; i < bufs; ++i) { - ssize_t len = lpra[i].buf.len; + size_t len = lpra[i].buf.len; list[i].num = 0; list[i].pgidx = 0; if (!len) @@ -793,7 +796,8 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) for (i = 0; i < inbufs + outbufs; ++i) { struct fastrpc_mmap *map = ctx->maps[i]; uint64_t buf = ptr_to_uint64(lpra[i].buf.pv); - ssize_t len = lpra[i].buf.len; + size_t len = lpra[i].buf.len; + rpra[i].buf.pv = 0; rpra[i].buf.len = len; if (!len) @@ -801,7 +805,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) if (map) { struct vm_area_struct *vma; uintptr_t offset; - int num = buf_num_pages(buf, len); + uint64_t num = buf_num_pages(buf, len); int idx = list[i].pgidx; VERIFY(err, NULL != (vma = find_vma(current->mm, @@ -821,9 +825,9 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) for (oix = 0; oix < inbufs + outbufs; ++oix) { int i = ctx->overps[oix]->raix; struct fastrpc_mmap *map = ctx->maps[i]; - ssize_t mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; + size_t mlen = ctx->overps[oix]->mend - ctx->overps[oix]->mstart; uint64_t buf; - ssize_t len = lpra[i].buf.len; + size_t len = lpra[i].buf.len; if (!len) continue; if (map) @@ -891,7 +895,7 @@ static int put_args(uint32_t kernel, struct smq_invoke_ctx *ctx, goto bail; } else { fastrpc_mmap_free(ctx->maps[i]); - ctx->maps[i] = 0; + ctx->maps[i] = NULL; } } num = REMOTE_SCALARS_OUTHANDLES(sc); @@ -1065,7 +1069,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, uint32_t kernel, struct fastrpc_ioctl_invoke_fd *invokefd) { - struct smq_invoke_ctx *ctx = 0; + struct smq_invoke_ctx *ctx = NULL; struct fastrpc_ioctl_invoke *invoke = &invokefd->inv; int cid = fl->cid; int interrupted = 0; @@ -1139,7 +1143,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, ioctl.inv.handle = 1; ioctl.inv.sc = REMOTE_SCALARS_MAKE(0, 1, 0); ioctl.inv.pra = ra; - ioctl.fds = 0; + ioctl.fds = NULL; VERIFY(err, !(err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) @@ -1218,7 +1222,7 @@ static int fastrpc_release_current_dsp_process(struct fastrpc_file *fl) ioctl.inv.handle = 1; ioctl.inv.sc = REMOTE_SCALARS_MAKE(1, 1, 0); ioctl.inv.pra = ra; - ioctl.fds = 0; + ioctl.fds = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); return err; @@ -1264,7 +1268,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, else ioctl.inv.sc = REMOTE_SCALARS_MAKE(2, 2, 1); ioctl.inv.pra = ra; - ioctl.fds = 0; + ioctl.fds = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); map->raddr = (uintptr_t)routargs.vaddrout; @@ -1301,7 +1305,7 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, ioctl.inv.handle = 1; ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1); ioctl.inv.pra = ra; - ioctl.fds = 0; + ioctl.fds = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); @@ -1328,7 +1332,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, struct { int pid; uintptr_t vaddrout; - ssize_t size; + size_t size; } inargs; if (map->flags == ADSP_MMAP_HEAP_ADDR) { VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map)); @@ -1348,7 +1352,7 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, else ioctl.inv.sc = REMOTE_SCALARS_MAKE(3, 1, 0); ioctl.inv.pra = ra; - ioctl.fds = 0; + ioctl.fds = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); @@ -1359,8 +1363,8 @@ bail: static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) { - struct fastrpc_mmap *match = 0, *map; - struct hlist_node *n; + struct fastrpc_mmap *match = NULL, *map = NULL; + struct hlist_node *n = NULL; int err = 0; struct fastrpc_apps *me = &gfa; spin_lock(&me->hlock); @@ -1384,7 +1388,7 @@ bail: } static int fastrpc_mmap_remove(struct fastrpc_file *fl, uintptr_t va, - ssize_t len, struct fastrpc_mmap **ppmap); + size_t len, struct fastrpc_mmap **ppmap); static void fastrpc_mmap_add(struct fastrpc_mmap *map); @@ -1392,7 +1396,7 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, struct fastrpc_ioctl_munmap *ud) { int err = 0; - struct fastrpc_mmap *map = 0; + struct fastrpc_mmap *map = NULL; if (!fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)) { @@ -1408,10 +1412,10 @@ bail: } static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, - ssize_t len, int mflags, struct fastrpc_mmap **ppmap) + size_t len, int mflags, struct fastrpc_mmap **ppmap) { - struct fastrpc_mmap *match = 0, *map; - struct hlist_node *n; + struct fastrpc_mmap *match = NULL, *map = NULL; + struct hlist_node *n = NULL; if (mflags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_apps *me = &gfa; @@ -1446,10 +1450,10 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, return -ENOTTY; } -static int dma_alloc_memory(phys_addr_t *region_start, ssize_t size) +static int dma_alloc_memory(phys_addr_t *region_start, size_t size) { struct fastrpc_apps *me = &gfa; - void *vaddr = 0; + void *vaddr = NULL; DEFINE_DMA_ATTRS(attrs); dma_set_attr(DMA_ATTR_SKIP_ZEROING, &attrs); @@ -1465,10 +1469,10 @@ static int dma_alloc_memory(phys_addr_t *region_start, ssize_t size) } static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va, - ssize_t len, int mflags, struct fastrpc_mmap **ppmap) + size_t len, int mflags, struct fastrpc_mmap **ppmap) { int err = 0; - struct fastrpc_mmap *map = 0; + struct fastrpc_mmap *map = NULL; struct fastrpc_apps *me = &gfa; unsigned long ionflag = 0; size_t pa_len = 0; @@ -1488,7 +1492,7 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, uintptr_t va, map->fd = fd; if (mflags == ADSP_MMAP_HEAP_ADDR) { map->apps = me; - map->fl = 0; + map->fl = NULL; VERIFY(err, !dma_alloc_memory(®ion_start, len)); if (err) goto bail; @@ -1523,7 +1527,7 @@ bail: static int fastrpc_internal_mmap(struct fastrpc_file *fl, struct fastrpc_ioctl_mmap *ud) { - struct fastrpc_mmap *map = 0; + struct fastrpc_mmap *map = NULL; int err = 0; if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin, ud->size, ud->flags, &map)) @@ -1551,7 +1555,7 @@ static void fastrpc_channel_close(struct kref *kref) ctx = container_of(kref, struct fastrpc_chan_ctx, kref); smd_close(ctx->chan); - ctx->chan = 0; + ctx->chan = NULL; mutex_unlock(&me->smd_mutex); cid = ctx - &me->channel[0]; pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name, @@ -1563,7 +1567,7 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl); static int fastrpc_file_free(struct fastrpc_file *fl) { struct hlist_node *n; - struct fastrpc_mmap *map = 0; + struct fastrpc_mmap *map = NULL; int cid; if (!fl) @@ -1589,7 +1593,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) static int fastrpc_device_release(struct inode *inode, struct file *file) { fastrpc_file_free((struct fastrpc_file *)file->private_data); - file->private_data = 0; + file->private_data = NULL; return 0; } @@ -1598,7 +1602,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) int cid = MINOR(inode->i_rdev); int err = 0; struct fastrpc_apps *me = &gfa; - struct fastrpc_file *fl = 0; + struct fastrpc_file *fl = NULL; VERIFY(err, fl = kzalloc(sizeof(*fl), GFP_KERNEL)); if (err) @@ -1620,7 +1624,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) fl->ssrcount = me->channel[cid].ssrcount; if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) || - (me->channel[cid].chan == 0)) { + (me->channel[cid].chan == NULL)) { VERIFY(err, !smd_named_open_on_edge(FASTRPC_SMD_GUID, gcinfo[cid].channel, &me->channel[cid].chan, @@ -1669,7 +1673,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, p.invokefd.fds = 0; size = (ioctl_num == FASTRPC_IOCTL_INVOKE) ? sizeof(p.invokefd.inv) : sizeof(p.invokefd); - VERIFY(err, 0 == copy_from_user(&p.invokefd, param, size)); + K_COPY_FROM_USER(err, 0, &p.invokefd, param, size); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, fl->mode, @@ -1678,20 +1682,20 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, goto bail; break; case FASTRPC_IOCTL_MMAP: - VERIFY(err, 0 == copy_from_user(&p.mmap, param, - sizeof(p.mmap))); + K_COPY_FROM_USER(err, 0, &p.mmap, param, + sizeof(p.mmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p.mmap))); if (err) goto bail; - VERIFY(err, 0 == copy_to_user(param, &p.mmap, sizeof(p.mmap))); + K_COPY_TO_USER(err, 0, param, &p.mmap, sizeof(p.mmap)); if (err) goto bail; break; case FASTRPC_IOCTL_MUNMAP: - VERIFY(err, 0 == copy_from_user(&p.munmap, param, - sizeof(p.munmap))); + K_COPY_FROM_USER(err, 0, &p.munmap, param, + sizeof(p.munmap)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl, @@ -1711,8 +1715,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, } break; case FASTRPC_IOCTL_INIT: - VERIFY(err, 0 == copy_from_user(&p.init, param, - sizeof(p.init))); + K_COPY_FROM_USER(err, 0, &p.init, param, sizeof(p.init)); if (err) goto bail; VERIFY(err, 0 == fastrpc_init_process(fl, &p.init)); @@ -1743,7 +1746,7 @@ static int fastrpc_restart_notifier_cb(struct notifier_block *nb, ctx->ssrcount++; if (ctx->chan) { smd_close(ctx->chan); - ctx->chan = 0; + ctx->chan = NULL; pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name, MAJOR(me->dev_no), cid); } @@ -1791,10 +1794,10 @@ static struct platform_driver adsp_memory_driver = { static int __init fastrpc_device_init(void) { struct fastrpc_apps *me = &gfa; - struct device_node *node; - struct platform_device *pdev; - struct iommu_group *group; - struct iommu_domain *domain; + struct device_node *node = NULL; + struct platform_device *pdev = NULL; + struct iommu_group *group = NULL; + struct iommu_domain *domain = NULL; int err = 0, i; memset(me, 0, sizeof(*me)); diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index ee324dcf91f0..160ad1851c9a 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014,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 @@ -33,7 +33,7 @@ struct compat_remote_buf { compat_uptr_t pv; /* buffer pointer */ - compat_ssize_t len; /* length of buffer */ + compat_size_t len; /* length of buffer */ }; union compat_remote_arg { @@ -56,13 +56,13 @@ struct compat_fastrpc_ioctl_mmap { compat_int_t fd; /* ion fd */ compat_uint_t flags; /* flags for dsp to map with */ compat_uptr_t vaddrin; /* optional virtual address */ - compat_ssize_t size; /* size */ + compat_size_t size; /* size */ compat_uptr_t vaddrout; /* dsps virtual address */ }; struct compat_fastrpc_ioctl_munmap { compat_uptr_t vaddrout; /* address to unmap */ - compat_ssize_t size; /* size */ + compat_size_t size; /* size */ }; struct compat_fastrpc_ioctl_init { @@ -81,7 +81,7 @@ static int compat_get_fastrpc_ioctl_invoke( unsigned int cmd) { compat_uint_t u, sc; - compat_ssize_t s; + compat_size_t s; compat_uptr_t p; struct fastrpc_ioctl_invoke_fd *inv; union compat_remote_arg *pra32; @@ -164,7 +164,7 @@ static int compat_get_fastrpc_ioctl_mmap( { compat_uint_t u; compat_int_t i; - compat_ssize_t s; + compat_size_t s; compat_uptr_t p; int err; @@ -198,7 +198,7 @@ static int compat_get_fastrpc_ioctl_munmap( struct fastrpc_ioctl_munmap __user *unmap) { compat_uptr_t p; - compat_ssize_t s; + compat_size_t s; int err; err = get_user(p, &unmap32->vaddrout); diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index 3be29916f99b..722d1fa7f0a2 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-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 @@ -93,7 +93,7 @@ do {\ struct remote_buf64 { uint64_t pv; - int64_t len; + uint64_t len; }; union remote_arg64 { @@ -126,25 +126,25 @@ struct fastrpc_ioctl_invoke_fd { struct fastrpc_ioctl_init { uint32_t flags; /* one of FASTRPC_INIT_* macros */ - uintptr_t __user file; /* pointer to elf file */ - int32_t filelen; /* elf file length */ + uintptr_t file; /* pointer to elf file */ + uint32_t filelen; /* elf file length */ int32_t filefd; /* ION fd for the file */ - uintptr_t __user mem; /* mem for the PD */ - int32_t memlen; /* mem length */ + uintptr_t mem; /* mem for the PD */ + uint32_t memlen; /* mem length */ int32_t memfd; /* ION fd for the mem */ }; struct fastrpc_ioctl_munmap { uintptr_t vaddrout; /* address to unmap */ - ssize_t size; /* size */ + size_t size; /* size */ }; struct fastrpc_ioctl_mmap { int fd; /* ion fd */ uint32_t flags; /* flags for dsp to map with */ - uintptr_t __user *vaddrin; /* optional virtual address */ - ssize_t size; /* size */ + uintptr_t vaddrin; /* optional virtual address */ + size_t size; /* size */ uintptr_t vaddrout; /* dsps virtual address */ }; @@ -183,14 +183,15 @@ struct smq_invoke_rsp { static inline struct smq_invoke_buf *smq_invoke_buf_start(remote_arg64_t *pra, uint32_t sc) { - int len = REMOTE_SCALARS_LENGTH(sc); + unsigned int len = REMOTE_SCALARS_LENGTH(sc); + return (struct smq_invoke_buf *)(&pra[len]); } static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc, struct smq_invoke_buf *buf) { - int nTotal = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); + uint32_t nTotal = REMOTE_SCALARS_INBUFS(sc)+REMOTE_SCALARS_OUTBUFS(sc); return (struct smq_phy_page *)(&buf[nTotal]); } From 8f53ffbee2cfeadec6b64223b50610a87507b9b5 Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Fri, 5 Jan 2018 11:03:42 +0530 Subject: [PATCH 42/45] clocksource: arch_timer: Disable user access to the physical counter Disable user access to physical counter. This reverts commit 63cb2598d5ba ("clocksource: arch_timer: Enable user access to the physical counter"). This could potentially break the userspace applications using physical counters; but all those usages should move to using virtual counter, to get the timing information. Change-Id: I653816a93515507a400ff23dbaa4442bf614a79b Signed-off-by: Neeraj Upadhyay --- drivers/clocksource/arm_arch_timer.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index efffeedfb7c2..5f1f2f164b14 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -313,14 +313,12 @@ static void arch_counter_set_user_access(void) { u32 cntkctl = arch_timer_get_cntkctl(); - /* Disable user access to the timers */ + /* Disable user access to the timers and the physical counter */ /* Also disable virtual event stream */ cntkctl &= ~(ARCH_TIMER_USR_PT_ACCESS_EN | ARCH_TIMER_USR_VT_ACCESS_EN - | ARCH_TIMER_VIRT_EVT_EN); - - /* Enable user access to the physical counter */ - cntkctl |= ARCH_TIMER_USR_PCT_ACCESS_EN; + | ARCH_TIMER_VIRT_EVT_EN + | ARCH_TIMER_USR_PCT_ACCESS_EN); /* Enable user access to the virtual counter */ if (IS_ENABLED(CONFIG_ARM_ARCH_TIMER_VCT_ACCESS)) From a031f627fb15cfc094c8b7957382b2343168ad4e Mon Sep 17 00:00:00 2001 From: Neeraj Upadhyay Date: Wed, 10 Jan 2018 11:52:37 +0530 Subject: [PATCH 43/45] arm: traps: emulate a MRRC instruction reading CNTVCT register In addition to emulating CNTPCT access, emulate CNTVCT access too, so that userspace can get CNTVCT value, if the direct counter read is disabled. Also, keep direct access disabled by default for userspace. Change-Id: I70263c129386314880cb28d1e561146ce62d52b8 Signed-off-by: Neeraj Upadhyay --- arch/arm/include/asm/traps.h | 2 +- arch/arm/kernel/traps.c | 24 +++++++++++++----------- arch/arm64/include/asm/traps.h | 2 +- drivers/clocksource/Kconfig | 2 +- drivers/clocksource/arm_arch_timer.c | 2 +- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h index f9e412b97fbf..91aba35a3f5a 100644 --- a/arch/arm/include/asm/traps.h +++ b/arch/arm/include/asm/traps.h @@ -46,7 +46,7 @@ static inline int in_exception_text(unsigned long ptr) return in ? : __in_irqentry_text(ptr); } -extern void get_pct_hook_init(void); +extern void get_timer_count_hook_init(void); extern void __init early_trap_init(void *); extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame); extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs); diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index d539cc066330..7708310c73c6 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -734,12 +734,13 @@ late_initcall(arm_mrc_hook_init); #endif -static int get_pct_trap(struct pt_regs *regs, unsigned int instr) +static int get_timer_count_trap(struct pt_regs *regs, unsigned int instr) { - u64 cntpct; + u64 cval; unsigned int res; int rd = (instr >> 12) & 0xF; int rn = (instr >> 16) & 0xF; + int read_virtual = (instr >> 4) & 1; res = arm_check_condition(instr, regs->ARM_cpsr); if (res == ARM_OPCODE_CONDTEST_FAIL) { @@ -749,26 +750,27 @@ static int get_pct_trap(struct pt_regs *regs, unsigned int instr) if (rd == 15 || rn == 15) return 1; - cntpct = arch_counter_get_cntpct(); - regs->uregs[rd] = cntpct; - regs->uregs[rn] = cntpct >> 32; + cval = read_virtual ? + arch_counter_get_cntvct() : arch_counter_get_cntpct(); + regs->uregs[rd] = cval; + regs->uregs[rn] = cval >> 32; regs->ARM_pc += 4; return 0; } -static struct undef_hook get_pct_hook = { - .instr_mask = 0x0ff00fff, +static struct undef_hook get_timer_count_hook = { + .instr_mask = 0x0ff00fef, .instr_val = 0x0c500f0e, .cpsr_mask = MODE_MASK, .cpsr_val = USR_MODE, - .fn = get_pct_trap, + .fn = get_timer_count_trap, }; -void get_pct_hook_init(void) +void get_timer_count_hook_init(void) { - register_undef_hook(&get_pct_hook); + register_undef_hook(&get_timer_count_hook); } -EXPORT_SYMBOL(get_pct_hook_init); +EXPORT_SYMBOL(get_timer_count_hook_init); void __bad_xchg(volatile void *ptr, int size) { diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index 462e5dc8566b..5bd37a589c66 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -40,5 +40,5 @@ static inline int in_exception_text(unsigned long ptr) ptr < (unsigned long)&__exception_text_end; } -static inline void get_pct_hook_init(void) {} +static inline void get_timer_count_hook_init(void) {} #endif diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e05e8e9a2fe7..b1de73fde72a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -84,7 +84,7 @@ config ARM_ARCH_TIMER_EVTSTREAM config ARM_ARCH_TIMER_VCT_ACCESS bool "Support for ARM architected timer virtual counter access in userspace" - default !ARM64 + default n depends on ARM_ARCH_TIMER help This option enables support for reading the ARM architected timer's diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index efffeedfb7c2..6cacce351687 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -796,7 +796,7 @@ static void __init arch_timer_mem_init(struct device_node *np) arch_timer_detect_rate(base, np); arch_timer_mem_register(base, irq); arch_timer_common_init(); - get_pct_hook_init(); + get_timer_count_hook_init(); } CLOCKSOURCE_OF_DECLARE(armv7_arch_timer_mem, "arm,armv7-timer-mem", arch_timer_mem_init); From ae9aaa824cf24d05ff149a3e09cb18723deaa928 Mon Sep 17 00:00:00 2001 From: Bharat Pawar Date: Fri, 26 Aug 2016 17:42:44 +0530 Subject: [PATCH 44/45] Revert "Revert "ARM: dts: msm: update memory map for msm8976/8956/8952 for External release"" This reverts commit 376499ac2763303a6211252b39af1cf49fa58ebc. Change-Id: I68fa86c047a8aef975dcf349d4dc4e8da83f07c5 Signed-off-by: Bharat Pawar --- arch/arm/boot/dts/qcom/msm8952.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8956.dtsi | 4 ++-- arch/arm/boot/dts/qcom/msm8976.dtsi | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/qcom/msm8952.dtsi b/arch/arm/boot/dts/qcom/msm8952.dtsi index db131f465c99..9da8c58c1c20 100644 --- a/arch/arm/boot/dts/qcom/msm8952.dtsi +++ b/arch/arm/boot/dts/qcom/msm8952.dtsi @@ -44,7 +44,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -52,7 +52,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8956.dtsi b/arch/arm/boot/dts/qcom/msm8956.dtsi index 777488d13b9d..ca35a0ead9e2 100644 --- a/arch/arm/boot/dts/qcom/msm8956.dtsi +++ b/arch/arm/boot/dts/qcom/msm8956.dtsi @@ -69,7 +69,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86c00000 0x0 0x06a00000>; + reg = <0x0 0x86c00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -77,7 +77,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8d600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; diff --git a/arch/arm/boot/dts/qcom/msm8976.dtsi b/arch/arm/boot/dts/qcom/msm8976.dtsi index 8c0712ea1aa6..0ac86a3577bb 100644 --- a/arch/arm/boot/dts/qcom/msm8976.dtsi +++ b/arch/arm/boot/dts/qcom/msm8976.dtsi @@ -70,7 +70,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x86C00000 0x0 0x06A00000>; + reg = <0x0 0x86C00000 0x0 0x05600000>; label = "modem_mem"; }; @@ -78,7 +78,7 @@ linux,reserve-contiguous-region; linux,reserve-region; linux,remove-completely; - reg = <0x0 0x8D600000 0x0 0x1700000>; + reg = <0x0 0x8c200000 0x0 0x1700000>; label = "reloc_mem"; }; From a8b1f40acbbfb28742614ba2ad1293adcb887052 Mon Sep 17 00:00:00 2001 From: VijayaKumar T M Date: Mon, 29 Jan 2018 10:56:40 +0530 Subject: [PATCH 45/45] msm: sensor: actuator: add null pointer check for i2c array Issue: i2c_reg_tbl may be null under error condition when set param. then, other actuator function still may use the i2c_reg_tbl as null. Fix: 1) the assignment total_steps follow on kmalloc buffer. 2) Add NULL pointer check for i2c tbl. CRs-Fixed: 2152401 Change-Id: Ieec3d88e6dae0177787da0906f53d59ac4f5a624 Signed-off-by: Haibin Liu Signed-off-by: VijayaKumar T M --- .../camera_v2/sensor/actuator/msm_actuator.c | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) mode change 100755 => 100644 drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c 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 old mode 100755 new mode 100644 index 4a6e57d8d7a2..ec38a6783c2d --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -56,6 +56,11 @@ static int32_t msm_actuator_piezo_set_default_focus( struct msm_camera_i2c_reg_setting reg_setting; CDBG("Enter\n"); + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return -EFAULT; + } + if (a_ctrl->curr_step_pos != 0) { a_ctrl->i2c_tbl_index = 0; a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl, @@ -532,6 +537,11 @@ static int32_t msm_actuator_piezo_move_focus( return -EFAULT; } + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return -EFAULT; + } + if (dest_step_position > a_ctrl->total_steps) { pr_err("Step pos greater than total steps = %d\n", dest_step_position); @@ -594,6 +604,10 @@ static int32_t msm_actuator_move_focus( pr_err("Invalid direction = %d\n", dir); return -EFAULT; } + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return -EFAULT; + } if (dest_step_pos > a_ctrl->total_steps) { pr_err("Step pos greater than total steps = %d\n", dest_step_pos); @@ -1158,6 +1172,18 @@ static int32_t msm_actuator_set_position( return -EFAULT; } + if (!a_ctrl || !a_ctrl->func_tbl || + !a_ctrl->func_tbl->actuator_parse_i2c_params || + !a_ctrl->i2c_reg_tbl) { + pr_err("failed. NULL actuator pointers."); + return -EFAULT; + } + + if (a_ctrl->actuator_state != ACT_ENABLE_STATE) { + pr_err("failed. Invalid actuator state."); + return -EFAULT; + } + a_ctrl->i2c_tbl_index = 0; hw_params = set_pos->hw_params; for (index = 0; index < set_pos->number_of_steps; index++) { @@ -1248,12 +1274,10 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, a_ctrl->region_size = set_info->af_tuning_params.region_size; a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step; - a_ctrl->total_steps = set_info->af_tuning_params.total_steps; if (copy_from_user(&a_ctrl->region_params, (void *)set_info->af_tuning_params.region_params, a_ctrl->region_size * sizeof(struct region_params_t))) { - a_ctrl->total_steps = 0; pr_err("Error copying region_params\n"); return -EFAULT; } @@ -1286,6 +1310,7 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, (a_ctrl->i2c_reg_tbl != NULL)) { kfree(a_ctrl->i2c_reg_tbl); } + a_ctrl->i2c_reg_tbl = NULL; a_ctrl->i2c_reg_tbl = kzalloc(sizeof(struct msm_camera_i2c_reg_array) * @@ -1295,6 +1320,8 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, return -ENOMEM; } + a_ctrl->total_steps = set_info->af_tuning_params.total_steps; + if (copy_from_user(&a_ctrl->reg_tbl, (void *)set_info->actuator_params.reg_tbl_params, a_ctrl->reg_tbl_size *