linux security(LSM)

LSM(Linux security module)

1. security_init初始化

内核启动流程:start_kernel()-->security_init()

2. security_init LSM子系统初始化

static struct security_operations *security_ops; //安全操作接口
static struct security_operations default_security_ops = { //默认操作接口
	.name	= "default",
};
int __init security_init(void)
{
	printk(KERN_INFO "Security Framework initialized\n");

	security_fixup_ops(&default_security_ops); //初始化安全操作接口,见下面
	security_ops = &default_security_ops;
	do_security_initcalls(); //执行System.map的代码段,见下面

	return 0;
}

3. security_fixup_ops LSM安全操作接口绑定

void __init security_fixup_ops(struct security_operations *ops)
{
	set_to_cap_if_null(ops, ptrace_access_check);
	set_to_cap_if_null(ops, ptrace_traceme);
	set_to_cap_if_null(ops, capget);
	set_to_cap_if_null(ops, capset);
	set_to_cap_if_null(ops, capable);
	set_to_cap_if_null(ops, quotactl);
	set_to_cap_if_null(ops, quota_on);
	set_to_cap_if_null(ops, syslog);
	set_to_cap_if_null(ops, settime);
	set_to_cap_if_null(ops, vm_enough_memory);
	set_to_cap_if_null(ops, bprm_set_creds);
	set_to_cap_if_null(ops, bprm_committing_creds);
	set_to_cap_if_null(ops, bprm_committed_creds);
	set_to_cap_if_null(ops, bprm_check_security);
	set_to_cap_if_null(ops, bprm_secureexec);
	set_to_cap_if_null(ops, sb_alloc_security);
	set_to_cap_if_null(ops, sb_free_security);
	set_to_cap_if_null(ops, sb_copy_data);
	set_to_cap_if_null(ops, sb_remount);
	set_to_cap_if_null(ops, sb_kern_mount);
	set_to_cap_if_null(ops, sb_show_options);
	set_to_cap_if_null(ops, sb_statfs);
	set_to_cap_if_null(ops, sb_mount);
	set_to_cap_if_null(ops, sb_umount);
	set_to_cap_if_null(ops, sb_pivotroot);
	set_to_cap_if_null(ops, sb_set_mnt_opts);
	set_to_cap_if_null(ops, sb_clone_mnt_opts);
	set_to_cap_if_null(ops, sb_parse_opts_str);
	set_to_cap_if_null(ops, inode_alloc_security);
	set_to_cap_if_null(ops, inode_free_security);
	set_to_cap_if_null(ops, inode_init_security);
	set_to_cap_if_null(ops, inode_create);
	set_to_cap_if_null(ops, inode_link);
	set_to_cap_if_null(ops, inode_unlink);
	set_to_cap_if_null(ops, inode_symlink);
	set_to_cap_if_null(ops, inode_mkdir);
	set_to_cap_if_null(ops, inode_rmdir);
	set_to_cap_if_null(ops, inode_mknod);
	set_to_cap_if_null(ops, inode_rename);
	set_to_cap_if_null(ops, inode_readlink);
	set_to_cap_if_null(ops, inode_follow_link);
	set_to_cap_if_null(ops, inode_permission);
	set_to_cap_if_null(ops, inode_setattr);
	set_to_cap_if_null(ops, inode_getattr);
	set_to_cap_if_null(ops, inode_setxattr);
	set_to_cap_if_null(ops, inode_post_setxattr);
	set_to_cap_if_null(ops, inode_getxattr);
	set_to_cap_if_null(ops, inode_listxattr);
	set_to_cap_if_null(ops, inode_removexattr);
	set_to_cap_if_null(ops, inode_need_killpriv);
	set_to_cap_if_null(ops, inode_killpriv);
	set_to_cap_if_null(ops, inode_getsecurity);
	set_to_cap_if_null(ops, inode_setsecurity);
	set_to_cap_if_null(ops, inode_listsecurity);
	set_to_cap_if_null(ops, inode_getsecid);
#ifdef CONFIG_SECURITY_PATH
	set_to_cap_if_null(ops, path_mknod);
	set_to_cap_if_null(ops, path_mkdir);
	set_to_cap_if_null(ops, path_rmdir);
	set_to_cap_if_null(ops, path_unlink);
	set_to_cap_if_null(ops, path_symlink);
	set_to_cap_if_null(ops, path_link);
	set_to_cap_if_null(ops, path_rename);
	set_to_cap_if_null(ops, path_truncate);
	set_to_cap_if_null(ops, path_chmod);
	set_to_cap_if_null(ops, path_chown);
	set_to_cap_if_null(ops, path_chroot);
#endif
	set_to_cap_if_null(ops, file_permission);
	set_to_cap_if_null(ops, file_alloc_security);
	set_to_cap_if_null(ops, file_free_security);
	set_to_cap_if_null(ops, file_ioctl);
	set_to_cap_if_null(ops, mmap_addr);
	set_to_cap_if_null(ops, mmap_file);
	set_to_cap_if_null(ops, file_mprotect);
	set_to_cap_if_null(ops, file_lock);
	set_to_cap_if_null(ops, file_fcntl);
	set_to_cap_if_null(ops, file_set_fowner);
	set_to_cap_if_null(ops, file_send_sigiotask);
	set_to_cap_if_null(ops, file_receive);
	set_to_cap_if_null(ops, file_open);
	set_to_cap_if_null(ops, task_create);
	set_to_cap_if_null(ops, task_free);
	set_to_cap_if_null(ops, cred_alloc_blank);
	set_to_cap_if_null(ops, cred_free);
	set_to_cap_if_null(ops, cred_prepare);
	set_to_cap_if_null(ops, cred_transfer);
	set_to_cap_if_null(ops, kernel_act_as);
	set_to_cap_if_null(ops, kernel_create_files_as);
	set_to_cap_if_null(ops, kernel_module_request);
	set_to_cap_if_null(ops, kernel_module_from_file);
	set_to_cap_if_null(ops, task_fix_setuid);
	set_to_cap_if_null(ops, task_setpgid);
	set_to_cap_if_null(ops, task_getpgid);
	set_to_cap_if_null(ops, task_getsid);
	set_to_cap_if_null(ops, task_getsecid);
	set_to_cap_if_null(ops, task_setnice);
	set_to_cap_if_null(ops, task_setioprio);
	set_to_cap_if_null(ops, task_getioprio);
	set_to_cap_if_null(ops, task_setrlimit);
	set_to_cap_if_null(ops, task_setscheduler);
	set_to_cap_if_null(ops, task_getscheduler);
	set_to_cap_if_null(ops, task_movememory);
	set_to_cap_if_null(ops, task_wait);
	set_to_cap_if_null(ops, task_kill);
	set_to_cap_if_null(ops, task_prctl);
	set_to_cap_if_null(ops, task_to_inode);
	set_to_cap_if_null(ops, ipc_permission);
	set_to_cap_if_null(ops, ipc_getsecid);
	set_to_cap_if_null(ops, msg_msg_alloc_security);
	set_to_cap_if_null(ops, msg_msg_free_security);
	set_to_cap_if_null(ops, msg_queue_alloc_security);
	set_to_cap_if_null(ops, msg_queue_free_security);
	set_to_cap_if_null(ops, msg_queue_associate);
	set_to_cap_if_null(ops, msg_queue_msgctl);
	set_to_cap_if_null(ops, msg_queue_msgsnd);
	set_to_cap_if_null(ops, msg_queue_msgrcv);
	set_to_cap_if_null(ops, shm_alloc_security);
	set_to_cap_if_null(ops, shm_free_security);
	set_to_cap_if_null(ops, shm_associate);
	set_to_cap_if_null(ops, shm_shmctl);
	set_to_cap_if_null(ops, shm_shmat);
	set_to_cap_if_null(ops, sem_alloc_security);
	set_to_cap_if_null(ops, sem_free_security);
	set_to_cap_if_null(ops, sem_associate);
	set_to_cap_if_null(ops, sem_semctl);
	set_to_cap_if_null(ops, sem_semop);
	set_to_cap_if_null(ops, netlink_send);
	set_to_cap_if_null(ops, d_instantiate);
	set_to_cap_if_null(ops, getprocattr);
	set_to_cap_if_null(ops, setprocattr);
	set_to_cap_if_null(ops, secid_to_secctx);
	set_to_cap_if_null(ops, secctx_to_secid);
	set_to_cap_if_null(ops, release_secctx);
	set_to_cap_if_null(ops, inode_notifysecctx);
	set_to_cap_if_null(ops, inode_setsecctx);
	set_to_cap_if_null(ops, inode_getsecctx);
#ifdef CONFIG_SECURITY_NETWORK
	set_to_cap_if_null(ops, unix_stream_connect);
	set_to_cap_if_null(ops, unix_may_send);
	set_to_cap_if_null(ops, socket_create); //创建socket
	set_to_cap_if_null(ops, socket_post_create);
	set_to_cap_if_null(ops, socket_bind);
	set_to_cap_if_null(ops, socket_connect);
	set_to_cap_if_null(ops, socket_listen);
	set_to_cap_if_null(ops, socket_accept);
	set_to_cap_if_null(ops, socket_sendmsg);
	set_to_cap_if_null(ops, socket_recvmsg);
	set_to_cap_if_null(ops, socket_getsockname);
	set_to_cap_if_null(ops, socket_getpeername);
	set_to_cap_if_null(ops, socket_setsockopt);
	set_to_cap_if_null(ops, socket_getsockopt);
	set_to_cap_if_null(ops, socket_shutdown);
	set_to_cap_if_null(ops, socket_sock_rcv_skb);
	set_to_cap_if_null(ops, socket_getpeersec_stream);
	set_to_cap_if_null(ops, socket_getpeersec_dgram);
	set_to_cap_if_null(ops, sk_alloc_security);
	set_to_cap_if_null(ops, sk_free_security);
	set_to_cap_if_null(ops, sk_clone_security);
	set_to_cap_if_null(ops, sk_getsecid);
	set_to_cap_if_null(ops, sock_graft);
	set_to_cap_if_null(ops, inet_conn_request);
	set_to_cap_if_null(ops, inet_csk_clone);
	set_to_cap_if_null(ops, inet_conn_established);
	set_to_cap_if_null(ops, secmark_relabel_packet);
	set_to_cap_if_null(ops, secmark_refcount_inc);
	set_to_cap_if_null(ops, secmark_refcount_dec);
	set_to_cap_if_null(ops, req_classify_flow);
	set_to_cap_if_null(ops, tun_dev_alloc_security);
	set_to_cap_if_null(ops, tun_dev_free_security);
	set_to_cap_if_null(ops, tun_dev_create);
	set_to_cap_if_null(ops, tun_dev_open);
	set_to_cap_if_null(ops, tun_dev_attach_queue);
	set_to_cap_if_null(ops, tun_dev_attach);
	set_to_cap_if_null(ops, skb_owned_by);
#endif	/* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
	set_to_cap_if_null(ops, xfrm_policy_alloc_security);
	set_to_cap_if_null(ops, xfrm_policy_clone_security);
	set_to_cap_if_null(ops, xfrm_policy_free_security);
	set_to_cap_if_null(ops, xfrm_policy_delete_security);
	set_to_cap_if_null(ops, xfrm_state_alloc_security);
	set_to_cap_if_null(ops, xfrm_state_free_security);
	set_to_cap_if_null(ops, xfrm_state_delete_security);
	set_to_cap_if_null(ops, xfrm_policy_lookup);
	set_to_cap_if_null(ops, xfrm_state_pol_flow_match);
	set_to_cap_if_null(ops, xfrm_decode_session);
#endif	/* CONFIG_SECURITY_NETWORK_XFRM */
#ifdef CONFIG_KEYS
	set_to_cap_if_null(ops, key_alloc);
	set_to_cap_if_null(ops, key_free);
	set_to_cap_if_null(ops, key_permission);
	set_to_cap_if_null(ops, key_getsecurity);
#endif	/* CONFIG_KEYS */
#ifdef CONFIG_AUDIT
	set_to_cap_if_null(ops, audit_rule_init);
	set_to_cap_if_null(ops, audit_rule_known);
	set_to_cap_if_null(ops, audit_rule_match);
	set_to_cap_if_null(ops, audit_rule_free);
#endif
}

这个函数主要是绑定LSM安全操作接口,这里涉及到结构体,路径:include\linux\security.h

struct security_operations {
	char name[SECURITY_NAME_MAX + 1];

	int (*ptrace_access_check) (struct task_struct *child, unsigned int mode);
	int (*ptrace_traceme) (struct task_struct *parent);
	int (*capget) (struct task_struct *target,
		       kernel_cap_t *effective,
		       kernel_cap_t *inheritable, kernel_cap_t *permitted);
	int (*capset) (struct cred *new,
		       const struct cred *old,
		       const kernel_cap_t *effective,
		       const kernel_cap_t *inheritable,
		       const kernel_cap_t *permitted);
	int (*capable) (const struct cred *cred, struct user_namespace *ns,
			int cap, int audit);
	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
	int (*quota_on) (struct dentry *dentry);
	int (*syslog) (int type);
	int (*settime) (const struct timespec *ts, const struct timezone *tz);
	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
        ...
}

4. do_security_initcalls 

初始化System.map内部的LSM函数

extern initcall_t __security_initcall_start[], __security_initcall_end[];
static void __init do_security_initcalls(void)
{
	initcall_t *call;
	call = __security_initcall_start;
	while (call < __security_initcall_end) {
		(*call) ();
		call++;
	}
}

在System.map文件内部:

c0442a10 T __security_initcall_end
c0442a10 T __security_initcall_start

这里内部没有函数地址,表明没有启用安全模式。

5. socket套接字 例子

我们通过创建socket套接字来访问LSM

-->应用层创建socket()

-->系统调用

-->SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol),

        其中SYSCALL_DEFINE3路径为:include\linux\syscalls.h

-->sock_create(family, type, protocol, &sock)

-->__sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0)

-->security_socket_create(family, type, protocol, kern)

-->security_ops->socket_create(family, type, protocol, kern),该函数将回调如下的接口

在上面第3.内部

set_to_cap_if_null(ops, socket_create);
至此,即可校验socket套接字创建时的domain协议族、socket类型!


猜你喜欢

转载自blog.csdn.net/chenliang0224/article/details/80325071
LSM
今日推荐