Merge "msm: camera: Do not increment refcount when buffer is already mapped" into msm-4.9
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index e21ed36..4a8d06d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -11,6 +11,7 @@
*/
#include "smb1355.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/{
qrd_batterydata: qcom,battery-data {
@@ -18,6 +19,34 @@
#include "fg-gen3-batterydata-itech-3000mah.dtsi"
#include "fg-gen3-batterydata-ascent-3450mah.dtsi"
};
+
+ aliases {
+ serial0 = &qupv3_se9_2uart;
+ spi0 = &qupv3_se8_spi;
+ i2c0 = &qupv3_se10_i2c;
+ i2c1 = &qupv3_se3_i2c;
+ hsuart0 = &qupv3_se6_4uart;
+ };
+};
+
+&qupv3_se9_2uart {
+ status = "ok";
+};
+
+&qupv3_se8_spi {
+ status = "ok";
+};
+
+&qupv3_se3_i2c {
+ status = "ok";
+};
+
+&qupv3_se10_i2c {
+ status = "ok";
+};
+
+&qupv3_se6_4uart {
+ status = "ok";
};
&pmi8998_fg {
@@ -39,3 +68,53 @@
qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
};
};
+
+&ufsphy_mem {
+ compatible = "qcom,ufs-phy-qmp-v3";
+
+ vdda-phy-supply = <&pm8998_l1>; /* 0.88v */
+ vdda-pll-supply = <&pm8998_l26>; /* 1.2v */
+ vdda-phy-max-microamp = <62900>;
+ vdda-pll-max-microamp = <18300>;
+
+ status = "ok";
+};
+
+&ufshc_mem {
+ vdd-hba-supply = <&ufs_phy_gdsc>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pm8998_l20>;
+ vccq2-supply = <&pm8998_s4>;
+ vcc-max-microamp = <600000>;
+ vccq2-max-microamp = <600000>;
+
+ qcom,vddp-ref-clk-supply = <&pm8998_l2>;
+ qcom,vddp-ref-clk-max-microamp = <100>;
+
+ status = "ok";
+};
+
+&ufsphy_card {
+ compatible = "qcom,ufs-phy-qmp-v3";
+
+ vdda-phy-supply = <&pm8998_l1>; /* 0.88v */
+ vdda-pll-supply = <&pm8998_l26>; /* 1.2v */
+ vdda-phy-max-microamp = <62900>;
+ vdda-pll-max-microamp = <18300>;
+
+ status = "ok";
+};
+
+&ufshc_card {
+ vdd-hba-supply = <&ufs_card_gdsc>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pm8998_l21>;
+ vccq2-supply = <&pm8998_s4>;
+ vcc-max-microamp = <300000>;
+ vccq2-max-microamp = <300000>;
+
+ qcom,vddp-ref-clk-supply = <&pm8998_l2>;
+ qcom,vddp-ref-clk-max-microamp = <100>;
+
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index b8018b6..95c1d65 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1678,6 +1678,11 @@
compatible = "qcom,msm-imem-kaslr_offset";
reg = <0x6d0 12>;
};
+
+ diag_dload@c8 {
+ compatible = "qcom,msm-imem-diag-dload";
+ reg = <0xc8 200>;
+ };
};
qcom,venus@aae0000 {
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 40e775a..837bbab 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -1953,20 +1953,32 @@ EXPORT_SYMBOL(arm_iommu_release_mapping);
*
* Attaches specified io address space mapping to the provided device,
* this replaces the dma operations (dma_map_ops pointer) with the
- * IOMMU aware version. More than one client might be attached to
- * the same io address space mapping.
+ * IOMMU aware version. Only one device in an iommu_group may use this
+ * function.
*/
int arm_iommu_attach_device(struct device *dev,
struct dma_iommu_mapping *mapping)
{
int err;
int s1_bypass = 0, is_fast = 0;
+ struct iommu_group *group;
+
+ group = dev->iommu_group;
+ if (!group) {
+ dev_err(dev, "No iommu associated with device\n");
+ return -ENODEV;
+ }
+
+ if (iommu_get_domain_for_dev(dev)) {
+ dev_err(dev, "Device already attached to other iommu_domain\n");
+ return -EINVAL;
+ }
iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
if (is_fast)
return fast_smmu_attach_device(dev, mapping);
- err = iommu_attach_device(mapping->domain, dev);
+ err = iommu_attach_group(mapping->domain, group);
if (err)
return err;
@@ -1994,6 +2006,7 @@ void arm_iommu_detach_device(struct device *dev)
{
struct dma_iommu_mapping *mapping;
int is_fast, s1_bypass = 0;
+ struct iommu_group *group;
mapping = to_dma_iommu_mapping(dev);
if (!mapping) {
@@ -2013,7 +2026,13 @@ void arm_iommu_detach_device(struct device *dev)
if (msm_dma_unmap_all_for_dev(dev))
dev_warn(dev, "IOMMU detach with outstanding mappings\n");
- iommu_detach_device(mapping->domain, dev);
+ group = dev->iommu_group;
+ if (!group) {
+ dev_err(dev, "No iommu associated with device\n");
+ return;
+ }
+
+ iommu_detach_group(mapping->domain, group);
kref_put(&mapping->kref, release_iommu_mapping);
dev->archdata.mapping = NULL;
if (!s1_bypass)
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index b18a172..ee847d9f 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -306,7 +306,6 @@ static struct fastrpc_channel_ctx gcinfo[NUM_CHANNELS] = {
.subsys = "slpi",
.link.link_info.edge = "dsps",
.link.link_info.transport = "smem",
- .vmid = VMID_SSC_Q6,
},
{
.name = "cdsprpc-smd",
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index aded314..8ba6da4 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -730,6 +730,7 @@ int fast_smmu_attach_device(struct device *dev,
{
int atomic_domain = 1;
struct iommu_domain *domain = mapping->domain;
+ struct iommu_group *group;
struct iommu_pgtbl_info info;
u64 size = (u64)mapping->bits << PAGE_SHIFT;
@@ -746,7 +747,18 @@ int fast_smmu_attach_device(struct device *dev,
mapping->fast->domain = domain;
mapping->fast->dev = dev;
- if (iommu_attach_device(domain, dev))
+ group = dev->iommu_group;
+ if (!group) {
+ dev_err(dev, "No iommu associated with device\n");
+ return -ENODEV;
+ }
+
+ if (iommu_get_domain_for_dev(dev)) {
+ dev_err(dev, "Device already attached to other iommu_domain\n");
+ return -EINVAL;
+ }
+
+ if (iommu_attach_group(mapping->domain, group))
return -EINVAL;
if (iommu_domain_get_attr(domain, DOMAIN_ATTR_PGTBL_INFO,
@@ -781,7 +793,7 @@ EXPORT_SYMBOL(fast_smmu_attach_device);
void fast_smmu_detach_device(struct device *dev,
struct dma_iommu_mapping *mapping)
{
- iommu_detach_device(mapping->domain, dev);
+ iommu_detach_group(mapping->domain, dev->iommu_group);
dev->archdata.mapping = NULL;
set_dma_ops(dev, NULL);
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 181e889..bea5f03 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -548,7 +548,7 @@ static void iommu_debug_device_profiling(struct seq_file *s, struct device *dev,
}
}
- if (iommu_attach_device(domain, dev)) {
+ if (iommu_attach_group(domain, dev->iommu_group)) {
seq_puts(s,
"Couldn't attach new domain to device. Is it already attached?\n");
goto out_domain_free;
@@ -669,7 +669,7 @@ static void iommu_debug_device_profiling(struct seq_file *s, struct device *dev,
}
out_detach:
- iommu_detach_device(domain, dev);
+ iommu_detach_group(domain, dev->iommu_group);
out_domain_free:
iommu_domain_free(domain);
}
@@ -1451,6 +1451,8 @@ static const struct file_operations iommu_debug_functional_arm_dma_api_fops = {
static int iommu_debug_attach_do_attach(struct iommu_debug_device *ddev,
int val, bool is_secure)
{
+ struct iommu_group *group = ddev->dev->iommu_group;
+
ddev->domain = iommu_domain_alloc(&platform_bus_type);
if (!ddev->domain) {
pr_err("Couldn't allocate domain\n");
@@ -1464,8 +1466,8 @@ static int iommu_debug_attach_do_attach(struct iommu_debug_device *ddev,
goto out_domain_free;
}
- if (iommu_attach_device(ddev->domain, ddev->dev)) {
- pr_err("Couldn't attach new domain to device. Is it already attached?\n");
+ if (iommu_attach_group(ddev->domain, group)) {
+ dev_err(ddev->dev, "Couldn't attach new domain to device\n");
goto out_domain_free;
}
@@ -1483,6 +1485,8 @@ static ssize_t __iommu_debug_attach_write(struct file *file,
bool is_secure)
{
struct iommu_debug_device *ddev = file->private_data;
+ struct device *dev = ddev->dev;
+ struct iommu_domain *domain;
ssize_t retval;
int val;
@@ -1494,12 +1498,15 @@ static ssize_t __iommu_debug_attach_write(struct file *file,
if (val) {
if (ddev->domain) {
- pr_err("Already attached.\n");
+ pr_err("Iommu-Debug is already attached?\n");
retval = -EINVAL;
goto out;
}
- if (WARN(ddev->dev->archdata.iommu,
- "Attachment tracking out of sync with device\n")) {
+
+ domain = iommu_get_domain_for_dev(dev);
+ if (domain) {
+ pr_err("Another driver is using this device's iommu\n"
+ "Iommu-Debug cannot be used concurrently\n");
retval = -EINVAL;
goto out;
}
@@ -1510,11 +1517,11 @@ static ssize_t __iommu_debug_attach_write(struct file *file,
pr_err("Attached\n");
} else {
if (!ddev->domain) {
- pr_err("No domain. Did you already attach?\n");
+ pr_err("Iommu-Debug is not attached?\n");
retval = -EINVAL;
goto out;
}
- iommu_detach_device(ddev->domain, ddev->dev);
+ iommu_detach_group(ddev->domain, dev->iommu_group);
iommu_domain_free(ddev->domain);
ddev->domain = NULL;
pr_err("Detached\n");
@@ -1566,7 +1573,6 @@ static ssize_t iommu_debug_attach_write_secure(struct file *file,
{
return __iommu_debug_attach_write(file, ubuf, count, offset,
true);
-
}
static const struct file_operations iommu_debug_secure_attach_fops = {
@@ -1868,6 +1874,10 @@ static int snarf_iommu_devices(struct device *dev, void *ignored)
if (!of_find_property(dev->of_node, "iommus", NULL))
return 0;
+ /* Hold a reference count */
+ if (!iommu_group_get(dev))
+ return 0;
+
ddev = kzalloc(sizeof(*ddev), GFP_KERNEL);
if (!ddev)
return -ENODEV;
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 1a65d07..d80e7f4 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -90,7 +90,7 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
done = budget - quota;
if (done < budget) {
- napi_complete(napi);
+ napi_complete_done(napi, done);
wil6210_unmask_irq_rx(wil);
wil_dbg_txrx(wil, "NAPI RX complete\n");
}
diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index 5595b7b..4e9bd64 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -764,6 +764,25 @@ static int msm_11ad_ssr_powerup(const struct subsys_desc *subsys)
return rc;
}
+static int msm_11ad_ssr_copy_ramdump(struct msm11ad_ctx *ctx)
+{
+ if (ctx->rops.ramdump && ctx->wil_handle) {
+ int rc = ctx->rops.ramdump(ctx->wil_handle, ctx->ramdump_addr,
+ WIGIG_RAMDUMP_SIZE);
+ if (rc) {
+ dev_err(ctx->dev, "ramdump failed : %d\n", rc);
+ return -EINVAL;
+ }
+ }
+
+ ctx->dump_data.version = WIGIG_DUMP_FORMAT_VER;
+ strlcpy(ctx->dump_data.name, WIGIG_SUBSYS_NAME,
+ sizeof(ctx->dump_data.name));
+
+ ctx->dump_data.magic = WIGIG_DUMP_MAGIC_VER_V1;
+ return 0;
+}
+
static int msm_11ad_ssr_ramdump(int enable, const struct subsys_desc *subsys)
{
int rc;
@@ -780,13 +799,10 @@ static int msm_11ad_ssr_ramdump(int enable, const struct subsys_desc *subsys)
if (!enable)
return 0;
- if (ctx->rops.ramdump && ctx->wil_handle) {
- rc = ctx->rops.ramdump(ctx->wil_handle, ctx->ramdump_addr,
- WIGIG_RAMDUMP_SIZE);
- if (rc) {
- dev_err(ctx->dev, "ramdump failed : %d\n", rc);
- return -EINVAL;
- }
+ if (!ctx->recovery_in_progress) {
+ rc = msm_11ad_ssr_copy_ramdump(ctx);
+ if (rc)
+ return rc;
}
memset(&segment, 0, sizeof(segment));
@@ -798,7 +814,6 @@ static int msm_11ad_ssr_ramdump(int enable, const struct subsys_desc *subsys)
static void msm_11ad_ssr_crash_shutdown(const struct subsys_desc *subsys)
{
- int rc;
struct platform_device *pdev;
struct msm11ad_ctx *ctx;
@@ -810,19 +825,8 @@ static void msm_11ad_ssr_crash_shutdown(const struct subsys_desc *subsys)
return;
}
- if (ctx->rops.ramdump && ctx->wil_handle) {
- rc = ctx->rops.ramdump(ctx->wil_handle, ctx->ramdump_addr,
- WIGIG_RAMDUMP_SIZE);
- if (rc)
- dev_err(ctx->dev, "ramdump failed : %d\n", rc);
- /* continue */
- }
-
- ctx->dump_data.version = WIGIG_DUMP_FORMAT_VER;
- strlcpy(ctx->dump_data.name, WIGIG_SUBSYS_NAME,
- sizeof(ctx->dump_data.name));
-
- ctx->dump_data.magic = WIGIG_DUMP_MAGIC_VER_V1;
+ if (!ctx->recovery_in_progress)
+ (void)msm_11ad_ssr_copy_ramdump(ctx);
}
static void msm_11ad_ssr_deinit(struct msm11ad_ctx *ctx)
@@ -901,7 +905,7 @@ static int msm_11ad_ssr_init(struct msm11ad_ctx *ctx)
static void msm_11ad_init_cpu_boost(struct msm11ad_ctx *ctx)
{
unsigned int minfreq = 0, maxfreq = 0, freq;
- int i, boost_cpu;
+ int i, boost_cpu = 0;
for_each_possible_cpu(i) {
freq = cpufreq_quick_get_max(i);
@@ -1321,6 +1325,7 @@ static int msm_11ad_notify_crash(struct msm11ad_ctx *ctx)
if (ctx->subsys) {
dev_info(ctx->dev, "SSR requested\n");
+ (void)msm_11ad_ssr_copy_ramdump(ctx);
ctx->recovery_in_progress = true;
rc = subsystem_restart_dev(ctx->subsys);
if (rc) {
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 0e9505f..1258b16 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -559,7 +559,8 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object)
shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object));
if (shadow_byte < 0 || shadow_byte >= KASAN_SHADOW_SCALE_SIZE) {
- kasan_report_double_free(cache, object, shadow_byte);
+ kasan_report_double_free(cache, object,
+ __builtin_return_address(1));
return true;
}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 1c260e6..7572917 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -104,7 +104,7 @@ static inline bool kasan_report_enabled(void)
void kasan_report(unsigned long addr, size_t size,
bool is_write, unsigned long ip);
void kasan_report_double_free(struct kmem_cache *cache, void *object,
- s8 shadow);
+ void *ip);
#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB)
void quarantine_put(struct kasan_free_meta *info, struct kmem_cache *cache);
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 073325a..35d2db8 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -48,7 +48,13 @@ static const void *find_first_bad_addr(const void *addr, size_t size)
return first_bad_addr;
}
-static void print_error_description(struct kasan_access_info *info)
+static bool addr_has_shadow(struct kasan_access_info *info)
+{
+ return (info->access_addr >=
+ kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
+}
+
+static const char *get_shadow_bug_type(struct kasan_access_info *info)
{
const char *bug_type = "unknown-crash";
u8 *shadow_addr;
@@ -95,12 +101,39 @@ static void print_error_description(struct kasan_access_info *info)
break;
}
- pr_err("BUG: KASAN: %s in %pS at addr %p\n",
- bug_type, (void *)info->ip,
- info->access_addr);
- pr_err("%s of size %zu by task %s/%d\n",
- info->is_write ? "Write" : "Read",
- info->access_size, current->comm, task_pid_nr(current));
+ return bug_type;
+}
+
+const char *get_wild_bug_type(struct kasan_access_info *info)
+{
+ const char *bug_type = "unknown-crash";
+
+ if ((unsigned long)info->access_addr < PAGE_SIZE)
+ bug_type = "null-ptr-deref";
+ else if ((unsigned long)info->access_addr < TASK_SIZE)
+ bug_type = "user-memory-access";
+ else
+ bug_type = "wild-memory-access";
+
+ return bug_type;
+}
+
+static const char *get_bug_type(struct kasan_access_info *info)
+{
+ if (addr_has_shadow(info))
+ return get_shadow_bug_type(info);
+ return get_wild_bug_type(info);
+}
+
+static void print_error_description(struct kasan_access_info *info)
+{
+ const char *bug_type = get_bug_type(info);
+
+ pr_err("BUG: KASAN: %s in %pS\n",
+ bug_type, (void *)info->ip);
+ pr_err("%s of size %zu at addr %p by task %s/%d\n",
+ info->is_write ? "Write" : "Read", info->access_size,
+ info->access_addr, current->comm, task_pid_nr(current));
}
static inline bool kernel_or_module_addr(const void *addr)
@@ -139,9 +172,9 @@ static void kasan_end_report(unsigned long *flags)
kasan_enable_current();
}
-static void print_track(struct kasan_track *track)
+static void print_track(struct kasan_track *track, const char *prefix)
{
- pr_err("PID = %u\n", track->pid);
+ pr_err("%s by task %u:\n", prefix, track->pid);
if (track->stack) {
struct stack_trace trace;
@@ -152,59 +185,84 @@ static void print_track(struct kasan_track *track)
}
}
-static void kasan_object_err(struct kmem_cache *cache, void *object)
+static struct page *addr_to_page(const void *addr)
+{
+ if ((addr >= (void *)PAGE_OFFSET) &&
+ (addr < high_memory))
+ return virt_to_head_page(addr);
+ return NULL;
+}
+
+static void describe_object_addr(struct kmem_cache *cache, void *object,
+ const void *addr)
+{
+ unsigned long access_addr = (unsigned long)addr;
+ unsigned long object_addr = (unsigned long)object;
+ const char *rel_type;
+ int rel_bytes;
+
+ pr_err("The buggy address belongs to the object at %p\n"
+ " which belongs to the cache %s of size %d\n",
+ object, cache->name, cache->object_size);
+
+ if (!addr)
+ return;
+
+ if (access_addr < object_addr) {
+ rel_type = "to the left";
+ rel_bytes = object_addr - access_addr;
+ } else if (access_addr >= object_addr + cache->object_size) {
+ rel_type = "to the right";
+ rel_bytes = access_addr - (object_addr + cache->object_size);
+ } else {
+ rel_type = "inside";
+ rel_bytes = access_addr - object_addr;
+ }
+
+ pr_err("The buggy address is located %d bytes %s of\n"
+ " %d-byte region [%p, %p)\n",
+ rel_bytes, rel_type, cache->object_size, (void *)object_addr,
+ (void *)(object_addr + cache->object_size));
+}
+
+static void describe_object(struct kmem_cache *cache, void *object,
+ const void *addr)
{
struct kasan_alloc_meta *alloc_info = get_alloc_info(cache, object);
+ if (cache->flags & SLAB_KASAN) {
+ print_track(&alloc_info->alloc_track, "Allocated");
+ pr_err("\n");
+ print_track(&alloc_info->free_track, "Freed");
+ pr_err("\n");
+ }
+
+ describe_object_addr(cache, object, addr);
+}
+
+static void print_address_description(void *addr)
+{
+ struct page *page = addr_to_page(addr);
+
dump_stack();
- pr_err("Object at %p, in cache %s size: %d\n", object, cache->name,
- cache->object_size);
+ pr_err("\n");
- if (!(cache->flags & SLAB_KASAN))
- return;
+ if (page && PageSlab(page)) {
+ struct kmem_cache *cache = page->slab_cache;
+ void *object = nearest_obj(cache, page, addr);
- pr_err("Allocated:\n");
- print_track(&alloc_info->alloc_track);
- pr_err("Freed:\n");
- print_track(&alloc_info->free_track);
-}
+ describe_object(cache, object, addr);
+ }
-void kasan_report_double_free(struct kmem_cache *cache, void *object,
- s8 shadow)
-{
- unsigned long flags;
+ if (kernel_or_module_addr(addr) && !init_task_stack_addr(addr)) {
+ pr_err("The buggy address belongs to the variable:\n");
+ pr_err(" %pS\n", addr);
+ }
- kasan_start_report(&flags);
- pr_err("BUG: Double free or freeing an invalid pointer\n");
- pr_err("Unexpected shadow byte: 0x%hhX\n", shadow);
- kasan_object_err(cache, object);
- kasan_end_report(&flags);
-}
-
-static void print_address_description(struct kasan_access_info *info)
-{
- const void *addr = info->access_addr;
-
- if ((addr >= (void *)PAGE_OFFSET) &&
- (addr < high_memory)) {
- struct page *page = virt_to_head_page(addr);
-
- if (PageSlab(page)) {
- void *object;
- struct kmem_cache *cache = page->slab_cache;
- object = nearest_obj(cache, page,
- (void *)info->access_addr);
- kasan_object_err(cache, object);
- return;
- }
+ if (page) {
+ pr_err("The buggy address belongs to the page:\n");
dump_page(page, "kasan: bad access detected");
}
-
- if (kernel_or_module_addr(addr)) {
- if (!init_task_stack_addr(addr))
- pr_err("Address belongs to variable %pS\n", addr);
- }
- dump_stack();
}
static bool row_is_guilty(const void *row, const void *guilty)
@@ -259,31 +317,34 @@ static void print_shadow_for_address(const void *addr)
}
}
+void kasan_report_double_free(struct kmem_cache *cache, void *object,
+ void *ip)
+{
+ unsigned long flags;
+
+ kasan_start_report(&flags);
+ pr_err("BUG: KASAN: double-free or invalid-free in %pS\n", ip);
+ pr_err("\n");
+ print_address_description(object);
+ pr_err("\n");
+ print_shadow_for_address(object);
+ kasan_end_report(&flags);
+}
+
static void kasan_report_error(struct kasan_access_info *info)
{
unsigned long flags;
- const char *bug_type;
kasan_start_report(&flags);
- if (info->access_addr <
- kasan_shadow_to_mem((void *)KASAN_SHADOW_START)) {
- if ((unsigned long)info->access_addr < PAGE_SIZE)
- bug_type = "null-ptr-deref";
- else if ((unsigned long)info->access_addr < TASK_SIZE)
- bug_type = "user-memory-access";
- else
- bug_type = "wild-memory-access";
- pr_err("BUG: KASAN: %s on address %p\n",
- bug_type, info->access_addr);
- pr_err("%s of size %zu by task %s/%d\n",
- info->is_write ? "Write" : "Read",
- info->access_size, current->comm,
- task_pid_nr(current));
+ print_error_description(info);
+ pr_err("\n");
+
+ if (!addr_has_shadow(info)) {
dump_stack();
} else {
- print_error_description(info);
- print_address_description(info);
+ print_address_description((void *)info->access_addr);
+ pr_err("\n");
print_shadow_for_address(info->first_bad_addr);
}