diff options
| author | Michael Bestas <mkbestas@lineageos.org> | 2022-11-05 17:51:13 +0200 |
|---|---|---|
| committer | Michael Bestas <mkbestas@lineageos.org> | 2022-11-05 17:51:13 +0200 |
| commit | 7dbda95466d5447b89c0209f0086815bbecc5e2f (patch) | |
| tree | 706dcb52841614b589db43dbc4d9b62d6a6c4c79 | |
| parent | 369119e5df4e48f1e737791e781da185b7810921 (diff) | |
| parent | 67887f6ac3f11fd5ee1639e18d854e6071e58c51 (diff) | |
Merge tag 'LA.UM.8.4.c25-06600-8x98.0' of https://git.codelinaro.org/clo/la/kernel/msm-4.4 into android13-4.4-msm8998
"LA.UM.8.4.c25-06600-8x98.0"
* tag 'LA.UM.8.4.c25-06600-8x98.0' of https://git.codelinaro.org/clo/la/kernel/msm-4.4:
diag: Prevent out of bound write while sending dci pkt to remote
diag: Ensure dci entry is valid before sending the packet
ion: Fix integer overflow in msm_ion_custom_ioctl
diag: Use valid data_source for a valid token
msm: kgsl: Remove 'fd' dependency to get dma_buf handle
msm: kgsl: Fix gpuaddr_in_range() to check upper bound
msm: adsprpc: Handle UAF in fastrpc debugfs read
msm: kgsl: Add a sysfs node to control performance counter reads
msm: kgsl: Perform cache flush on the pages obtained using get_user_pages()
soc: qcom: hab: Add sanity check for payload_count
msm: kgsl: Fix out of bound write in adreno_profile_submit_time
futex: Fix inode life-time issue
futex: Handle faults correctly for PI futexes
futex: Simplify fixup_pi_state_owner()
futex: Use pi_state_update_owner() in put_pi_state()
rtmutex: Remove unused argument from rt_mutex_proxy_unlock()
futex: Provide and use pi_state_update_owner()
futex: Replace pointless printk in fixup_owner()
futex: Avoid violating the 10th rule of futex
futex: Rework inconsistent rt_mutex/futex_q state
futex: Remove rt_mutex_deadlock_account_*()
futex,rt_mutex: Provide futex specific rt_mutex API
msm: adsprpc: Handle UAF in process shell memory
Disable TRACER Check to improve Camera Performance
msm: kgsl: Deregister gpu address on memdesc_sg_virt failure
crypto: Fix possible stack out-of-bound error
msm: kgsl: Correct the refcount on current process PID.
msm: kgsl: Compare pid pointer instead of TGID for a new process
qcom,max-freq-level change for trial
msm: kgsl: Protect the memdesc->gpuaddr in SVM use cases.
msm: kgsl: Stop using memdesc->usermem.
Conflicts:
drivers/char/adsprpc.c
drivers/char/diag/diag_dci.c
drivers/gpu/msm/kgsl.c
drivers/gpu/msm/kgsl_debugfs.c
drivers/gpu/msm/kgsl_iommu.c
drivers/gpu/msm/kgsl_mmu.c
drivers/gpu/msm/kgsl_sharedmem.c
drivers/gpu/msm/kgsl_trace.h
kernel/futex.c
kernel/locking/rtmutex.c
kernel/locking/rtmutex_common.h
Change-Id: I777ee96b855e2967ef6733e603d12f40174974d0
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm8996-v3.dtsi | 1 | ||||
| -rw-r--r-- | arch/arm/boot/dts/qcom/msm8996pro.dtsi | 1 | ||||
| -rw-r--r-- | arch/arm64/configs/msmcortex_defconfig | 8 | ||||
| -rw-r--r-- | drivers/char/adsprpc.c | 11 | ||||
| -rw-r--r-- | drivers/char/diag/diag_dci.c | 20 | ||||
| -rw-r--r-- | drivers/crypto/msm/qce50.c | 12 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno.h | 7 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_compat.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_dispatch.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_ioctl.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/msm/adreno_sysfs.c | 33 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl.c | 34 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_iommu.c | 10 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_mmu.c | 8 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_mmu.h | 7 | ||||
| -rw-r--r-- | drivers/soc/qcom/hab/hab.h | 8 | ||||
| -rw-r--r-- | drivers/soc/qcom/hab/hab_msg.c | 59 | ||||
| -rw-r--r-- | drivers/staging/android/ion/msm/msm_ion.c | 31 |
19 files changed, 222 insertions, 53 deletions
diff --git a/arch/arm/boot/dts/qcom/msm8996-v3.dtsi b/arch/arm/boot/dts/qcom/msm8996-v3.dtsi index 8e46ce5277b3..ae44b88d6927 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-v3.dtsi @@ -788,7 +788,6 @@ }; qcom,msm-thermal { msm_thermal_freq: qcom,vdd-apps-rstr{ - qcom,max-freq-level = <1190400>; qcom,levels = <1036800 1555200 1555200>; }; qcom,vdd-gfx-rstr{ diff --git a/arch/arm/boot/dts/qcom/msm8996pro.dtsi b/arch/arm/boot/dts/qcom/msm8996pro.dtsi index f140e78a16d7..d0949d70c3ca 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996pro.dtsi @@ -1332,7 +1332,6 @@ qcom,limit-temp = <80>; qcom,core-limit-temp = <90>; msm_thermal_freq: qcom,vdd-apps-rstr { - qcom,max-freq-level = <1209600>; qcom,levels = <1056000 1516800 1516800>; }; qcom,vdd-gfx-rstr{ diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index a37953ad33c5..a127dfa00726 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -704,11 +704,11 @@ CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y CONFIG_IPC_LOGGING=y CONFIG_QCOM_RTB=y CONFIG_QCOM_RTB_SEPARATE_CPUS=y -CONFIG_FUNCTION_TRACER=y +#CONFIG_FUNCTION_TRACER=y CONFIG_PREEMPTIRQ_EVENTS=y -CONFIG_IRQSOFF_TRACER=y -CONFIG_PREEMPT_TRACER=y -CONFIG_BLK_DEV_IO_TRACE=y +#CONFIG_IRQSOFF_TRACER=y +#CONFIG_PREEMPT_TRACER=y +#CONFIG_BLK_DEV_IO_TRACE=y CONFIG_CPU_FREQ_SWITCH_PROFILER=y CONFIG_LKDTM=y CONFIG_MEMTEST=y diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index b5b239eb6dc3..69bfaa0bc6f4 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -2747,6 +2747,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, char *fileinfo = NULL; char single_line[UL_SIZE] = "----------------"; char title[UL_SIZE] = "========================="; + unsigned long irq_flags = 0; fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL); if (!fileinfo) @@ -2809,6 +2810,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + spin_lock_irqsave(&me->hlock, irq_flags); hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n", @@ -2816,18 +2818,21 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, (uint32_t)gmaps->size, gmaps->va); } + spin_unlock_irqrestore(&me->hlock, irq_flags); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20s|%-20s|%-20s|%-20s\n", "len", "refs", "raddr", "flags"); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + spin_lock_irqsave(&me->hlock, irq_flags); hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "0x%-18X|%-20d|%-20lu|%-20u\n", (uint32_t)gmaps->len, gmaps->refs, gmaps->raddr, gmaps->flags); } + spin_unlock_irqrestore(&me->hlock, irq_flags); } else { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n%s %13s %d\n", "cid", ":", fl->cid); @@ -2869,6 +2874,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + mutex_lock(&fl->map_mutex); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "0x%-20lX|0x%-20llX|0x%-20zu\n\n", @@ -2878,6 +2884,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%s %d\n\n", "DEV_MINOR:", fl->dev_minor); } + mutex_unlock(&fl->map_mutex); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20s|%-20s|%-20s|%-20s\n", "len", "refs", @@ -2886,23 +2893,27 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + mutex_lock(&fl->map_mutex); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20zu|%-20d|0x%-20lX|%-20d\n\n", map->len, map->refs, map->raddr, map->uncached); } + mutex_unlock(&fl->map_mutex); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20s|%-20s\n", "secure", "attr"); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%s%s%s%s%s\n", single_line, single_line, single_line, single_line, single_line); + mutex_lock(&fl->map_mutex); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "%-20d|0x%-20lX\n\n", map->secure, map->attr); } + mutex_unlock(&fl->map_mutex); len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n%s %s %s\n", title, " LIST OF PENDING SMQCONTEXTS ", title); diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 973bc3b1c5b5..ed52ebbb786a 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -1,4 +1,5 @@ /* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -1615,7 +1616,6 @@ static int diag_send_dci_pkt(struct diag_cmd_reg_t *entry, return -EIO; } - mutex_lock(&driver->dci_mutex); /* prepare DCI packet */ header.start = CONTROL_CHAR; header.version = 1; @@ -1634,7 +1634,6 @@ static int diag_send_dci_pkt(struct diag_cmd_reg_t *entry, diag_update_pkt_buffer(driver->apps_dci_buf, write_len, DCI_PKT_TYPE); diag_update_sleeping_process(entry->pid, DCI_PKT_TYPE); - mutex_unlock(&driver->dci_mutex); return DIAG_DCI_NO_ERROR; } @@ -1654,7 +1653,6 @@ static int diag_send_dci_pkt(struct diag_cmd_reg_t *entry, entry->proc); status = DIAG_DCI_SEND_DATA_FAIL; } - mutex_unlock(&driver->dci_mutex); return status; } @@ -1734,7 +1732,16 @@ static int diag_send_dci_pkt_remote(unsigned char *data, int len, int tag, write_len += dci_header_size; *(int *)(buf + write_len) = tag; write_len += sizeof(int); - memcpy(buf + write_len, data, len); + if ((write_len + len) < DIAG_MDM_BUF_SIZE) { + memcpy(buf + write_len, data, len); + } else { + pr_err("diag: skip writing invalid length packet, token: %d, pkt_len: %d\n", + token, (write_len + len)); + spin_lock_irqsave(&driver->dci_mempool_lock, flags); + diagmem_free(driver, buf, dci_ops_tbl[token].mempool); + spin_unlock_irqrestore(&driver->dci_mempool_lock, flags); + return -EAGAIN; + } write_len += len; *(buf + write_len) = CONTROL_CHAR; /* End Terminator */ write_len += sizeof(uint8_t); @@ -2115,8 +2122,11 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len) if (temp_entry) { reg_item = container_of(temp_entry, struct diag_cmd_reg_t, entry); - ret = diag_send_dci_pkt(reg_item, req_buf, req_len, + mutex_lock(&driver->dci_mutex); + if (req_entry) + ret = diag_send_dci_pkt(reg_item, req_buf, req_len, req_entry->tag); + mutex_unlock(&driver->dci_mutex); } else { DIAG_LOG(DIAG_DEBUG_DCI, "Command not found: %02x %02x %02x\n", reg_entry.cmd_code, reg_entry.subsys_id, diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 7740a8c59126..3f8c512e0cd9 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -1,6 +1,6 @@ /* Qualcomm Crypto Engine driver. * - * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018, 2020-2021 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 @@ -866,6 +866,11 @@ static int _ce_setup_cipher(struct qce_device *pce_dev, struct qce_req *creq, break; case CIPHER_ALG_3DES: if (creq->mode != QCE_MODE_ECB) { + if (ivsize > MAX_IV_LENGTH) { + pr_err("%s: error: Invalid length parameter\n", + __func__); + return -EINVAL; + } _byte_stream_to_net_words(enciv32, creq->iv, ivsize); pce = cmdlistinfo->encr_cntr_iv; pce->data = enciv32[0]; @@ -914,6 +919,11 @@ static int _ce_setup_cipher(struct qce_device *pce_dev, struct qce_req *creq, } } if (creq->mode != QCE_MODE_ECB) { + if (ivsize > MAX_IV_LENGTH) { + pr_err("%s: error: Invalid length parameter\n", + __func__); + return -EINVAL; + } if (creq->mode == QCE_MODE_XTS) _byte_stream_swap_to_net_words(enciv32, creq->iv, ivsize); diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 172d8a2c6136..a2249cda051e 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1,4 +1,5 @@ /* Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -1016,6 +1017,8 @@ static int adreno_probe(struct platform_device *pdev) adreno_debugfs_init(adreno_dev); adreno_profile_init(adreno_dev); + adreno_dev->perfcounter = false; + adreno_sysfs_init(adreno_dev); kgsl_pwrscale_init(&pdev->dev, CONFIG_QCOM_ADRENO_DEFAULT_GOVERNOR); diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 5434cfb4083b..1868b0d5ec0a 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1,4 +1,5 @@ /* Copyright (c) 2008-2018,2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -439,6 +440,12 @@ struct adreno_device { struct list_head active_list; spinlock_t active_list_lock; + + /* + * @perfcounter: Flag to clear perfcounters across contexts and + * controls perfcounter ioctl read + */ + bool perfcounter; }; /** diff --git a/drivers/gpu/msm/adreno_compat.c b/drivers/gpu/msm/adreno_compat.c index 5a8d587d4536..faaec90ba74a 100644 --- a/drivers/gpu/msm/adreno_compat.c +++ b/drivers/gpu/msm/adreno_compat.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -229,6 +230,14 @@ static long adreno_ioctl_perfcounter_read_compat( struct kgsl_perfcounter_read_compat *read32 = data; struct kgsl_perfcounter_read read; + /* + * When performance counter zapping is enabled, the counters are cleared + * across context switches. Reading the counters when they are zapped is + * not permitted. + */ + if (!adreno_dev->perfcounter) + return -EPERM; + read.reads = (struct kgsl_perfcounter_read_group __user *) (uintptr_t)read32->reads; read.count = read32->count; diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 5209f1b2a2e6..3c804ca09371 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1,4 +1,5 @@ /* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -1149,7 +1150,8 @@ static inline bool _verify_ib(struct kgsl_device_private *dev_priv, } /* Make sure that the address is mapped */ - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr)) { + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, ib->gpuaddr, + ib->size)) { pr_context(device, context, "ctxt %d invalid ib gpuaddr %llX\n", context->id, ib->gpuaddr); return false; diff --git a/drivers/gpu/msm/adreno_ioctl.c b/drivers/gpu/msm/adreno_ioctl.c index 0d5e3e094c36..579ba2b61863 100644 --- a/drivers/gpu/msm/adreno_ioctl.c +++ b/drivers/gpu/msm/adreno_ioctl.c @@ -1,4 +1,5 @@ /* Copyright (c) 2002,2007-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -76,6 +77,14 @@ static long adreno_ioctl_perfcounter_read(struct kgsl_device_private *dev_priv, struct adreno_device *adreno_dev = ADRENO_DEVICE(dev_priv->device); struct kgsl_perfcounter_read *read = data; + /* + * When performance counter zapping is enabled, the counters are cleared + * across context switches. Reading the counters when they are zapped is + * not permitted. + */ + if (!adreno_dev->perfcounter) + return -EPERM; + return (long) adreno_perfcounter_read_group(adreno_dev, read->reads, read->count); } diff --git a/drivers/gpu/msm/adreno_sysfs.c b/drivers/gpu/msm/adreno_sysfs.c index f893b29e816e..a6c179f7c932 100644 --- a/drivers/gpu/msm/adreno_sysfs.c +++ b/drivers/gpu/msm/adreno_sysfs.c @@ -1,4 +1,5 @@ /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -233,6 +234,31 @@ static unsigned int _lm_show(struct adreno_device *adreno_dev) return test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag); } +static unsigned int _perfcounter_show(struct adreno_device *adreno_dev) +{ + return adreno_dev->perfcounter; +} + +static int _perfcounter_store(struct adreno_device *adreno_dev, + unsigned int val) +{ + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + + if (adreno_dev->perfcounter == val) + return 0; + + mutex_lock(&device->mutex); + + /* Power down the GPU before changing the state */ + kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND); + adreno_dev->perfcounter = val; + kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER); + + mutex_unlock(&device->mutex); + + return 0; +} + static ssize_t _sysfs_store_u32(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -327,6 +353,7 @@ static ADRENO_SYSFS_BOOL(lm); static ADRENO_SYSFS_BOOL(preemption); static ADRENO_SYSFS_BOOL(hwcg); static ADRENO_SYSFS_BOOL(throttling); +static ADRENO_SYSFS_BOOL(perfcounter); @@ -343,6 +370,7 @@ static const struct device_attribute *_attr_list[] = { &adreno_attr_preemption.attr, &adreno_attr_hwcg.attr, &adreno_attr_throttling.attr, + &adreno_attr_perfcounter.attr, NULL, }; @@ -499,8 +527,11 @@ int adreno_sysfs_init(struct adreno_device *adreno_dev) ret = kgsl_create_device_sysfs_files(device->dev, _attr_list); /* Add the PPD directory and files */ - if (ret == 0) + if (ret == 0) { + /* Notify userspace */ + kobject_uevent(&device->dev->kobj, KOBJ_ADD); ppd_sysfs_init(adreno_dev); + } return 0; } diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index bda0afed50b6..fc6ab898ccaa 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -1,4 +1,5 @@ /* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -1273,7 +1274,7 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr) if (!private) return NULL; - if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr)) + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr, 0)) return NULL; spin_lock(&private->mem_lock); @@ -2183,6 +2184,15 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, unsigned long useraddr) ret = sg_alloc_table_from_pages(memdesc->sgt, pages, npages, 0, memdesc->size, GFP_KERNEL); + + if (ret) + goto out; + + ret = kgsl_cache_range_op(memdesc, 0, memdesc->size, + KGSL_CACHE_OP_FLUSH); + + if (ret) + sg_free_table(memdesc->sgt); out: if (ret) { for (i = 0; i < npages; i++) @@ -2231,15 +2241,6 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, return ret; } -static int match_file(const void *p, struct file *file, unsigned int fd) -{ - /* - * We must return fd + 1 because iterate_fd stops searching on - * non-zero return, but 0 is a valid fd. - */ - return (p == file) ? (fd + 1) : 0; -} - static void _setup_cache_mode(struct kgsl_mem_entry *entry, struct vm_area_struct *vma) { @@ -2278,8 +2279,6 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, vma = find_vma(current->mm, hostptr); if (vma && vma->vm_file) { - int fd; - ret = check_vma_flags(vma, entry->memdesc.flags); if (ret) { up_read(¤t->mm->mmap_sem); @@ -2295,10 +2294,13 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, return -EFAULT; } - /* Look for the fd that matches this the vma file */ - fd = iterate_fd(current->files, 0, match_file, vma->vm_file); - if (fd != 0) - dmabuf = dma_buf_get(fd - 1); + /* + * Take a refcount because dma_buf_put() decrements the + * refcount + */ + get_file(vma->vm_file); + + dmabuf = vma->vm_file->private_data; } if (IS_ERR_OR_NULL(dmabuf)) { diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 98537730cbc9..31e8a7ea5f65 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1,4 +1,5 @@ /* Copyright (c) 2011-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -2525,20 +2526,21 @@ static int kgsl_iommu_svm_range(struct kgsl_pagetable *pagetable, } static bool kgsl_iommu_addr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { struct kgsl_iommu_pt *pt = pagetable->priv; if (gpuaddr == 0) return false; - if (gpuaddr >= pt->va_start && gpuaddr < pt->va_end) + if (gpuaddr >= pt->va_start && (gpuaddr + size) < pt->va_end) return true; - if (gpuaddr >= pt->compat_va_start && gpuaddr < pt->compat_va_end) + if (gpuaddr >= pt->compat_va_start && + (gpuaddr + size) < pt->compat_va_end) return true; - if (gpuaddr >= pt->svm_start && gpuaddr < pt->svm_end) + if (gpuaddr >= pt->svm_start && (gpuaddr + size) < pt->svm_end) return true; return false; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index d0a45e713d0d..228f3396ae90 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -1,4 +1,5 @@ /* Copyright (c) 2002,2007-2017,2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -606,10 +607,11 @@ enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device) EXPORT_SYMBOL(kgsl_mmu_get_mmutype); bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { if (PT_OP_VALID(pagetable, addr_in_range)) - return pagetable->pt_ops->addr_in_range(pagetable, gpuaddr); + return pagetable->pt_ops->addr_in_range(pagetable, + gpuaddr, size); return false; } @@ -645,7 +647,7 @@ EXPORT_SYMBOL(kgsl_mmu_get_qtimer_global_entry); */ static bool nommu_gpuaddr_in_range(struct kgsl_pagetable *pagetable, - uint64_t gpuaddr) + uint64_t gpuaddr, uint64_t size) { return (gpuaddr != 0) ? true : false; } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index 505fe591a53e..fcf3b188f9f7 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -1,4 +1,5 @@ /* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -99,7 +100,8 @@ struct kgsl_mmu_pt_ops { int (*set_svm_region)(struct kgsl_pagetable *, uint64_t, uint64_t); int (*svm_range)(struct kgsl_pagetable *, uint64_t *, uint64_t *, uint64_t); - bool (*addr_in_range)(struct kgsl_pagetable *pagetable, uint64_t); + bool (*addr_in_range)(struct kgsl_pagetable *pagetable, + uint64_t, uint64_t); int (*mmu_map_offset)(struct kgsl_pagetable *pt, uint64_t virtaddr, uint64_t virtoffset, struct kgsl_memdesc *memdesc, uint64_t physoffset, @@ -187,7 +189,8 @@ unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, u64 ttbr0, uint64_t addr); enum kgsl_mmutype kgsl_mmu_get_mmutype(struct kgsl_device *device); -bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr); +bool kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, uint64_t gpuaddr, + uint64_t size); int kgsl_mmu_get_region(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size); diff --git a/drivers/soc/qcom/hab/hab.h b/drivers/soc/qcom/hab/hab.h index cb7ed52050b2..bdc8f54b08b4 100644 --- a/drivers/soc/qcom/hab/hab.h +++ b/drivers/soc/qcom/hab/hab.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, 2021, 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 @@ -98,6 +98,12 @@ enum hab_payload_type { /* make sure concascaded name is less than this value */ #define MAX_VMID_NAME_SIZE 30 +/* + * The maximum value of payload_count in struct export_desc + * Max u32_t size_bytes from hab_ioctl.h(0xFFFFFFFF) / page size(0x1000) + */ +#define MAX_EXP_PAYLOAD_COUNT 0xFFFFF + #define HABCFG_FILE_SIZE_MAX 256 #define HABCFG_MMID_AREA_MAX (MM_ID_MAX/100) diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c index 9f92074665df..4494cfbf0e0b 100644 --- a/drivers/soc/qcom/hab/hab_msg.c +++ b/drivers/soc/qcom/hab/hab_msg.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, 2021, 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 @@ -11,6 +11,7 @@ * */ #include "hab.h" +#include "hab_grantable.h" static int hab_rx_queue_empty(struct virtual_channel *vchan) { @@ -207,6 +208,8 @@ int hab_msg_recv(struct physical_channel *pchan, struct export_desc *exp_desc = NULL, exp_ack = {0}; struct timeval tv = {0}; unsigned long long rx_mpm_tv = 0; + size_t exp_desc_size_expected = 0; + struct compressed_pfns *pfn_table = NULL; /* get the local virtual channel if it isn't an open message */ if (payload_type != HAB_PAYLOAD_TYPE_INIT && @@ -295,8 +298,11 @@ int hab_msg_recv(struct physical_channel *pchan, break; case HAB_PAYLOAD_TYPE_EXPORT: - if (sizebytes > HAB_HEADER_SIZE_MASK) { - pr_err("%s exp size too large %zd header %zd\n", + exp_desc_size_expected = sizeof(struct export_desc) + + sizeof(struct compressed_pfns); + if (sizebytes > (size_t)HAB_HEADER_SIZE_MASK) || + sizebytes < exp_desc_size_expected) { + pr_err("%s exp size too large/small %zu header %zu\n", pchan->name, sizebytes, sizeof(*exp_desc)); break; } @@ -328,6 +334,53 @@ int hab_msg_recv(struct physical_channel *pchan, hab_export_enqueue(vchan, exp_desc); /* for local use */ hab_send_export_ack(vchan, pchan, &exp_ack); /* ack exporter */ + /* + * We should do all the checks here. + * But in order to improve performance, we put the + * checks related to exp->payload_count and + * pfn_table->region[i].size into function pages_list_create. + * So any potential usage of such data from the remote side + * after the checks here and before the checks in + * pages_list_create needs to add some more checks if necessary. + */ + pfn_table = (struct compressed_pfns *)exp_desc->payload; + if (pfn_table->nregions <= 0 || + (pfn_table->nregions > + SIZE_MAX / sizeof(struct region)) || + (SIZE_MAX - exp_desc_size_expected < + pfn_table->nregions * sizeof(struct region))) { + pr_err("%s nregions is too large or negative, nregions:%d!\n", + pchan->name, pfn_table->nregions); + kfree(exp_desc); + break; + } + + if (pfn_table->nregions > exp_desc->payload_count) { + pr_err("%s nregions %d greater than payload_count %d\n", + pchan->name, pfn_table->nregions, + exp_desc->payload_count); + kfree(exp_desc); + break; + } + + if (exp_desc->payload_count > MAX_EXP_PAYLOAD_COUNT) { + pr_err("payload_count out of range: %d size overflow\n", + exp_desc->payload_count); + kfree(exp_desc); + break; + } + + exp_desc_size_expected += + pfn_table->nregions * sizeof(struct region); + if (sizebytes != exp_desc_size_expected) { + pr_err("%s exp size not equal %zu expect %zu\n", + pchan->name, sizebytes, exp_desc_size_expected); + kfree(exp_desc); + break; + } + + hab_export_enqueue(vchan, exp_desc); + hab_send_export_ack(vchan, pchan, exp_desc); break; case HAB_PAYLOAD_TYPE_EXPORT_ACK: diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c index 1a3aca407c9e..0a61301385f2 100644 --- a/drivers/staging/android/ion/msm/msm_ion.c +++ b/drivers/staging/android/ion/msm/msm_ion.c @@ -628,6 +628,9 @@ static int check_vaddr_bounds(unsigned long start, unsigned long end) struct vm_area_struct *vma; int ret = 1; + if (!start) + goto out; + if (end < start) goto out; @@ -781,20 +784,28 @@ long msm_ion_custom_ioctl(struct ion_client *client, down_read(&mm->mmap_sem); - start = (unsigned long)data.flush_data.vaddr + - data.flush_data.offset; - end = start + data.flush_data.length; - - if (start && check_vaddr_bounds(start, end)) { - pr_err("%s: virtual address %pK is out of bounds\n", + if ((unsigned long)data.flush_data.vaddr > + (ULONG_MAX - data.flush_data.offset)) { + pr_err("%s: Integer overflow detected for %pK\n", __func__, data.flush_data.vaddr); ret = -EINVAL; } else { - ret = ion_do_cache_op( - client, handle, data.flush_data.vaddr, - data.flush_data.offset, - data.flush_data.length, cmd); + start = (unsigned long)data.flush_data.vaddr + + data.flush_data.offset; + end = start + data.flush_data.length; + + if (check_vaddr_bounds(start, end)) { + pr_err("%s: virtual address %pK is out of bounds\n", + __func__, data.flush_data.vaddr); + ret = -EINVAL; + } else { + ret = ion_do_cache_op( + client, handle, data.flush_data.vaddr, + data.flush_data.offset, + data.flush_data.length, cmd); + } } + up_read(&mm->mmap_sem); ion_free_nolock(client, handle); |
