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编辑  收藏  举报

导航