Linux 安全 - LSM源码分析

文章目录

  • 前言
  • 一、简介
    • 1.1 DAC 和 MAC
    • 1.2 LSM 调用流程图
  • 二、LSM相关数据结构
    • 2.1 struct security_hook_list
    • 2.2 union security_list_options
    • 2.3 structure security_hook_heads
  • 三、security_bprm_check
  • 四、LSM 源码分析
    • 3.1 early_security_init
    • 3.2 security_init
      • 3.2.1 security_init
      • 3.2.2 ordered_lsm_init
      • 3.2.3 initialize_lsm
  • 五、LSM初始化例程
    • 5.1 selinux
    • 5.2 apparmor
  • 参考资料

前言

这篇文章介绍了LSM相关知识:Linux 安全 - LSM机制,接下来源码分析LSM模块。

一、简介

1.1 DAC 和 MAC

(1)
DAC(Discretionary Access Control)基于访问控制是一种根据主体或组的身份限制对对象访问的手段。DAC使用用户和组权限,实现访问控制。DAC的一个问题是其基本操作是可传递的。一个特权用户可以创建其他特权用户,并且这些用户可能具有对受限对象的访问权限。

传统的Linux UID/GID机制,Linux通过用户、进程、文件的UID/GID来进行权限管理的。Linux将文件的权限划分为读、写和执行三种,分别用字母r、w和x表示。每一个文件有三组读、写和执行权限,分别是针对文件的所有者(u)、文件所有者所属的组(g)以及除前两种之外的其它用户(o)。这样,如果一个用户想要将一个自己创建的文件交给另外一个用户访问,那么只需要相应地设置一下这个文件的其它用户权限位就可以了。文件的权限控制在所有者手中。

(2)
MAC(Mandatory Access Control)中,主体(例如用户、进程、线程)和对象(例如文件、套接字、内存段)都具有一组安全属性。这些安全属性通过MAC策略进行集中管理。在MAC的情况下,用户/组不做任何访问决策,而是由安全属性进行管理。

每当主体尝试访问对象时,都会由操作系统内核强 制执行授权规则–检查安全属性并决定是否可进行访问。同样,任何主体对任何对象的任何操作都将根据一组授权规则(策略)进行测试,决定操作是否被允许。

MAC提供了更严格的访问控制,它不依赖于用户或组的身份,而是根据预定义的安全策略和属性来进行访问决策。这种策略可能基于许多因素,如用户角色、标签、上下文等。通过使用MAC,可以实现更细粒度的访问控制,并提供更高的安全性,以防止特权用户滥用权限或绕过访问控制规则。

在Linux中,MAC功能由安全模块(Linux Security Module)提供,如SELinux(Security-Enhanced Linux)和AppArmor。这些安全模块通过管理对象的安全上下文和定义访问策略来实现MAC。与DAC相比,MAC提供了更强大的安全能力,特别适用于需要更严格访问控制的环境,如多用户系统、服务器和敏感数据系统。

1.2 LSM 调用流程图

LSM通过在内核代码中恰好在访问内核对象(比如inode)之前放置挂钩来调解对内核对象的访问。
在这里插入图片描述
当用户空间中的进程调用open()系统调用打开文件时,涉及以下步骤:

(1)用户空间中的进程调用open()系统调用,并提供文件路径作为参数。

(2)系统调度该系统调用,并使用提供的文件路径获取与文件关联的内核文件对象和inode对象。

(3)如果open()系统调用的参数不正确或无效,则返回错误。

(4)内核执行常规的"自主访问控制"(DAC)文件权限检查。它验证当前用户是否具有打开文件所需的权限。如果用户没有所需的权限,则终止系统调用,并将错误返回给用户空间。

(5)如果DAC检查通过,并且用户具有所需的权限,则Linux安全模块(LSM)框架开始工作。对于每个已启用的LSM,框架调用file_open钩子函数。每个LSM都有机会执行额外的安全检查或修改文件打开操作的行为。如果任何LSM钩子函数返回错误,则终止系统调用,并将错误返回给用户空间。

(6)最后,如果所有的安全检查,包括DAC和LSM钩子函数,都通过了,文件将被打开给进程。创建一个新的文件描述符,并返回给用户空间的进程,允许对已打开文件进行进一步操作。

当进程调用open()打开文件时,内核首先执行DAC文件权限检查,如果通过,然后调用LSM框架执行额外的安全检查。只有当所有的安全检查都通过后,文件才会被打开,并将文件描述符返回给进程。

从上图可以看出,LSM挂钩是在执行DAC和其他健全性检查之后应用的。

通过系统调用进入内核之后,系统首先进行传统的DAC权限检查(传统权限检查主要是基于用户的,用户通过验证之后就可以访问资源),通过之后才会进行MAC强制访问控制 ,从图上看来,LSM实现MAC强制访问控制主要通过LSM安全模块的钩子函数实现。

LSM是一种基于MAC的控制形式,常见的有SELinux/AppArmor。

以下是selinux LSM 简易图:
在这里插入图片描述
在这里插入图片描述

二、LSM相关数据结构

2.1 struct security_hook_list

struct hlist_node {struct hlist_node *next, **pprev;
};struct hlist_head {struct hlist_node *first;
};union security_list_options {.....int (*ptrace_access_check)(struct task_struct *child,unsigned int mode);......
}/** Security module hook list structure.* For use with generic list macros for common operations.*/
struct security_hook_list {struct hlist_node		list;struct hlist_head		*head;union security_list_options	hook;char				*lsm;
} __randomize_layout;

security_hook_list结构体用于表示安全模块钩子列表的结构。这个结构体被用于在通用的列表操作中进行常见操作。

结构体的成员含义:
(1)list:struct hlist_node类型的成员,用于将security_hook_list结构体链接到一个哈希链表中。哈希链表提供了高效的查找和插入操作。

(2)head:指向struct hlist_head类型的指针,指向哈希链表的头部。哈希链表的头部包含指向链表中第一个元素的指针。

(3)hook:union security_list_options类型的联合体,表示安全模块钩子的选项。这是一个通用的选项字段,具体的含义可能取决于具体的安全模块和使用场景。

(4)lsm:一个指向字符(char)类型的指针,用于存储与此安全模块钩子相关的LSM(Linux Security Module)的名称。LSM是Linux内核的安全模块架构,用于实现各种安全策略和功能。

(5)__randomize_layout:一个特殊的属性,用于在内存中随机化这个结构体的布局。这有助于增加系统的安全性,使攻击者更难利用结构体的布局来进行攻击。

这个结构体的设计使得可以使用通用的列表宏(generic list macros)对安全模块钩子进行常见操作,例如插入、删除和遍历。它提供了一种灵活的方式来管理安全模块钩子,并与其他系统组件进行交互。

2.2 union security_list_options

/*** union security_list_options - Linux Security Module hook function list** Security hooks for program execution operations.***/union security_list_options {int (*binder_set_context_mgr)(struct task_struct *mgr);int (*binder_transaction)(struct task_struct *from,struct task_struct *to);int (*binder_transfer_binder)(struct task_struct *from,struct task_struct *to);int (*binder_transfer_file)(struct task_struct *from,struct task_struct *to,struct file *file);int (*ptrace_access_check)(struct task_struct *child,unsigned int mode);int (*ptrace_traceme)(struct task_struct *parent);......
}

为LSM定义的安全挂钩的函数指针的联合,在内核代码中的各种关键路径上调用。

2.3 structure security_hook_heads

struct security_hook_heads {struct hlist_head binder_set_context_mgr;struct hlist_head binder_transaction;struct hlist_head binder_transfer_binder;struct hlist_head binder_transfer_file;struct hlist_head ptrace_access_check;struct hlist_head ptrace_traceme;......

该数据结构包含与每个钩子相对应的链表的头部,考虑到LSM的堆叠属性,从而允许它们以正确的顺序执行。

三、security_bprm_check

SYSCALL_DEFINE5(execveat-->do_execveat()-->do_execveat_common()-->__do_execve_file()--exec_binprm()-->search_binary_handler()-->security_bprm_check()
int security_bprm_check(struct linux_binprm *bprm)
{int ret;ret = call_int_hook(bprm_check_security, 0, bprm);if (ret)return ret;return ima_bprm_check(bprm);
}

函数 security_bprm_check 就是一个LSM HOOK 点,用于在执行二进制文件之前进行安全性检查。

struct security_hook_heads security_hook_heads __lsm_ro_after_init;
#define call_int_hook(FUNC, IRC, ...) ({			\int RC = IRC;						\do {							\struct security_hook_list *P;			\\hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \RC = P->hook.FUNC(__VA_ARGS__);		\if (RC != 0)				\break;				\}						\} while (0);						\RC;							\
})

宏 call_int_hook,用于调用安全模块的钩子函数。

这个宏的作用是依次调用安全模块的钩子函数,并将它们的返回值进行处理。

宏接受三个参数:
FUNC:安全模块钩子函数的名称。这个宏将通过 FUNC 参数拼接出对应的钩子函数列表的成员。
IRC:初始返回值(Initial Return Code)。这个值将被用作初始的返回值,如果所有的钩子函数都返回0,则最终的返回值将是初始返回值。
…:可变参数,用于传递给钩子函数的参数。

宏的工作流程如下:
使用 hlist_for_each_entry 宏遍历存储在 security_hook_heads.FUNC 中的钩子函数列表。
对于每个钩子函数,调用 P->hook.FUNC 并传递可变参数 __VA_ARGS__。
如果钩子函数的返回值 RC 不等于0,则跳出循环。

四、LSM 源码分析

start_kernel()-->early_security_init()-->security_init()/* Load LSMs in specified order. */-->ordered_lsm_init()-->initialize_lsm()-->lsm->init()-->selinux_init()-->apparmor_init()-->tomoyo_init()-->smack_init()

由于selinux、apparmor、tomoyo和smack都是LSM_FLAG_EXCLUSIVE 独占模式标志,因此只能选择其中的一个启动。

3.1 early_security_init

struct security_hook_heads security_hook_heads __lsm_ro_after_init;int __init early_security_init(void)
{int i;struct hlist_head *list = (struct hlist_head *) &security_hook_heads;struct lsm_info *lsm;for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);i++)INIT_HLIST_HEAD(&list[i]);for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) {if (!lsm->enabled)lsm->enabled = &lsm_enabled_true;prepare_lsm(lsm);initialize_lsm(lsm);}return 0;
}

early_security_init函数是在系统初始化过程中早期调用的安全初始化函数。

(1)将security_hook_heads的地址强制转换为struct hlist_head指针,并将其赋值给名为list的变量。security_hook_heads是一个全局变量,它存储了一组hlist_head结构体,用于存储不同安全钩子的链表头部。

(2)循环遍历security_hook_heads数组,计算需要迭代的次数。通过sizeof(security_hook_heads)除以sizeof(struct hlist_head),可以确定数组中有多少个hlist_head元素。

(3)INIT_HLIST_HEAD(&list[i]);:对list[i]所指向的hlist_head进行初始化,将其设置为空链表。

(4)循环遍历__start_early_lsm_info到__end_early_lsm_info之间的lsm_info结构体数组,这些结构体包含了早期加载的安全模块信息。

(5)调用prepare_lsm函数,对当前安全模块进行准备工作。

(6)调用initialize_lsm函数,对当前安全模块进行初始化。

总的来说,这段代码的作用是在系统初始化早期对安全模块进行初始化。它遍历安全钩子的链表头部,将每个链表头部初始化为空链表。然后,对早期加载的安全模块进行准备和初始化操作,确保它们的状态正确并可用于后续的安全处理。

3.2 security_init

3.2.1 security_init

LSM内核调用security_init进行LSM框架初始化,该初始化按以下顺序加载已启用的受支持的Linux安全模块:

– Capability module
– Minor LSMs
– Major LSM
// linux-5.4.18/include/asm-generic/vmlinux.lds.h#ifdef CONFIG_SECURITY
#define LSM_TABLE()	. = ALIGN(8);					\__start_lsm_info = .;				\KEEP(*(.lsm_info.init))				\__end_lsm_info = .;
#define EARLY_LSM_TABLE()	. = ALIGN(8);				\__start_early_lsm_info = .;			\KEEP(*(.early_lsm_info.init))			\__end_early_lsm_info = .;
// linux-5.4.18/include/linux/lsm_hooks.h/** Security blob size or offset data.*/
struct lsm_blob_sizes {int	lbs_cred;int	lbs_file;int	lbs_inode;int	lbs_ipc;int	lbs_msg_msg;int	lbs_task;
};enum lsm_order {LSM_ORDER_FIRST = -1,	/* This is only for capabilities. */LSM_ORDER_MUTABLE = 0,
};struct lsm_info {const char *name;	/* Required. */enum lsm_order order;	/* Optional: default is LSM_ORDER_MUTABLE */unsigned long flags;	/* Optional: flags describing LSM */int *enabled;		/* Optional: controlled by CONFIG_LSM */int (*init)(void);	/* Required. */struct lsm_blob_sizes *blobs; /* Optional: for blob sharing. */
};/*** security_init - initializes the security framework** This should be called early in the kernel initialization sequence.*/
int __init security_init(void)
{struct lsm_info *lsm;pr_info("Security Framework initializing\n");/** Append the names of the early LSM modules now that kmalloc() is* available*/for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) {if (lsm->enabled)lsm_append(lsm->name, &lsm_names);}/* Load LSMs in specified order. */ordered_lsm_init();return 0;
}

security_init函数用于初始化安全框架。它应该在内核初始化序列的早期调用。

(1)定义一个指向lsm_info结构体的指针变量lsm,用于遍历LSM模块的数组。循环遍历__start_early_lsm_info到__end_early_lsm_info之间的lsm_info结构体数组,这些结构体包含了早期加载的安全模块的信息。

(2)调用ordered_lsm_init函数,按照指定的顺序加载LSM模块。

这段代码的作用是初始化安全框架。它遍历早期加载的安全模块数组,将启用的模块名称追加到链表中。然后,按照指定的顺序加载LSM模块。这个函数在内核初始化的早期阶段被调用,用于确保安全框架在系统启动时得到正确的初始化。

3.2.2 ordered_lsm_init

/* Boot-time LSM user choice */
static __initdata const char *chosen_lsm_order;
static __initdata const char *chosen_major_lsm;static __initconst const char * const builtin_lsm_order = CONFIG_LSM;/* Ordered list of LSMs to initialize. */
static __initdata struct lsm_info **ordered_lsms;static void __init ordered_lsm_init(void)
{struct lsm_info **lsm;ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms),GFP_KERNEL);if (chosen_lsm_order) {if (chosen_major_lsm) {pr_info("security= is ignored because it is superseded by lsm=\n");chosen_major_lsm = NULL;}ordered_lsm_parse(chosen_lsm_order, "cmdline");} elseordered_lsm_parse(builtin_lsm_order, "builtin");for (lsm = ordered_lsms; *lsm; lsm++)prepare_lsm(*lsm);init_debug("cred blob size     = %d\n", blob_sizes.lbs_cred);init_debug("file blob size     = %d\n", blob_sizes.lbs_file);init_debug("inode blob size    = %d\n", blob_sizes.lbs_inode);init_debug("ipc blob size      = %d\n", blob_sizes.lbs_ipc);init_debug("msg_msg blob size  = %d\n", blob_sizes.lbs_msg_msg);init_debug("task blob size     = %d\n", blob_sizes.lbs_task);/** Create any kmem_caches needed for blobs*/if (blob_sizes.lbs_file)lsm_file_cache = kmem_cache_create("lsm_file_cache",blob_sizes.lbs_file, 0,SLAB_PANIC, NULL);if (blob_sizes.lbs_inode)lsm_inode_cache = kmem_cache_create("lsm_inode_cache",blob_sizes.lbs_inode, 0,SLAB_PANIC, NULL);lsm_early_cred((struct cred *) current->cred);lsm_early_task(current);for (lsm = ordered_lsms; *lsm; lsm++)initialize_lsm(*lsm);kfree(ordered_lsms);
}

ordered_lsm_init函数用于按照指定的顺序初始化LSM模块。

代码含义如下:
(1)定义一个指向lsm_info结构体指针的指针变量lsm,用于遍历LSM模块的指针数组。
(2)使用kcalloc函数为ordered_lsms分配内存,大小为LSM_COUNT + 1个指针的大小。这个数组用于存储按顺序加载的LSM模块的指针。
(3)如果存在chosen_lsm_order,表示在内核命令行中指定了LSM的加载顺序。调用ordered_lsm_parse函数解析chosen_lsm_order,解析类型为"cmdline",将解析结果存储在ordered_lsms数组中。
(4)如果没有指定chosen_lsm_order,则使用内核编译时的默认LSM加载顺序。调用ordered_lsm_parse函数解析builtin_lsm_order,解析类型为"builtin",将解析结果存储在ordered_lsms数组中。
(5)遍历ordered_lsms数组,对于每个非空指针,调用prepare_lsm函数进行LSM的准备工作。
(6)打印LSM需要的blob大小的调试信息,包括cred、file、inode、ipc、msg_msg和task blob的大小。
(7)如果blob_sizes.lbs_file不为0,使用kmem_cache_create函数创建一个名为lsm_file_cache的内存缓存,用于存储file blob。
(8)如果blob_sizes.lbs_inode不为0,使用kmem_cache_create函数创建一个名为lsm_inode_cache的内存缓存,用于存储inode blob。
(9)调用lsm_early_cred函数,传递当前进程的cred结构作为参数,进行早期的cred blob初始化。
(10)调用lsm_early_task函数,传递当前进程作为参数,进行早期的task blob初始化。
(11)再次遍历ordered_lsms数组,对于每个非空指针,调用initialize_lsm函数进行LSM的初始化。

这段代码的作用是按照指定的顺序初始化LSM模块。它根据指定的LSM加载顺序解析LSM模块,并进行准备工作和初始化。同时,它还创建了用于存储file blob和inode blob的内存缓存。在LSM初始化之前,它对cred blob和task blob进行了早期的初始化。完成初始化后,释放了用于存储LSM模块指针的内存。

3.2.3 initialize_lsm

/* Initialize a given LSM, if it is enabled. */
static void __init initialize_lsm(struct lsm_info *lsm)
{if (is_enabled(lsm)) {int ret;init_debug("initializing %s\n", lsm->name);ret = lsm->init();WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret);}
}

lsm->init()表示调用给定LSM的初始化函数。

这个函数用于初始化给定的LSM,前提是该LSM是启用的。它首先检查LSM是否启用,然后调用LSM的初始化函数:

selinux_init()
apparmor_init()
tomoyo_init()
smack_init()

五、LSM初始化例程

5.1 selinux

/* SELinux requires early initialization in order to labelall processes and objects when they are created. */
DEFINE_LSM(selinux) = {.name = "selinux",.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,.enabled = &selinux_enabled,.blobs = &selinux_blob_sizes,.init = selinux_init,
};

这段代码的作用是定义了一个名为selinux的LSM模块的信息结构体,并初始化了结构体的成员。

(1).name = “selinux”:设置了name成员,表示LSM模块的名称是"selinux"。

(2).flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE:设置了flags成员,表示LSM模块的标志。LSM_FLAG_LEGACY_MAJOR标志表示该模块是遗留的主要模块,LSM_FLAG_EXCLUSIVE标志表示该模块是独占的,不与其他模块共存。比如 selinux 不能和 apparmor 同时存在。

(3).enabled = &selinux_enabled:设置了enabled成员,指向一个名为selinux_enabled的变量。这个变量用于指示selinux模块是否启用。

(4).blobs = &selinux_blob_sizes:设置了blobs成员,指向一个名为selinux_blob_sizes的变量。这个变量用于指定selinux模块需要的各个blob的大小。

(5).init = selinux_init:设置了init成员,指向一个名为selinux_init的函数。这个函数用于初始化selinux模块。

通过DEFINE_LSM宏创建的结构体被赋值给selinux,从而定义了一个名为selinux的LSM模块的信息结构体。这个结构体包含了模块的名称、标志、启用状态、blob大小和初始化函数等信息。

DEFINE_LSM宏:

#define DEFINE_LSM(lsm)							\static struct lsm_info __lsm_##lsm				\__used __section(.lsm_info.init)			\__aligned(sizeof(unsigned long))

宏定义用于定义LSM模块的信息结构体,这个宏定义包含了以下几个部分:
(1)DEFINE_LSM(lsm):定义了一个名为DEFINE_LSM的宏,宏的参数是lsm,用于指定LSM模块的名称。

(2)static struct lsm_info _lsm##lsm:定义了一个名为__lsm_加上lsm参数的结构体,该结构体用于存储LSM模块的信息。使用static关键字使结构体具有文件作用域。

(3)__used:这是一个编译器特定的属性,用于告诉编译器即使没有使用到这个结构体,也不要优化掉它。

(4)__section(.lsm_info.init):这是一个编译器特定的属性,用于指定将这个结构体放置在名为.lsm_info.init的特定节(section)中。这个节可能是用于存放LSM模块信息的特定节。

(5)__aligned(sizeof(unsigned long)):这是一个编译器特定的属性,用于指定结构体的对齐方式。在这里,结构体的对齐方式被设置为unsigned long的大小。

这个宏定义用于创建一个静态的LSM信息结构体,该结构体存储了LSM模块的相关信息,并通过编译器的属性设置将它放置在特定的节中。这个宏定义通常用于在LSM模块的源文件中定义LSM信息结构体。

static __init int selinux_init(void)
{security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
}
/*** security_add_hooks - Add a modules hooks to the hook lists.* @hooks: the hooks to add* @count: the number of hooks to add* @lsm: the name of the security module** Each LSM has to register its hooks with the infrastructure.*/
void __init security_add_hooks(struct security_hook_list *hooks, int count,char *lsm)
{int i;for (i = 0; i < count; i++) {hooks[i].lsm = lsm;hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);}......
}
/** Security module hook list structure.* For use with generic list macros for common operations.*/
struct security_hook_list {struct hlist_node		list;struct hlist_head		*head;union security_list_options	hook;char				*lsm;
} __randomize_layout;
static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),......
}
/** Initializing a security_hook_list structure takes* up a lot of space in a source file. This macro takes* care of the common case and reduces the amount of* text involved.*/
#define LSM_HOOK_INIT(HEAD, HOOK) \{ .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }

(1)LSM_HOOK_INIT(HEAD, HOOK):定义了一个名为LSM_HOOK_INIT的宏,宏的参数是HEAD和HOOK,用于指定security_hook_list结构体的成员。

(2){ .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }:这是一个结构体初始化的语法,用于初始化security_hook_list结构体的成员。具体来说:

.head = &security_hook_heads.HEAD:初始化head成员,将其指向security_hook_heads结构体中的HEAD成员的地址。security_hook_heads是一个全局变量,用于存储各个hook链表的头部。

struct security_hook_heads {.....struct hlist_head ptrace_access_check;......
}

.hook = { .HEAD = HOOK }:初始化hook成员,其中的.HEAD = HOOK将HOOK的值赋给hook中对应的HEAD成员。这里的HEAD是一个宏参数,用于指定具体的hook函数

union security_list_options {......int (*ptrace_access_check)(struct task_struct *child,unsigned int mode);......
}

struct security_hook_heads这个全局变量用于存储各个hook链表的头部。

比如:

LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check)

等价于:

{ .head = &security_hook_heads.ptrace_access_check, .hook = { .ptrace_access_check= selinux_ptrace_access_check} }

这个宏定义用于简化初始化security_hook_list结构体的操作。通过宏调用,可以用较少的代码初始化security_hook_list结构体中的head和hook成员。

如果Linux使用的是 selinux,那么执行 exec系统调用时,执行 security_bprm_check hook点就是执行 selinux_ptrace_access_check 函数。

5.2 apparmor

apparmor 和 selinux 初始化过程相同:

DEFINE_LSM(apparmor) = {.name = "apparmor",.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,.enabled = &apparmor_enabled,.blobs = &apparmor_blob_sizes,.init = apparmor_init,
};
static int __init apparmor_init(void)
{......security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),"apparmor");......
}
static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),LSM_HOOK_INIT(capget, apparmor_capget),LSM_HOOK_INIT(capable, apparmor_capable),......
}

如果Linux使用的是 apparmor,那么执行 exec系统调用时,执行 security_bprm_check hook点就是执行 apparmor_ptrace_access_check函数。

参考资料

Linux 5.4.18

https://pwl999.blog.csdn.net/article/details/107066666
https://blog.csdn.net/feelabclihu/article/details/121059328
https://github.com/kubearmor/KubeArmor/wiki/Introduction-to-Linux-Security-Modules-(LSMs)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/99737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二证券:市场情绪或逐步修复 十月行情值得期待

第二证券指出&#xff0c;周一A股商场探底回升、小幅轰动收拾&#xff0c;沪指全天底子出现先抑后扬的运转特征。其时上证综指与创业板指数的平均市盈率分别为12.46倍、33.94倍&#xff0c;处于近三年中位数以下水平&#xff0c;商场估值仍然处于较低区域&#xff0c;合适中长期…

华为OD机考B卷 | 100分】阿里巴巴找黄金宝箱(JAVA题解——也许是全网最详)

前言 本人是算法小白&#xff0c;甚至也没有做过Leetcode。所以&#xff0c;我相信【同为菜鸡的我更能理解作为菜鸡的你们的痛点】。 题干 1. 题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上&#xff0c;无意中发现了强盗集团的藏宝地&#xff0c;藏宝地有编号从0~N的箱子&…

【C++设计模式之责任链模式:行为型】分析及示例

简介 责任链模式是一种行为型设计模式&#xff0c;它允许将请求沿着处理链传递&#xff0c;直到有一个处理器能够处理该请求。这种模式将请求的发送者和接收者解耦&#xff0c;同时提供了更高的灵活性和可扩展性。 描述 责任链模式由多个处理器组成一个处理链&#xff0c;每…

香橙派、树莓派、核桃派、鲁班猫安装jupyter notebook【ubuntu、Debian开发板操作类似】

文章目录 前言一、安装环境二、使用方法总结 前言 香橙派树莓派鲁班猫安装一下调试代码还是比较方便的。 一、安装环境 假设已经安装好了miniconda3。如果还没安装可以参考我另外一篇博文&#xff0c;有写怎么安装。 pip install jupyter notebook # 生成Jupyter Notebook的…

算法题:K 次取反后最大化的数组和(典型的贪心算法问题)

这道题没有看题解&#xff0c;直接提交&#xff0c;成绩超越99.5%&#xff0c;说明思路是优的。就是考虑的情况里面弯弯绕比较多&#xff0c;需要考虑全面一点。&#xff08;本题完整题目附在了最后面&#xff09; 具体思路如下&#xff1a; 1、首先排序&#xff0c;然后从最…

智能合约漏洞,价值 5200 万美元的 Vyper 漏洞攻击原理分析

智能合约漏洞&#xff0c;价值 5200 万美元的 Vyper 漏洞攻击原理分析 7 月 30 日&#xff0c;因为 Vyper 部分版本中的漏洞&#xff0c;导致 Curve、JPEG’d 等项目陆续受到攻击&#xff0c;损失总计超过 5200 万美元。 Safful 对此事件第一时间进行了技术分析&#xff0c;并…

2023 IDC中国数字金融论坛丨中电金信向行业分享“源启+应用重构”新范式

9月8日&#xff0c;IDC主办的“2023 IDC中国数字金融论坛”在北京召开。中电金信受邀参会&#xff0c;并带来了深度数字化转型趋势之下关于应用重构的分享与洞见。 论坛重点关注金融科技创新发展趋势与数字化转型之路&#xff0c;中电金信副总经理、研究院院长况文川带来了“创…

nSoftware IPWorks IoT 2022 Java 22.0.8 Crack

物联网库&#xff0c;使用这个轻量级组件库&#xff0c;可以在任何平台上的应用程序中轻松实现物联网 (IoT) 通信协议。 nSoftware IPWorks IoT 最新的 IPWorks IoT 现已推出&#xff01;最新版本的 IPWorks IoT 具有现代化和简化的体验&#xff0c;包括 .NET 中的异步和跨平台…

[开源]MIT协议,开源论坛程序,拥有友好的用户界面和操作体验

一、开源项目简介 尤得一物是一个开源论坛程序&#xff0c;提供丰富的功能&#xff0c;可以作为管理或分享文章的论坛博客&#xff0c;也可以在此基础上进行自定义开发。 二、开源协议 使用MIT开源协议 三、界面展示 四、功能概述 尤得一物是一个开源论坛程序&#xff0c;…

vue-7-vuex

一、Vuex 概述 目标&#xff1a;明确Vuex是什么&#xff0c;应用场景以及优势 1.是什么 Vuex 是一个 Vue 的 状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;Vuex 是一个插件&#xff0c;可以帮我们管理 Vue 通用的数据 (多组件共享的数据)。例如&#xff1a;购…

arcgis地形分析全流程

主要内容&#xff1a;DEM的获取与处理、高程分析、坡度分析、坡向分析、地形起伏度分析、地表粗糙度分析、地表曲率分析&#xff1b; 主要工具&#xff1a;镶嵌至新栅格、按掩膜提取、投影栅格、坡度、坡向、焦点统计 一 DEM的获取与处理 1.1 DEM是什么&#xff1f; DEM(D…

安全与隐私:直播购物App开发中的重要考虑因素

随着直播购物App的崭露头角&#xff0c;开发者需要特别关注安全性和隐私问题。本文将介绍在直播购物App开发中的一些重要安全和隐私考虑因素&#xff0c;并提供相关的代码示例。 1. 数据加密 在直播购物App中&#xff0c;用户的个人信息和支付信息是极为敏感的数据。为了保护…

Linux文件与目录的增删改查

一、增 1、mkdir命令 作用: 创建一个新目录。格式: mkdir [选项] 要创建的目录 常用参数: -p:创建目录结构中指定的每一个目录,如果目录不存在则创建,如果目录已存在也不会被覆盖。用法示例: 1、mkdir directory:创建单个目录 这个命令会在当前目录下创建一个名为…

简单好用的CHM文件阅读器 CHM Viewer Star最新 for mac

CHM Viewer Star 是一款适用于 Mac 平台的 CHM 文件阅读器软件&#xff0c;支持本地和远程 CHM 文件的打开和查看。它提供了直观易用的界面设计&#xff0c;支持多种浏览模式&#xff0c;如书籍模式、缩略图模式和文本模式等&#xff0c;并提供了丰富的功能和工具&#xff0c;如…

亚马逊流量攻略:如何将流量转化为销售,测评实现销售飙升!

在电商领域&#xff0c;流量获取一直是一个核心议题。对于任何希望增加订单量的商家而言&#xff0c;将流量引导至自身店铺并成功转化为销售至关重要。对于初入电商领域或规模较小的卖家来说&#xff0c;亚马逊内部的流量获取通常可带来显著的销售业绩。那么&#xff0c;如何利…

python—如何提取word中指定内容

假设有一个Word&#xff0c;该Word中存在 “联系人” 关键字&#xff0c;如何将该Word中的联系人所对应的内容提取出来呢&#xff1f; 该Word内容如下所示&#xff1a; 要在给定的Word文档中提取出与"联系人"关键字对应的内容&#xff0c;可以使用Python的py…

【抓包https请求网络异常/无数据怎么破】

当你测试App的时候&#xff0c;想要通过Fiddler/Charles等工具抓包看下https请求的数据情况&#xff0c;发现大部分的App都提示网络异常/无数据等等信息。 当你测试App的时候&#xff0c;想要通过Fiddler/Charles等工具抓包看下https请求的数据情况&#xff0c;发现大部分的Ap…

见微知著:从企业售后技术支持看云计算发展

作者&#xff1a;余凯 售后业务中的细微变化 作为阿里云企业容器技术支持的一员&#xff0c;每天会面对全球各地企业级客户提出的关于容器的各种问题&#xff0c;通过这几年的技术支持的经历&#xff0c;逐步发现容器问题客户的一些惯性&#xff0c;哪些是重度用户&#xff0…

Java使用模板导出word、pdf

使用deepoove根据模板导出word文档&#xff0c;包括文本、表格、图表、图片&#xff0c;使用WordConvertPdf可将word文档转换为pdf导出 模板样例&#xff1a; 导出结果&#xff1a; 一、引入相关依赖 <!-- 工具类--><dependency><groupId>cn.hutool&…

基于YOLOv5、YOLOv8的火灾检测(超实用毕业设计项目)

yolo系列文章目录 摘要&#xff1a;基于YOLOV5模型的火灾检测系统用于日常生活中检测与定位火灾目标&#xff0c;包括建筑火灾、森林火灾等。利用深度学习算法可实现图片、视频、摄像头等方式的火灾目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导…