Documentation/filesystems/fscrypt.rst arch/arm/common/Kconfig arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi arch/arm64/boot/dts/amd/amd-seattle-soc.dtsi arch/arm64/boot/dts/arm/juno-clocks.dtsi arch/arm64/boot/dts/broadcom/ns2.dtsi arch/arm64/boot/dts/lg/lg1312.dtsi arch/arm64/boot/dts/lg/lg1313.dtsi arch/arm64/boot/dts/marvell/armada-37xx.dtsi arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi arch/arm64/boot/dts/nvidia/tegra210.dtsi arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi arch/arm64/boot/dts/qcom/msm8996.dtsi arch/arm64/configs/ranchu64_defconfig arch/arm64/include/asm/cpucaps.h arch/arm64/kernel/cpufeature.c arch/arm64/kernel/traps.c arch/arm64/mm/mmu.c crypto/Makefile crypto/ablkcipher.c crypto/blkcipher.c crypto/testmgr.h crypto/zstd.c drivers/android/binder.c drivers/android/binder_alloc.c drivers/char/random.c drivers/clocksource/exynos_mct.c drivers/dma/pl330.c drivers/hid/hid-sony.c drivers/hid/uhid.c drivers/hid/usbhid/hiddev.c drivers/i2c/i2c-core.c drivers/md/dm-crypt.c drivers/media/v4l2-core/videobuf2-v4l2.c drivers/mmc/host/dw_mmc.c drivers/net/ethernet/broadcom/tg3.c drivers/net/usb/r8152.c drivers/scsi/scsi_logging.c drivers/scsi/sd.c drivers/scsi/ufs/ufshcd-pci.c drivers/scsi/ufs/ufshcd-pltfrm.c drivers/staging/android/Kconfig drivers/staging/android/ion/ion.c drivers/staging/android/ion/ion_priv.h drivers/staging/android/ion/ion_system_heap.c drivers/staging/android/lowmemorykiller.c drivers/tty/serial/samsung.c drivers/usb/dwc3/core.c drivers/usb/dwc3/gadget.c drivers/usb/host/xhci-hub.c drivers/video/fbdev/core/fbmon.c drivers/video/fbdev/core/modedb.c fs/crypto/fname.c fs/crypto/fscrypt_private.h fs/crypto/keyinfo.c fs/ext4/ialloc.c fs/ext4/namei.c fs/ext4/xattr.c fs/f2fs/checkpoint.c fs/f2fs/data.c fs/f2fs/debug.c fs/f2fs/dir.c fs/f2fs/f2fs.h fs/f2fs/file.c fs/f2fs/gc.c fs/f2fs/inline.c fs/f2fs/inode.c fs/f2fs/namei.c fs/f2fs/node.c fs/f2fs/recovery.c fs/f2fs/segment.c fs/f2fs/segment.h fs/f2fs/super.c fs/f2fs/sysfs.c fs/fat/dir.c fs/fat/fatent.c fs/file.c fs/namespace.c fs/pnode.c fs/proc/inode.c fs/proc/root.c fs/proc/task_mmu.c fs/sdcardfs/dentry.c fs/sdcardfs/derived_perm.c fs/sdcardfs/file.c fs/sdcardfs/inode.c fs/sdcardfs/lookup.c fs/sdcardfs/main.c fs/sdcardfs/sdcardfs.h fs/sdcardfs/super.c include/linux/blk_types.h include/linux/cpuhotplug.h include/linux/cred.h include/linux/fb.h include/linux/power_supply.h include/linux/sched.h include/linux/zstd.h include/trace/events/sched.h include/uapi/linux/android/binder.h init/Kconfig init/main.c kernel/bpf/hashtab.c kernel/cpu.c kernel/cred.c kernel/fork.c kernel/locking/spinlock_debug.c kernel/panic.c kernel/printk/printk.c kernel/sched/Makefile kernel/sched/core.c kernel/sched/fair.c kernel/sched/rt.c kernel/sched/walt.c kernel/sched/walt.h kernel/trace/trace.c lib/bug.c lib/list_debug.c lib/vsprintf.c lib/zstd/bitstream.h lib/zstd/compress.c lib/zstd/decompress.c lib/zstd/fse.h lib/zstd/fse_compress.c lib/zstd/fse_decompress.c lib/zstd/huf_compress.c lib/zstd/huf_decompress.c lib/zstd/zstd_internal.h mm/debug.c mm/filemap.c mm/rmap.c net/core/filter.c net/ipv4/sysctl_net_ipv4.c net/ipv4/sysfs_net_ipv4.c net/ipv4/tcp_input.c net/ipv4/tcp_output.c net/ipv4/udp.c net/ipv6/netfilter/nf_conntrack_reasm.c net/netfilter/Kconfig net/netfilter/Makefile net/netfilter/xt_qtaguid.c net/netfilter/xt_qtaguid_internal.h net/xfrm/xfrm_policy.c net/xfrm/xfrm_state.c scripts/checkpatch.pl security/selinux/hooks.c sound/core/compress_offload.c
193 lines
4.9 KiB
C
193 lines
4.9 KiB
C
/*
|
|
Generic support for BUG()
|
|
|
|
This respects the following config options:
|
|
|
|
CONFIG_BUG - emit BUG traps. Nothing happens without this.
|
|
CONFIG_GENERIC_BUG - enable this code.
|
|
CONFIG_GENERIC_BUG_RELATIVE_POINTERS - use 32-bit pointers relative to
|
|
the containing struct bug_entry for bug_addr and file.
|
|
CONFIG_DEBUG_BUGVERBOSE - emit full file+line information for each BUG
|
|
|
|
CONFIG_BUG and CONFIG_DEBUG_BUGVERBOSE are potentially user-settable
|
|
(though they're generally always on).
|
|
|
|
CONFIG_GENERIC_BUG is set by each architecture using this code.
|
|
|
|
To use this, your architecture must:
|
|
|
|
1. Set up the config options:
|
|
- Enable CONFIG_GENERIC_BUG if CONFIG_BUG
|
|
|
|
2. Implement BUG (and optionally BUG_ON, WARN, WARN_ON)
|
|
- Define HAVE_ARCH_BUG
|
|
- Implement BUG() to generate a faulting instruction
|
|
- NOTE: struct bug_entry does not have "file" or "line" entries
|
|
when CONFIG_DEBUG_BUGVERBOSE is not enabled, so you must generate
|
|
the values accordingly.
|
|
|
|
3. Implement the trap
|
|
- In the illegal instruction trap handler (typically), verify
|
|
that the fault was in kernel mode, and call report_bug()
|
|
- report_bug() will return whether it was a false alarm, a warning,
|
|
or an actual bug.
|
|
- You must implement the is_valid_bugaddr(bugaddr) callback which
|
|
returns true if the eip is a real kernel address, and it points
|
|
to the expected BUG trap instruction.
|
|
|
|
Jeremy Fitzhardinge <jeremy@goop.org> 2006
|
|
*/
|
|
|
|
#define pr_fmt(fmt) fmt
|
|
|
|
#include <linux/list.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/bug.h>
|
|
#include <linux/sched.h>
|
|
|
|
#ifdef CONFIG_SEC_DEBUG
|
|
#include <linux/sec_debug.h>
|
|
#endif
|
|
|
|
extern const struct bug_entry __start___bug_table[], __stop___bug_table[];
|
|
|
|
static inline unsigned long bug_addr(const struct bug_entry *bug)
|
|
{
|
|
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
|
|
return bug->bug_addr;
|
|
#else
|
|
return (unsigned long)bug + bug->bug_addr_disp;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_MODULES
|
|
/* Updates are protected by module mutex */
|
|
static LIST_HEAD(module_bug_list);
|
|
|
|
static const struct bug_entry *module_find_bug(unsigned long bugaddr)
|
|
{
|
|
struct module *mod;
|
|
const struct bug_entry *bug = NULL;
|
|
|
|
rcu_read_lock_sched();
|
|
list_for_each_entry_rcu(mod, &module_bug_list, bug_list) {
|
|
unsigned i;
|
|
|
|
bug = mod->bug_table;
|
|
for (i = 0; i < mod->num_bugs; ++i, ++bug)
|
|
if (bugaddr == bug_addr(bug))
|
|
goto out;
|
|
}
|
|
bug = NULL;
|
|
out:
|
|
rcu_read_unlock_sched();
|
|
|
|
return bug;
|
|
}
|
|
|
|
void module_bug_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
|
|
struct module *mod)
|
|
{
|
|
char *secstrings;
|
|
unsigned int i;
|
|
|
|
lockdep_assert_held(&module_mutex);
|
|
|
|
mod->bug_table = NULL;
|
|
mod->num_bugs = 0;
|
|
|
|
/* Find the __bug_table section, if present */
|
|
secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
|
|
for (i = 1; i < hdr->e_shnum; i++) {
|
|
if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table"))
|
|
continue;
|
|
mod->bug_table = (void *) sechdrs[i].sh_addr;
|
|
mod->num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry);
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Strictly speaking this should have a spinlock to protect against
|
|
* traversals, but since we only traverse on BUG()s, a spinlock
|
|
* could potentially lead to deadlock and thus be counter-productive.
|
|
* Thus, this uses RCU to safely manipulate the bug list, since BUG
|
|
* must run in non-interruptive state.
|
|
*/
|
|
list_add_rcu(&mod->bug_list, &module_bug_list);
|
|
}
|
|
|
|
void module_bug_cleanup(struct module *mod)
|
|
{
|
|
lockdep_assert_held(&module_mutex);
|
|
list_del_rcu(&mod->bug_list);
|
|
}
|
|
|
|
#else
|
|
|
|
static inline const struct bug_entry *module_find_bug(unsigned long bugaddr)
|
|
{
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
const struct bug_entry *find_bug(unsigned long bugaddr)
|
|
{
|
|
const struct bug_entry *bug;
|
|
|
|
for (bug = __start___bug_table; bug < __stop___bug_table; ++bug)
|
|
if (bugaddr == bug_addr(bug))
|
|
return bug;
|
|
|
|
return module_find_bug(bugaddr);
|
|
}
|
|
|
|
enum bug_trap_type report_bug(unsigned long bugaddr, struct pt_regs *regs)
|
|
{
|
|
const struct bug_entry *bug;
|
|
const char *file;
|
|
unsigned line, warning;
|
|
|
|
if (!is_valid_bugaddr(bugaddr))
|
|
return BUG_TRAP_TYPE_NONE;
|
|
|
|
bug = find_bug(bugaddr);
|
|
|
|
file = NULL;
|
|
line = 0;
|
|
warning = 0;
|
|
|
|
if (bug) {
|
|
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
|
#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
|
|
file = bug->file;
|
|
#else
|
|
file = (const char *)bug + bug->file_disp;
|
|
#endif
|
|
line = bug->line;
|
|
#endif
|
|
warning = (bug->flags & BUGFLAG_WARNING) != 0;
|
|
}
|
|
|
|
if (warning) {
|
|
/* this is a WARN_ON rather than BUG/BUG_ON */
|
|
__warn(file, line, (void *)bugaddr, BUG_GET_TAINT(bug), regs,
|
|
NULL);
|
|
return BUG_TRAP_TYPE_WARN;
|
|
}
|
|
|
|
printk(KERN_DEFAULT "------------[ cut here ]------------\n");
|
|
|
|
#ifdef CONFIG_SEC_DEBUG_EXTRA_INFO
|
|
if (file)
|
|
sec_debug_set_extra_info_bug(file, line);
|
|
#endif
|
|
|
|
if (file)
|
|
pr_auto(ASL1, "kernel BUG at %s:%u!\n", file, line);
|
|
else
|
|
pr_auto(ASL1, "Kernel BUG at %pB [verbose debug info unavailable]\n",
|
|
(void *)bugaddr);
|
|
|
|
return BUG_TRAP_TYPE_BUG;
|
|
}
|