summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Bestas <mkbestas@lineageos.org>2022-11-05 17:51:13 +0200
committerMichael Bestas <mkbestas@lineageos.org>2022-11-05 17:51:13 +0200
commit7dbda95466d5447b89c0209f0086815bbecc5e2f (patch)
tree706dcb52841614b589db43dbc4d9b62d6a6c4c79
parent369119e5df4e48f1e737791e781da185b7810921 (diff)
parent67887f6ac3f11fd5ee1639e18d854e6071e58c51 (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.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8996pro.dtsi1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig8
-rw-r--r--drivers/char/adsprpc.c11
-rw-r--r--drivers/char/diag/diag_dci.c20
-rw-r--r--drivers/crypto/msm/qce50.c12
-rw-r--r--drivers/gpu/msm/adreno.c3
-rw-r--r--drivers/gpu/msm/adreno.h7
-rw-r--r--drivers/gpu/msm/adreno_compat.c9
-rw-r--r--drivers/gpu/msm/adreno_dispatch.c4
-rw-r--r--drivers/gpu/msm/adreno_ioctl.c9
-rw-r--r--drivers/gpu/msm/adreno_sysfs.c33
-rw-r--r--drivers/gpu/msm/kgsl.c34
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c10
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c8
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h7
-rw-r--r--drivers/soc/qcom/hab/hab.h8
-rw-r--r--drivers/soc/qcom/hab/hab_msg.c59
-rw-r--r--drivers/staging/android/ion/msm/msm_ion.c31
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(&current->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);