Linux内核中各种鉴权
一、编译阶段
1. BUILD_BUG 系列
主要定义在 include/linux/build_bug.h 文件中,若编译期发现不合法就报错并中止编译。
(1) BUILD_BUG_ON(condition)
#define BUILD_BUG_ON(condition) BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
若条件为真就报错并中止编译,但需要在使用文件的顶行 #define __OPTIMIZE__ 才会生效。相关的还有:
/* 条件cond为真就编译报错且打印msg指定的信息 */ #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) /* 只要代码被编译住了,就报错 */ #define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed")
使用举例:
//kernel中使用: #define OEM_DATA_SIZE_ASSERT(oem_struct, k_struct) BUILD_BUG_ON(sizeof(oem_struct) > sizeof(((k_struct *)0)->android_oem_data1)) //触发了则编译期报错:ERROR: modpost: "__compiletime_assert_597" [kernel/oem_cpu/sched/oem_sched_optimize.ko] undefined! OEM_DATA_SIZE_ASSERT(struct oem_task_struct, struct task_struct); OEM_DATA_SIZE_ASSERT(struct oem_rq, struct rq); //也可以这样定义 #define OEM_DATA_SIZE_ASSERT(oem_struct, k_struct) BUILD_BUG_ON_ZERO(!!(sizeof(oem_struct) > sizeof(((k_struct *)0)->android_oem_data1))) //若触发了则编译期报错: error: negative width in bit-field ‘<anonymous>’
(2) BUILD_BUG_ON_ZERO(e)
#define BUILD_BUG_ON_ZERO(e) ((int)(sizeof(struct { int:(-!!(e)); })))
若条件e为真,则强制编译报错。这个没有什么依赖,可以直接拿来使用。
(3) 若常量表达式n不是2的次方,强制编译报错。也是依赖于 #define __OPTIMIZE__ 才会生效。
#define __BUILD_BUG_ON_NOT_POWER_OF_2(n) BUILD_BUG_ON(((n) & ((n) - 1)) != 0) #define BUILD_BUG_ON_NOT_POWER_OF_2(n) BUILD_BUG_ON((n) == 0 || (((n) & ((n) - 1)) != 0))
二、运行阶段-锁相关
1. lockdep_assert_held(),判断执行当前函数时指定spin_lock是否处于锁定状态。需要使能 CONFIG_LOCKDEP 宏才起作用,默认不使能。由于其还依赖其它feature,因此通常通过配置 CONFIG_LOCK_STAT=y 来使能。
lockdep_assert_held(&spin_lock); //使用举例: __assign_cfs_rq_runtime lockdep_assert_held(&cfs_b->lock);
除了此函数外,还有一些列相关函数:
lockdep_assert_irqs_enabled(); //需要使能 CONFIG_PROVE_LOCKING lockdep_assert_irqs_enabled() lockdep_assert_in_irq() lockdep_assert_preemption_enabled() lockdep_assert_preemption_disabled() lockdep_assert_in_softirq()
使用举例:
static void __unqueue_futex(struct futex_q *q) { if (WARN_ON_SMP(!q->lock_ptr) || WARN_ON(plist_node_empty(&q->list))) return; lockdep_assert_held(q->lock_ptr); ... }
三、运行阶段-判断上下文
1. assert当前是否关中断的
lockdep_assert_irqs_disabled(); //include/linux/lockdep.h 需要使能 CONFIG_PROVE_LOCKING
四、运行阶段-BUG_ON()系列
1. 主要定义在 include/asm-generic/bug.h 中,若执行时发现条件不满足,就直接panic.
BUG(); //直接panic打印栈回溯 BUG_ON(condition) //若条件为真,则BUG() WARN(condition, format...) WARN_ONCE(condition, format...) WARN_ON(condition); WARN_ON_ONCE(condition); WARN_TAINT(condition, taint, format...) WARN_TAINT_ONCE(condition, taint, format...)
BUG() 是通过brk中断来触发栈回溯的(相关注释见 arch/arm64/include/asm/brk-imm.h)
[ 1167.217429] sh: Call trace: [ 1167.217448] sh: dump_backtrace.cfi_jt+0x0/0x8 [ 1167.217465] sh: show_stack+0x1c/0x2c [ 1167.217482] sh: dump_stack_lvl+0xc4/0x140 [ 1167.217494] sh: dump_stack+0x1c/0x2c [ 1167.217586] sh: mrdump_common_die+0x2c4/0x3a8 [mrdump] [ 1167.217668] sh: ipanic_die+0x24/0x38 [mrdump] [ 1167.217690] sh: notify_die+0x8c/0x118 [ 1167.217705] sh: __die+0x80/0x240 [ 1167.217718] sh: die+0x6c/0x108 [ 1167.217733] sh: bug_handler+0x48/0xf4 [ 1167.217747] sh: brk_handler+0x9c/0x17c [ 1167.217762] sh: do_debug_exception+0xe0/0x1d8 [ 1167.217777] sh: el1_dbg+0x38/0x58 [ 1167.217792] sh: el1_sync_handler+0x40/0x8c [ 1167.217804] sh: el1_sync+0x8c/0x140 //BUG()会触发brk中断然后导致栈回溯 [ 1167.217863] sh: proc_my_test_write+0x35c/0x3e8 [my_test] //在这里面加 BUG() 并触发
五、运行阶段-合法地址检测
1. access_ok
检验一块内存是否是有效的用户空间地址。对系统调用传下来的地址必须进行检查。
// arch/arm64/include/asm/uaccess.h /* * Test whether a block of memory is a valid user space address. * Returns 1 if the range is valid, 0 otherwise. * * This is equivalent to the following test: * (u65)addr + (u65)size <= (u65)TASK_SIZE_MAX */ #define access_ok(addr, size) __range_ok(addr, size)
六、运行阶段-CPU检查
WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
posted on 2022-07-09 17:19 Hello-World3 阅读(917) 评论(0) 编辑 收藏 举报