#include <linux/atomic.h>
#include "kasan.h"
#include "../slab.h"
extern struct kasan_stack_ring stack_ring;
static const char *get_common_bug_type(struct kasan_report_info *info)
{
if (info->access_addr + info->access_size < info->access_addr)
return "out-of-bounds";
return "invalid-access";
}
void kasan_complete_mode_report_info(struct kasan_report_info *info)
{
unsigned long flags;
u64 pos;
struct kasan_stack_ring_entry *entry;
bool alloc_found = false, free_found = false;
if ((!info->cache || !info->object) && !info->bug_type) {
info->bug_type = get_common_bug_type(info);
return;
}
write_lock_irqsave(&stack_ring.lock, flags);
pos = atomic64_read(&stack_ring.pos);
for (u64 i = pos - 1; i != pos - 1 - stack_ring.size; i--) {
if (alloc_found && free_found)
break;
entry = &stack_ring.entries[i % stack_ring.size];
if (kasan_reset_tag(entry->ptr) != info->object ||
get_tag(entry->ptr) != get_tag(info->access_addr) ||
info->cache->object_size != entry->size)
continue;
if (entry->is_free) {
if (free_found)
break;
memcpy(&info->free_track, &entry->track,
sizeof(info->free_track));
free_found = true;
if (!info->bug_type)
info->bug_type = "slab-use-after-free";
} else {
if (alloc_found)
break;
memcpy(&info->alloc_track, &entry->track,
sizeof(info->alloc_track));
alloc_found = true;
if (!info->bug_type)
info->bug_type = "slab-out-of-bounds";
}
}
write_unlock_irqrestore(&stack_ring.lock, flags);
if (!info->bug_type)
info->bug_type = get_common_bug_type(info);
}