目录

. 引言
. Linux Security Module Framework Introduction
. LSM Sourcecode Analysis
. LSMs Hook Engine:基于LSM Hook进行元数据的监控获取
. LSM编程示例
. Linux LSM stacking

0. 引言

从最佳实践的角度来说,在Linux Kernel中进行安全审计、Access Control(访问控制)最好的方式就是使用Linux提供的原生的框架机制,例如

. Kprobe: Linux提供的原生的调试机制(Debug),允许向任意的内核函数注册Hook回调通知点,当执行到Hooked函数的时候,会触发我们注册的kprobe_handle
. LSM(Linux Security Modules): Linux提供的原生的Hook框架,本质上来说,LSM是直接串行的插入到了Linux Kernel的代码路径中,是Linux本身对外提供了一套审计机制(Hook框架)

LSM框架的设计初衷是为了在Linux Kernel中实现一个MAC(Mandatory Access Control) Hook框架,LSM已经作为Linux Kernel的一部分随着内核一起发布了,使用框架的好处就在于,安全人员可以直接基于LSM框架进行上层审计模块的开发,专注于业务逻辑,而不需要关注底层的内核差异兼 容性和稳定性,这是相对于sys_call hook方式最大的优势

1. Linux Security Module Framework Introduction

The Linux Security Module (LSM) framework provides a mechanism for various security checks to be hooked by new kernel extensions. The name "module" is a bit of a misnomer since these extensions are not actually loadable kernel modules. Instead, they are selectable at build-time via CONFIG_DEFAULT_SECURITY and can be overridden at boot-time via the "security=..." kernel command line argument, in the case where multiple LSMs were built into a given kernel.

The primary users of the LSM interface are Mandatory Access Control (MAC) extensions which provide a comprehensive security policy. Examples include

. SELinux
. Smack
. Tomoyo
. AppArmor
. other extensions can be built using the LSM to provide specific changes to system operation
//Linux LSM是Linux下的一个框架标准,并不是一个特定的技术,类似于WINDOWS中的NDIS(Network Driver Interface Specification)概念,而SELINUX是在遵循针这一框架的基础上实现的具体Hook技术,SELINUX和LSM的关系是具体实现和框架标准的关系

0x1: Design

LSM inserts "hooks" (upcalls to the module) at every point in the kernel where a user-level system call is about to result in access to an important internal kernel object such as inodes and task control blocks.

The project is narrowly scoped to solve the problem of access control to avoid imposing a large and complex change patch on the mainstream kernel. It is not intended as a general "hook" or "upcall" mechanism, nor does it support Operating system-level virtualization.

0x2: LSM Principle

The Linux Security Modules (LSM) project has developed a lightweight, general purpose, access control framework for the mainstream Linux kernel that enables many different access control models to be implemented as loadable kernel modules.

A number of existing enhanced access control implementations, including

. Linux Capabilities Model
. Security-Enhanced Linux (SELinux) Model
. Domain and Type Enforcement (DTE) Model

使用LSM Hook框架进行内核安全审计、元数据捕获,安全人员只需要按照既定的调用规范编写LKM模块,并加载进Linux内核,而不需要对system call lookup表进行任何修改

aaarticlea/png;base64,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" alt="" />

LSM allows modules to mediate access to kernel objects by placing hooks in the kernel code just ahead of the access, as shown in picture above

0x3: LSM Implementation Principle

The LSM kernel patch modifies the kernel in five primary ways

. it adds opaque security fields to certain kernel data structures
) task_struct: Task(Process)
) linux_binprm: Program
) super_block: Filesystem
) inode: Pipe、File,、or Socket
) file: Open File
) sk_buff: Network Buffer(Packet)
) net_device: Network Device
) kern_ipc_perm: Semaphore、Shared Memory Segment、Message Queue
) msg_msg: Individual Message
/*
The setting of these security fields and the management of the associated security data is handled by the security modules. LSM merely provides the fields and a set of calls to security hooks that can be implemented by the module to manage the security fields as desired
LSM以串行地方式插入到Linux Kernel中,在进行串行Hook的同时,同时自身也需要维护一套数据结构来保存自身的Hook信息,这也是Hook Engine的通用思路
*/ . the patch inserts calls to security hook functions at various points within the kernel code
LSM在Linux Kernel中插入了两种"security hooks function call"
) LSM安全策略判断
) lSM自身数据结构维护
这些hook function 指针都保存在一个全局结构体: "security-ops"中(struct security_operations) . the patch adds a generic security system call
LSM provides a general security system call that allows security modules to implement new calls for security-aware applications . the patch provides functions to allow kernel modules to register and unregister themselves as security modules
When a security module is loaded, it must register itself with the LSM framework by calling the "register-security"
function. This function sets the global "security_ops table" to refer to the module’s hook function pointers(即初始状态下,"security-ops"是指向NULL的指针), causing the kernel to call into the security module for access control decisions. The "register-security" function will not overwrite a previously loaded module.
Once a security module is loaded, it becomes a policy decision whether it will allow itself to be unloaded. . the patch moves most of the capabilities logic into an optional security module,
The Linux kernel currently provides support for a subset of POSIX.1e capabilities.

0x4: LSM Hook Method

. Task Hooks
LSM provides a set of task hooks that enable security modules to manage process security information and to control process operations . Program Loading Hooks
LSM provides a set of programloading hooks that are called at critical points during the processing of an execve operation.
"linux_binprm" . IPC Hooks
Security modules can manage security information and perform access control for System V IPC using the LSM IPC hooks.
LSM inserts a hook into the existing ipcperms function so that a security module can perform a check for each existing Linux IPC permission check . Filesystem Hooks
For file operations, three sets of hooks were defined:
) filesystem hooks
) inode hooks
) file hooks . Network Hooks
Application layer access to networking is mediated using a set of socket hooks. These hooks, which include interposition of all socket system calls, provide coarse mediation coverage of all socket-based protocols.
Since active user sockets have an associated inode structure, a separate security field was not added to the socket structure or to the lower-level sock structure.
As the socket hooks allow general mediation of network traffic in relation to processes, LSM significantly expands the kernel’s network access control framework (which is already handled at the network layer by Netfilter)(LSM对网络的访问控制和Netfilter保持兼容).
For example, the sock rcv skb hook allows an inbound packet to be mediated in terms of its destination application, prior to being queued at the associated userspace socket. . Other Hooks
LSM provides two additional sets of hooks:
) module hooks
Module hooks can be used to control the kernel operations that create, initialize, and delete kernel modules. ) a set of top-level system hooks
System hooks can be used to control system operations, such as setting the system hostname, accessing I/O ports, and configuring process accounting.

可以看出,LSM在向上层提供了一个统一的Hook的接口的同时,在下层进行了大量的兼容,对于Linux系统的各个子系统来说,要实现对它们的Hook,差异性是不言而喻的,LSM的Hook Point就像触手一样遍布在Linux Kernel的各个角落

0x5: 基于LSM框架的具体实现

LSM provides only the mechanism to enforce enhanced access control policies. Thus, it is the LSM modules that implement a specific policy and are critical in proving the functionality of the framework.

. SELinux
http://en.wikipedia.org/wiki/Security-Enhanced_Linux
http://selinuxproject.org/page/NB_LSM A Linux implementation of the Flask flexible access control architecture and an example security server that supports Type Enforcement, Role-Based Access Control, and optionally MultiLevel Security.
SELinux was originally implemented as a kernel patch and was then reimplemented as a security module that uses LSM.
SELinux can be used to confine processes to least privilege, to protect the integrity and confidentiality of processes and data, and to support application security needs. . DTE Linux
An implementation of Domain and Type Enforcement developed for Linux
Like SELinux, DTE Linux was originally implemented as a kernel patch and was then adapted to LSM. With this module loaded, types can be assigned to objects and domains to processes. The DTE policy restricts access between domains and from domains to types. The DTE Linux project also provided useful input into the design and implementation of LSM. . LSM port of Openwall kernel patch . POSIX.1e capabilities

Relevant Link:

http://lxr.free-electrons.com/source/Documentation/security/LSM.txt
https://www.usenix.org/legacy/event/sec02/wright.html
http://en.wikipedia.org/wiki/Linux_Security_Modules
https://www.usenix.org/legacy/event/sec02/wright.html
https://www.usenix.org/legacy/event/sec02/full_papers/wright/wright.pdf
https://www.kernel.org/doc/ols/2002/ols2002-pages-604-617.pdf
http://se7so.blogspot.com/2012/04/linux-security-modules-framework-lsm.html
http://www.kroah.com/linux/talks/ols_2002_lsm_paper/lsm.pdf

2. LSM Sourcecode Analysis

0x1: LSM的数据结构定义

/source/security/security.c

...
static struct security_operations *security_ops;
static struct security_operations default_security_ops = {
.name = "default",
};
...
/**
* security_init - initializes the security framework
*
* This should be called early in the kernel initialization sequence.
*/
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(); return ;
} ..
static void __init do_security_initcalls(void)
{
initcall_t *call;
call = __security_initcall_start;
while (call < __security_initcall_end)
{
(*call) ();
call++;
}
}

内核代码声明了全局静态结构体变量: security_ops,并将结构体初始化为默认Hook结构体(default_security_ops)

LSM中最重要的数据结构,保存所有LSM Hook Point Function的: struct security_operations的结构定义如下

/source/include/linux/security.h

struct security_operations
{
//A string that acts as a unique identifier for the LSM
char name[SECURITY_NAME_MAX + ]; 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); /*
1. Security hooks for program execution operations
程序装载钩子,LSM(Linux Security Modules)提供了一系列程序装载钩子,用在一个execve()操作执行过程的关键点上
1) "linux_binprm"结构中的安全域允许安全模块维护程序装载过程中的安全信息
2) LSM提供了钩子用于允许安全模块在装载程序前初始化安全信息和执行访问控制
3) LSM提供了钩子允许模块在新程序成功装载后更新任务的安全信息
4) LSM提供了钩子用来控制程序执行过程中的状态继承,例如确认打开的文件描述符(不是可信启动)
*/
//Save security information in the bprm->security field, typically based on information about the bprm->file, for later use by the apply_creds hook
int (*bprm_set_creds) (struct linux_binprm *bprm);
//This hook mediates the point when a search for a binary handler will begin. This hook may be called multiple times during a single execve; and in each pass set_creds is called first.
int (*bprm_check_security) (struct linux_binprm *bprm);
int (*bprm_secureexec) (struct linux_binprm *bprm);
//Prepare to install the new security attributes of a process being transformed by an execve operation, based on the old credentials pointed to by @current->cred and the information set in @bprm->cred by the bprm_set_creds hook
void (*bprm_committing_creds) (struct linux_binprm *bprm);
//Tidy up after the installation of the new security attributes of a process being transformed by an execve operation.
void (*bprm_committed_creds) (struct linux_binprm *bprm); /*
2. Security hooks for filesystem operations.
*/
//Allocate and attach a security structure to the sb->s_security field.
int (*sb_alloc_security) (struct super_block *sb);
//Deallocate and clear the sb->s_security field.
void (*sb_free_security) (struct super_block *sb);
//Allow mount option data to be copied prior to parsing by the filesystem, so that the security module can extract security-specific mount options cleanly (a filesystem may modify the data e.g. with strsep()).
int (*sb_copy_data) (char *orig, char *copy);
//Extracts security system specific mount options and verifies no changes are being made to those options.
int (*sb_remount) (struct super_block *sb, void *data);
int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);
int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
//Check permission before obtaining filesystem statistics for the @mnt mountpoint.
int (*sb_statfs) (struct dentry *dentry);
//Check permission before an object specified by @dev_name is mounted on the mount point named by @nd.
int (*sb_mount) (const char *dev_name, struct path *path, const char *type, unsigned long flags, void *data);
//Check permission before the @mnt file system is unmounted.
int (*sb_umount) (struct vfsmount *mnt, int flags);
//Check permission before pivoting the root filesystem.
int (*sb_pivotroot) (struct path *old_path, struct path *new_path);
//Set the security relevant mount options used for a superblock
int (*sb_set_mnt_opts) (struct super_block *sb, struct security_mnt_opts *opts, unsigned long kern_flags, unsigned long *set_kern_flags);
//Copy all security options from a given superblock to another
int (*sb_clone_mnt_opts) (const struct super_block *oldsb, struct super_block *newsb);
//Parse a string of security data filling in the opts structure
int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
//Compute a context for a dentry as the inode is not yet available since NFSv4 has no label backed by an EA anyway.
int (*dentry_init_security) (struct dentry *dentry, int mode, struct qstr *name, void **ctx, u32 *ctxlen); #ifdef CONFIG_SECURITY_PATH
int (*path_unlink) (struct path *dir, struct dentry *dentry);
int (*path_mkdir) (struct path *dir, struct dentry *dentry, umode_t mode);
int (*path_rmdir) (struct path *dir, struct dentry *dentry);
int (*path_mknod) (struct path *dir, struct dentry *dentry, umode_t mode,
unsigned int dev);
int (*path_truncate) (struct path *path);
int (*path_symlink) (struct path *dir, struct dentry *dentry,
const char *old_name);
int (*path_link) (struct dentry *old_dentry, struct path *new_dir,
struct dentry *new_dentry);
int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,
struct path *new_dir, struct dentry *new_dentry);
int (*path_chmod) (struct path *path, umode_t mode);
int (*path_chown) (struct path *path, kuid_t uid, kgid_t gid);
int (*path_chroot) (struct path *path);
#endif /*
3. Security hooks for inode operations.
*/
//Allocate and attach a security structure to @inode->i_security.
int (*inode_alloc_security) (struct inode *inode);
void (*inode_free_security) (struct inode *inode);
//Obtain the security attribute name suffix and value to set on a newly created inode and set up the incore security field for the new inode.
int (*inode_init_security) (struct inode *inode, struct inode *dir, const struct qstr *qstr, const char **name, void **value, size_t *len);
int (*inode_create) (struct inode *dir, struct dentry *dentry, umode_t mode);
int (*inode_link) (struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry);
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
int (*inode_symlink) (struct inode *dir, struct dentry *dentry, const char *old_name);
int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, umode_t mode);
int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
int (*inode_mknod) (struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev);
int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry);
int (*inode_readlink) (struct dentry *dentry);
int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
int (*inode_permission) (struct inode *inode, int mask);
int (*inode_setattr) (struct dentry *dentry, struct iattr *attr);
int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
int (*inode_setxattr) (struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
void (*inode_post_setxattr) (struct dentry *dentry, const char *name, const void *value, size_t size, int flags);
int (*inode_getxattr) (struct dentry *dentry, const char *name);
int (*inode_listxattr) (struct dentry *dentry);
int (*inode_removexattr) (struct dentry *dentry, const char *name);
int (*inode_need_killpriv) (struct dentry *dentry);
int (*inode_killpriv) (struct dentry *dentry);
int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
void (*inode_getsecid) (const struct inode *inode, u32 *secid); /*
4. Security hooks for file operations
*/
//Check file permissions before accessing an open file. This hook is called by various operations that read or write files.
int (*file_permission) (struct file *file, int mask);
//Allocate and attach a security structure to the file->f_security field
int (*file_alloc_security) (struct file *file);
//Deallocate and free any security structures stored in file->f_security.
void (*file_free_security) (struct file *file);
//Check permission for an ioctl operation on @file
int (*file_ioctl) (struct file *file, unsigned int cmd, unsigned long arg);
//Check permissions for a mmap operation at @addr.
int (*mmap_addr) (unsigned long addr);
//Check permissions for a mmap operation.
int (*mmap_file) (struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags);
//Check permissions before changing memory access permissions.
int (*file_mprotect) (struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot);
//Check permission before performing file locking operations.
int (*file_lock) (struct file *file, unsigned int cmd);
//Check permission before allowing the file operation specified by @cmd from being performed on the file @file.
int (*file_fcntl) (struct file *file, unsigned int cmd, unsigned long arg);
int (*file_set_fowner) (struct file *file);
int (*file_send_sigiotask) (struct task_struct *tsk, struct fown_struct *fown, int sig);
int (*file_receive) (struct file *file);
//Save open-time permission checking state for later use upon file_permission, and recheck access if anything has changed since inode_permission
int (*file_open) (struct file *file, const struct cred *cred); /*
5. Security hooks for task operations.
LSM(Linux Security Modules)提供了一系列的任务钩子使得安全模块可以管理进程的安全信息并且控制进程的操作
1) LSM可以使用"task_struct"结构中的安全域来维护进程安全信息
2) 任务钩子提供了控制进程间通信的钩子,例如kill()
3) LSM提供了控制对当前进程进行特权操作的钩子,例如setuid()
4) LSM提供了对资源管理操作进行细粒度控制的钩子,例如setrlimit()和nice()
*/
//Check permission before creating a child process
int (*task_create) (unsigned long clone_flags);
//@task task being freed Handle release of task-related resources. (Note that this can be called from interrupt context.)
void (*task_free) (struct task_struct *task);
//Only allocate sufficient memory and attach to @cred such that cred_transfer() will not get ENOMEM.
int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp);
//eallocate and clear the cred->security field in a set of credentials.
void (*cred_free) (struct cred *cred);
//Prepare a new set of credentials by copying the data from the old set.
int (*cred_prepare)(struct cred *new, const struct cred *old, gfp_t gfp);
//Transfer data from original creds to new creds
void (*cred_transfer)(struct cred *new, const struct cred *old);
//Set the credentials for a kernel service to act as (subjective context).
int (*kernel_act_as)(struct cred *new, u32 secid);
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
int (*kernel_module_request)(char *kmod_name);
int (*kernel_module_from_file)(struct file *file);
//Update the module's state after setting one or more of the user identity attributes of the current process.
int (*task_fix_setuid) (struct cred *new, const struct cred *old, int flags);
int (*task_setpgid) (struct task_struct *p, pid_t pgid);
int (*task_getpgid) (struct task_struct *p);
int (*task_getsid) (struct task_struct *p);
void (*task_getsecid) (struct task_struct *p, u32 *secid);
int (*task_setnice) (struct task_struct *p, int nice);
int (*task_setioprio) (struct task_struct *p, int ioprio);
int (*task_getioprio) (struct task_struct *p);
int (*task_setrlimit) (struct task_struct *p, unsigned int resource, struct rlimit *new_rlim);
int (*task_setscheduler) (struct task_struct *p);
int (*task_getscheduler) (struct task_struct *p);
int (*task_movememory) (struct task_struct *p);
int (*task_kill) (struct task_struct *p, struct siginfo *info, int sig, u32 secid);
int (*task_wait) (struct task_struct *p);
//Check permission before performing a process control operation on the current process.
int (*task_prctl) (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
void (*task_to_inode) (struct task_struct *p, struct inode *inode); int (*ipc_permission) (struct kern_ipc_perm *ipcp, short flag);
void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid); int (*msg_msg_alloc_security) (struct msg_msg *msg);
void (*msg_msg_free_security) (struct msg_msg *msg); int (*msg_queue_alloc_security) (struct msg_queue *msq);
void (*msg_queue_free_security) (struct msg_queue *msq);
int (*msg_queue_associate) (struct msg_queue *msq, int msqflg);
int (*msg_queue_msgctl) (struct msg_queue *msq, int cmd);
int (*msg_queue_msgsnd) (struct msg_queue *msq,
struct msg_msg *msg, int msqflg);
int (*msg_queue_msgrcv) (struct msg_queue *msq,
struct msg_msg *msg,
struct task_struct *target,
long type, int mode); int (*shm_alloc_security) (struct shmid_kernel *shp);
void (*shm_free_security) (struct shmid_kernel *shp);
int (*shm_associate) (struct shmid_kernel *shp, int shmflg);
int (*shm_shmctl) (struct shmid_kernel *shp, int cmd);
int (*shm_shmat) (struct shmid_kernel *shp,
char __user *shmaddr, int shmflg); int (*sem_alloc_security) (struct sem_array *sma);
void (*sem_free_security) (struct sem_array *sma);
int (*sem_associate) (struct sem_array *sma, int semflg);
int (*sem_semctl) (struct sem_array *sma, int cmd);
int (*sem_semop) (struct sem_array *sma,
struct sembuf *sops, unsigned nsops, int alter); /*
6. Security hooks for Netlink messaging.
*/
//Save security information for a netlink message so that permission checking can be performed when the message is processed.
int (*netlink_send) (struct sock *sk, struct sk_buff *skb); void (*d_instantiate) (struct dentry *dentry, struct inode *inode); int (*getprocattr) (struct task_struct *p, char *name, char **value);
int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
int (*ismaclabel) (const char *name);
int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
void (*release_secctx) (char *secdata, u32 seclen); int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); #ifdef CONFIG_SECURITY_NETWORK
/*
7. Security hooks for Unix domain networking.
*/
//Check permissions before establishing a Unix domain stream connection between @sock and @other.
int (*unix_stream_connect) (struct sock *sock, struct sock *other, struct sock *newsk);
//Check permissions before connecting or sending datagrams from @sock to @other.
int (*unix_may_send) (struct socket *sock, struct socket *other); int (*socket_create) (int family, int type, int protocol, int kern);
int (*socket_post_create) (struct socket *sock, int family, int type, int protocol, int kern);
int (*socket_bind) (struct socket *sock, struct sockaddr *address, int addrlen);
//Check permission before socket protocol layer connect operation attempts to connect socket @sock to a remote address,
int (*socket_connect) (struct socket *sock, struct sockaddr *address, int addrlen);
int (*socket_listen) (struct socket *sock, int backlog);
int (*socket_accept) (struct socket *sock, struct socket *newsock);
int (*socket_sendmsg) (struct socket *sock, struct msghdr *msg, int size);
int (*socket_recvmsg) (struct socket *sock, struct msghdr *msg, int size, int flags);
int (*socket_getsockname) (struct socket *sock);
int (*socket_getpeername) (struct socket *sock);
int (*socket_getsockopt) (struct socket *sock, int level, int optname);
int (*socket_setsockopt) (struct socket *sock, int level, int optname);
int (*socket_shutdown) (struct socket *sock, int how);
int (*socket_sock_rcv_skb) (struct sock *sk, struct sk_buff *skb);
int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len);
int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid);
int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
void (*sk_free_security) (struct sock *sk);
void (*sk_clone_security) (const struct sock *sk, struct sock *newsk);
void (*sk_getsecid) (struct sock *sk, u32 *secid);
void (*sock_graft) (struct sock *sk, struct socket *parent);
int (*inet_conn_request) (struct sock *sk, struct sk_buff *skb, struct request_sock *req);
void (*inet_csk_clone) (struct sock *newsk, const struct request_sock *req);
void (*inet_conn_established) (struct sock *sk, struct sk_buff *skb);
int (*secmark_relabel_packet) (u32 secid);
void (*secmark_refcount_inc) (void);
void (*secmark_refcount_dec) (void);
void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
int (*tun_dev_alloc_security) (void **security);
void (*tun_dev_free_security) (void *security);
int (*tun_dev_create) (void);
int (*tun_dev_attach_queue) (void *security);
int (*tun_dev_attach) (struct sock *sk, void *security);
int (*tun_dev_open) (void *security);
void (*skb_owned_by) (struct sk_buff *skb, struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM
/*
8. Security hooks for XFRM operations.
*/
int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp);
int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
int (*xfrm_state_alloc) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
int (*xfrm_state_alloc_acquire) (struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid);
void (*xfrm_state_free_security) (struct xfrm_state *x);
int (*xfrm_state_delete_security) (struct xfrm_state *x);
int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int (*xfrm_state_pol_flow_match) (struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi *fl);
int (*xfrm_decode_session) (struct sk_buff *skb, u32 *secid, int ckall);
#endif /* CONFIG_SECURITY_NETWORK_XFRM */ /* key management security hooks */
#ifdef CONFIG_KEYS
/*
9. Security hooks affecting all Key Management operations
*/
int (*key_alloc) (struct key *key, const struct cred *cred, unsigned long flags);
void (*key_free) (struct key *key);
int (*key_permission) (key_ref_t key_ref, const struct cred *cred, key_perm_t perm);
int (*key_getsecurity)(struct key *key, char **_buffer);
#endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT
int (*audit_rule_init) (u32 field, u32 op, char *rulestr, void **lsmrule);
int (*audit_rule_known) (struct audit_krule *krule);
int (*audit_rule_match) (u32 secid, u32 field, u32 op, void *lsmrule,
struct audit_context *actx);
void (*audit_rule_free) (void *lsmrule);
#endif /* CONFIG_AUDIT */
};

0x2: LSM在Linux Kernel函数的Hook点:security_file_mmap

LSM以串行插入的方式集成到了Linux Kernel Function中的正常函数中,以"security_file_mmap"为例

source/security/security.c

int security_file_mmap(
struct file *file,
unsigned long reqprot,
unsigned long prot,
unsigned long flags,
unsigned long addr,
unsigned long addr_only)
{
int ret; //LSM Hook Function嵌入到了原始的内核函数的执行流程中
ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
if (ret)
return ret;
return ima_file_mmap(file, prot);
}

Relevant Link:

http://lxr.free-electrons.com/source/security/security.c
http://wenku.baidu.com/view/df89fe235901020207409c49.html

3. LSMs Hook Engine:基于LSM Hook进行元数据的监控获取

. sys_fork
. sys_execve、sys_connect
. sys_init_module

0x1: sys_fork

Linux下进程创建的第一步就是执行fork,用该系统调用时,子进程复制父进程的全部资源。由于要复制父进程进程描述符给子进程(进程描述的结构很大),这一过程会消耗很大的性能开销。linux采用了"写时复制技术"(copy on write,COW),使子进程先共享父进程的物理页,只有子进程进行写操作时,再复制对应的物理页,避免了无用的复制开销,提高了系统的性能

source/arch/x86/kernel/process.c

int sys_fork(struct pt_regs *regs)
{
return do_fork(SIGCHLD, regs->sp, regs, , NULL, NULL);
}

在do_fork中的LSM Hook Point如下

. retval = security_task_create(clone_flags);
在copy_process中被调用
int security_task_create(unsigned long clone_flags)
{
return security_ops->task_create(clone_flags);
}

在这个LSM Hook中,当前新创建的进程的命令行参数并没有传入进来

0x2: sys_execve hook

当用户态发起一个sys_execve()的系统调用,在内核态需要经过一系列的调用流程,我们逐一学习它的LSM Hook点

aaarticlea/png;base64,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" alt="" />

1. do_execve

/source/fs/exec.c

/*
* sys_execve() executes a new program.
*/
int do_execve(char * filename, char __user *__user *argv, char __user *__user *envp, struct pt_regs * regs)
{
//将运行可执行文件时所需的信息组织到一起
struct linux_binprm *bprm;
struct file *file;
struct files_struct *displaced;
bool clear_in_exec;
int retval; retval = unshare_files(&displaced);
if (retval)
goto out_ret; retval = -ENOMEM;
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
if (!bprm)
goto out_files; /*
1. LSM Hook Point 1:
retval = prepare_bprm_creds(bprm);
prepare_exec_creds->security_prepare_creds
int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
{
return security_ops->cred_prepare(new, old, gfp);
}
*/
retval = prepare_bprm_creds(bprm);
if (retval)
goto out_free; retval = check_unsafe_exec(bprm);
if (retval < )
goto out_free;
clear_in_exec = retval;
current->in_execve = ;
//找到并打开给定的可执行程序文件,open_exec()返回file结构指针,代表着读入可执行文件的上下文
file = open_exec(filename);
//强制转换
retval = PTR_ERR(file);
//判断open_exec()返回的是否是无效指针
if (IS_ERR(file))
goto out_unmark; sched_exec(); //要执行的文件
bprm->file = file;
//要执行的文件的名字
bprm->filename = filename;
bprm->interp = filename; retval = bprm_mm_init(bprm);
if (retval)
goto out_file; //统计命令汗参数的个数
bprm->argc = count(argv, MAX_ARG_STRINGS);
if ((retval = bprm->argc) < )
goto out;
//统计环境变量参数的个数
bprm->envc = count(envp, MAX_ARG_STRINGS);
if ((retval = bprm->envc) < )
goto out; //可执行文件中读入开头的128个字节到linux_binprm结构brmp中的缓冲区,用于之后内核根据这头128字节判断应该调用哪个解析引擎来处理当前文件
retval = prepare_binprm(bprm);
if (retval < )
goto out; //文件名拷贝到新分配的页面中
retval = copy_strings_kernel(, &bprm->filename, bprm);
if (retval < )
goto out; bprm->exec = bprm->p;
//将环境变量拷贝到新分配的页面中
retval = copy_strings(bprm->envc, envp, bprm);
if (retval < )
goto out; //将命令行参数拷贝到新分配的页面中
retval = copy_strings(bprm->argc, argv, bprm);
if (retval < )
goto out; //所有准备工作已经完成,所有必要的信息都已经搜集到了linux_binprm结构中的bprm中
current->flags &= ~PF_KTHREAD; //调用search_binary_handler()装入并运行目标程序,根据读入数据结构linux_binprm内的二进制文件128字节头中的关键字,决定调用哪种加载函数
/*
2. LSM Hook Point 2:
retval = security_bprm_check(bprm);
int security_bprm_check(struct linux_binprm *bprm)
{
return security_ops->bprm_check_security(bprm);
}
*/
retval = search_binary_handler(bprm, regs);
if (retval < )
goto out; /* execve succeeded */
current->fs->in_exec = ;
current->in_execve = ;
acct_update_integrals(current); free_bprm(bprm);
if (displaced)
put_files_struct(displaced);
return retval; out:
if (bprm->mm) {
acct_arg_size(bprm, );
mmput(bprm->mm);
} out_file:
//发生错误,返回inode,并释放资源
if (bprm->file)
{
//调用allow_write_access()防止其他进程在读入可执行文件期间通过内存映射改变它的内容
allow_write_access(bprm->file);
//递减file文件中的共享计数
fput(bprm->file);
} out_unmark:
if (clear_in_exec)
current->fs->in_exec = ;
current->in_execve = ; out_free:
free_bprm(bprm); out_files:
if (displaced)
reset_files_struct(displaced);
out_ret:
return retval;
}

在do_execve中(search_binary_handler也包含在了do_execve中),包含了2个LSM Hook Point

. prepare_bprm_creds:cred初始化过程的LSM Hook点
. search_binary_handler:根据待执行文件的头128字节判断对应的解析处理引擎

对于这两个点,我们对比一下我们需要获取的元数据

. current
. argv

current(即task_struct)这个时候还未完全初始化完毕,例如"current->cred"还保存的是父进程的信息(因为linux下的所有进程都是通过父进程去"复制"出来的),代码在"execve_lsm_hook.c"

aaarticlea/png;base64,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" alt="" />

所以在这个LSM Hook Point上,不能直接获取current进行使用,是不准确的

另一方面,argv:retval = copy_strings(bprm->envc, envp, bprm);完成了将当前启动进程的命令行参数复制到内核栈的内存页中,将页的偏移地址保存在了"linux_binprm->p"指针中,这个p指针保存的是这个内存页的偏移,需要将参数从这块虚拟页内存中copy出来,如果直接打印printk会导致kernel panic(可以将那行注释去掉测试)

综上所述,这两个Hook点都不能满足我们进行execve进程执行元数据收集的目的,我们继续往下寻找

2. load_elf_binary

在do_execve()函数的准备阶段,已经从可执行文件头部读入128字节存放在bprm的缓冲区中,而且运行所需的参数和环境变量也已收集在bprm中
search_binary_handler()函数就是逐个扫描formats队列,直到找到一个匹配的可执行文件格式,运行的事就交给它

. 如果在这个队列中没有找到相应的可执行文件格式,就要根据文件头部的信息来查找是否有为此种格式设计的可动态安装的模块
. 如果找到对应的可执行文件格式,就把这个模块安装进内核,并挂入formats队列,然后再重新扫描

在linux_binfmt数据结构中,有三个函数指针

. load_binary
load_binary就是具体的ELF程序装载程序,不同的可执行文件其装载函数也不同
) a.out格式的装载函数为: load_aout_binary()
) elf的装载函数为: load_elf_binary()
. load_shlib
. core_dump

我们的Hook对象是ELF可执行程序的执行,因此,我们继续深入研究load_elf_binary这个函数

...
#ifdef CONFIG_MODULES
} else {
#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
if (printable(bprm->buf[]) &&
printable(bprm->buf[]) &&
printable(bprm->buf[]) &&
printable(bprm->buf[]))
break; /* -ENOEXEC */
request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[]));
#endif
...

内核会根据bprm结构体中判断得到的文件格式类型,加载对应的解析函数,对于ELF文件来说就是binfmt_elf.c

source/fs/binfmt_elf.c

在load_elf_binary()函数中,有两个LSM Hook Point

. file_permission(interpreter, MAY_READ)
int file_permission(struct file *file, int mask)
{
return inode_permission(file->f_path.dentry->d_inode, mask);
} . install_exec_creds(bprm);
void install_exec_creds(struct linux_binprm *bprm)
{
security_bprm_committing_creds(bprm); commit_creds(bprm->cred);
bprm->cred = NULL;
/*
* cred_guard_mutex must be held at least to this point to prevent
* ptrace_attach() from altering our determination of the task's
* credentials; any time after this it may be unlocked.
*/
security_bprm_committed_creds(bprm);
mutex_unlock(&current->cred_guard_mutex);
}
..
void security_bprm_committed_creds(struct linux_binprm *bprm)
{
security_ops->bprm_committed_creds(bprm);
}

在load_elf_binary()函数中,有一行代码需要重点关注

retval = create_elf_tables(bprm, &loc->elf_ex, load_addr, interp_load_addr);

跟进函数进行分析

.....
p = current->mm->arg_end = current->mm->arg_start;
while (argc-- > )
{
size_t len;
if (__put_user((elf_addr_t)p, argv++))
{
return -EFAULT;
}
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN)
{
return -EINVAL;
}
p += len;
}
if (__put_user(, argv))
{
return -EFAULT;
}
....

内核代码在这里将当前进程的参数保存在current->mm->arg_start和current->mm->arg_end之间的内存空间中,这也意味着在调用了create_elf_tables之后,我们就可以在current当中获取到当前进程的命令行参数了

3. do_mmap

从源代码中可以看到,在load_elf_binary中的do_mmap之前,调用了create_elf_tables,所以我们一定可以在do_mmap中寻找到一个hook点,在这个hook点当中可以通过current->mm->arg_start和current->mm->arg_end可以拿到进程的参数

\linux-2.6.32.63\include\linux\mm.h

/*
file:表示要映射的文件
addr:虚拟空间中的一个地址,表示从这个地址开始查找一个空闲的虚拟区
len:要映射的文件部分的长度
prot:这个参数指定对这个虚拟区所包含页的存取权限。可能的标志有
1) PROT_READ
2) PROT_WRITE
3) PROT_EXEC
4) PROT_NONE
前三个标志与标志VM_READ、VM_WRITE 及VM_EXEC的意义一样。PROT_NONE表示进程没有以上三个存取权限中的任意一个
Flag:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
1) MAP_FIXED: 使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上
2) MAP_SHARED: 与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新
3) MAP_PRIVATE: 建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个
4) MAP_DENYWRITE: 这个标志被忽略
5) MAP_EXECUTABLE: 这个标志被忽略
6) MAP_NORESERVE: 不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号
7) MAP_LOCKED: 锁定映射区的页面,从而防止页面被交换出内存
8) MAP_GROWSDOWN: 用于堆栈,告诉内核VM系统,映射区可以向下扩展
9) MAP_ANONYMOUS: 匿名映射,映射区不与任何文件关联
10) MAP_ANON: MAP_ANONYMOUS的别称,不再被使用。
11) MAP_FILE: 兼容标志,被忽略
12) MAP_32BIT: 将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当前这个标志只在x86-64平台上得到支持
13) MAP_POPULATE: 为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞
14) MAP_NONBLOCK: 仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。 off:文件内的偏移量,因为我们并不是一下子全部映射一个文件,可能只是映射文件的一部分,off就表示那部分的起始位置
*/
static inline unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset)
{
unsigned long ret = -EINVAL;
if ((offset + PAGE_ALIGN(len)) < offset)
goto out;
if (!(offset & ~PAGE_MASK))
//do_mmap()函数对参数offset的合法性检查后,就调用do_mmap_pgoff()函数,该函数才是内存映射的主要函数
ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
out:
return ret;
}

\linux-2.6.32.63\mm\mmap.c

在do_mmap_pgoff中可以找到的LSM Hook Point如下

. error = security_file_mmap(NULL, , , , addr, );
int security_file_mmap(struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags, unsigned long addr, unsigned long addr_only)
{
return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only);
}

在这个LSM Hook点:security_ops->file_mmap中,代码截获到的是当前系统所有的文件映射请求,如果需要专门针对ELF可执行文件镜像的file_mmap,需要针对ELF镜像头作判断,针对ELF可执行文件的file_mmap进行,数据量很大,会对性能产生影响,

Relevant Link:

http://blog.csdn.net/edwardlulinux/article/details/7998433

4. 在通用的LSM Hook点都无法直接获取参数的情况下如何通过Hacking方式获取进程当前命令行参数

LSM Hook框架是一种访问控制的审计型框架,它的主要目的是对进程执行的身份权限、文件名等信息进行权限审计,对进程命令行参数这些元数据的捕获并不是那么方便,目前遇到的难点情况如下

. 直接通过最靠近do_execve的LSM Hook接口:bprm_check_security进行Hook,这个时候拿到的arg和current都是不准确的
. 将Hook点下移,通过do_mmap中的LSM Hook接口:file_mmap进行Hook,参数arg和current是可以取到且也是准确的,但是这个函数的上层调用频率太高,需要ELF镜像头部进行区分,对系统运行性能影响较大

解决这个问题的思路可以朝这个方向思考

. 将LSM Hook点尽量上移,在执行流支的尽量上游进行Hook,减少冗余调用频率,提高Hook命中率
. 因为Hook上移,不可避免带来的问题就是,原始Linux内核代码的执行在这个点还未进行,很多变量还没有赋值、或者设置好
. 我们的代码需要针对我们所需的变量,将从当前代码逻辑位置后面的和这些变量相关的内核代码拷贝过来,我们在代码中进行模拟执行,即将原本内核做的事情,我们提前做了
. 但是需要注意的是,我们模拟执行的代码不能对正常的内核函数的执行流支产生任何影响,从程序的角度来说,就是只能拷贝模拟执行那种只获取(get),而不设置(set)的代码逻辑

基于以上思考,我们有了下面的Hacking思路

. 选取"security_ops->bprm_committed_creds"作为LSM Hook点
. "security_ops->bprm_committed_creds"在load_elf_binary的install_exec_creds中被调用,而install_exec_creds在create_elf_tables的前面,这个时候current->mm->arg_end还未被设置成命令行参数的结束位置、current->mm->arg_start已经是命令行参数的起始位置了,我们需要仿照create_elf_tables中对current->mm->arg_end的计算代码进行模拟执行,得到arg_end,要注意的是,为了保持系统状态一致性,不能去修改current->mm->arg_end
. 计算好arg_start、arg_end之后,我们继续模拟proc_pid_cmdline这个函数从arg_start、arg_end中获取到当前进程的命令行参数

按照这个思路,我们进行代码DEMO实现

我们来关注load_elf_binary这个函数中,看到这行代码:

retval = create_elf_tables(bprm, &loc->elf_ex, load_addr, interp_load_addr);

source/fs/binfmt_elf.c

....
p = current->mm->arg_end = current->mm->arg_start;
while (argc-- > ) {
size_t len;
if (__put_user((elf_addr_t)p, argv++))
return -EFAULT;
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN)
return -EINVAL;
p += len;
}
if (__put_user(, argv))
return -EFAULT; /*
current->mm->arg_start指向的已经是当前进程命令行参数的起始地址
但是未将current->mm->arg_end设置到命令行参数的终止位置(即arg_start + arg_len)
*/
current->mm->arg_end = current->mm->env_start = p;
.....

看这段代码,我们要明白的是,Linux将当前进程的命令行参数和环境变量参数都统一放在了一整块内核内存空间中了,而使用arg_start + offset、arg_len来进行区分它们,所以,如果我们想从中取出命令行参数,就需要仿照Linux内核的代码,对arg_start、arg_end进行计算,并得到len,这样才能从current->mm指向的内存中拷贝出我们想要的

int fake_cmdline(int argc)
{
char buffer[] = {};
unsigned long start ,end, p; start = current->mm->arg_start;
end = current->mm->arg_end;
p = current->mm->arg_start; printk("argc = %d, start =%p, end=%p, p =%p\n", argc, start, end, p); while (argc-- > )
{
size_t len;
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN)
return -EINVAL;
p += len;
} end = p;
printk("argc = %d, start =%p, end=%p, p =%p\n", argc, start, end, p);
proc_cmdline(start, end , buffer); return ;
}

拷贝出来之后,我们需要根据arg_start、arg_end从内核内存地址空间中直接复制出参数字符串,模拟proc_pid_cmdline这个函数的代码逻辑

\linux-2.6.32.63\fs\proc\base.c

static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
int res = ;
unsigned int len;
struct mm_struct *mm = get_task_mm(task);
if (!mm)
goto out;
if (!mm->arg_end)
goto out_mm; /* Shh! No looking before we're done */ len = mm->arg_end - mm->arg_start; if (len > PAGE_SIZE)
len = PAGE_SIZE; res = access_process_vm(task, mm->arg_start, buffer, len, ); // If the nul at the end of args has been overwritten, then
// assume application is using setproctitle(3).
if (res > && buffer[res-] != '\0' && len < PAGE_SIZE) {
len = strnlen(buffer, res);
if (len < res) {
res = len;
} else {
len = mm->env_end - mm->env_start;
if (len > PAGE_SIZE - res)
len = PAGE_SIZE - res;
res += access_process_vm(task, mm->env_start, buffer+res, len, );
res = strnlen(buffer, res);
}
}
out_mm:
mmput(mm);
out:
return res;
}

我们只要完成以上步骤,理论上应该是可以拿到进程的命令行参数的,在进行实际编码的时候,从最佳实践的角度来说,我们的代码中应该注意以下几点

. 尽量少的使用拷贝的源代码,而是采用系统原生提供的函数去实现功能,但是要注意的是,如果这个使用到的系统原生函数是会"改变当前系统运行状态"(例如设置全局变量、改变全局指针),就绝对不能使用,而只能采用拷贝源代码自己实现的方式,将其中会对当前系统状态产生影响的代码去掉,而只保留那些"取值型"、"临时变量计算型"的非核心代码
. 我们拷贝的执行代码一定要特别注意对全局变量、全局指针的操作,不能因为我们的模拟执行,而在当前LSM Hook点影响到了Linux内核的状态,否则这样往下执行系统就要处于不一致状态了
. Linux下进程都是通过父进程复制出来的,在bash下执行指令是通过bash复制出来的,而current值(即新进程的task_struct)是在整个sys_execve过程中不断完成初始化填充的,我们需要确认我们的hook点取到的current值已经是新进程的current值

代码示例见: "4. LSM编程示例->0x3: 针对sys_execve使用LSM Hook方式获取进程命令行参数"

到目前为止,我们已经解决了针对sys_execve进程执行的LSM Hook,并获取到了进程启动时的命令行参数,接下来继续研究一下如何Hook监控当前系统的网络连接状态,即对socket的LSM Hook

5. 借助remove_arg_zero直接从内核栈的内存页中拷贝获得进程参数

/source/fs/exec.c

/*
Arguments are '\0' separated strings found at the location bprm->p points to;
chop off the first by relocating brpm->p to right after the first '\0' encountered.
*/
int remove_arg_zero(struct linux_binprm *bprm)
{
int ret = ;
unsigned long offset;
char *kaddr;
struct page *page; if (!bprm->argc)
return ; do
{
offset = bprm->p & ~PAGE_MASK;
page = get_arg_page(bprm, bprm->p, );
if (!page)
{
ret = -EFAULT;
goto out;
}
kaddr = kmap_atomic(page, KM_USER0); for (; offset < PAGE_SIZE && kaddr[offset]; offset++, bprm->p++)
; kunmap_atomic(kaddr, KM_USER0);
put_arg_page(page); if (offset == PAGE_SIZE)
free_arg_page(bprm, (bprm->p >> PAGE_SHIFT) - );
} while (offset == PAGE_SIZE); bprm->p++;
bprm->argc--;
ret = ; out:
return ret;
}
EXPORT_SYMBOL(remove_arg_zero);

remove_arg_zero(bprm)是把argv[0]中的'\0'从bprm->page中清除,我们在bprm_check_security进行Hook的时候,通过调用这个内核函数之后,可以直接从bprm->page中获取到进程的启动参数,从而调用copy函数进行拷贝

0x3: sys_connect

使用LSM(Linux Security Modules)框架的一个最大的好处就是Linux Kernel帮助屏蔽了底层的差异性,在Linux 32bit/64bit和socket系统调用的差异性在LSM Hook这一层都不存在了,而取而代之的是统一的Hook接口

....
int (*socket_create) (int family, int type, int protocol, int kern);
int (*socket_post_create) (struct socket *sock, int family, int type, int protocol, int kern);
int (*socket_bind) (struct socket *sock, struct sockaddr *address, int addrlen);
int (*socket_connect) (struct socket *sock, struct sockaddr *address, int addrlen);
int (*socket_listen) (struct socket *sock, int backlog);
int (*socket_accept) (struct socket *sock, struct socket *newsock);
int (*socket_sendmsg) (struct socket *sock, struct msghdr *msg, int size);
int (*socket_recvmsg) (struct socket *sock, struct msghdr *msg, int size, int flags);
....

我们以socket_connect作为研究对象

关于和socket相关的数据结构定义,请参阅另一篇文章

http://www.cnblogs.com/LittleHann/p/3865490.html
//搜索:6. 系统网络状态相关的数据结构

在我们这个LSM Hook Engine的业务场景下,我们如果需要针对socket_connect动作进行Hook监控,我们要解决的问题有

. struct socket、inet_sk((struct socket)->(struc sock))、struct sockaddr这3中结构体中,要从中筛选出准确保存当前socket连接动作的IP、PORT等信息的字段
. LSM的security_socket_connect()函数会在一次socket连接过程中被多次调用,包括从初始化到最后建立完整连接,我们需要选择相关type字段,对当前的状态进行过滤,过滤出TCP Connect完整建立的那次调用

1. LSM Hook点被多次调用的问题

\linux-2.6.32.63\net\socket.c

SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr, int, addrlen)
{
  .../*
调用该BSD socket对应的connect调用
这里的sock是在前面的socket调用的时候就初始化的,对应于TCP的BSD socket的操作符集是inet_stream_ops
要注意的是:
网络子模块在内核初始化的时候(linux-2.6.32.63\net\ipv4\af_inet.c->inet_init()中)就注册了TCP,UDP和RAW3中协议
linux-2.6.32.63\net\ipv4\af_inet.c
const struct proto_ops inet_stream_ops =
{
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release,
.bind = inet_bind,
.connect = inet_stream_connect,
.socketpair = sock_no_socketpair,
.accept = inet_accept,
.getname = inet_getname,
.poll = tcp_poll,
.ioctl = inet_ioctl,
.listen = inet_listen,
.shutdown = inet_shutdown,
.setsockopt = sock_common_setsockopt,
.getsockopt = sock_common_getsockopt,
.sendmsg = tcp_sendmsg,
.recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap,
.sendpage = tcp_sendpage,
.splice_read = tcp_splice_read,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_sock_common_setsockopt,
.compat_getsockopt = compat_sock_common_getsockopt,
#endif
};
从上面的结构中可以看到connect对应的函数是inet_stream_connect,我们继续分析inet_stream_connect函数
*/
err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen, sock->file->f_flags);
out_put:
...
}

\linux-2.6.32.63\net\ipv4\af_inet.c

int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
{
struct sock *sk = sock->sk;
...
switch (sock->state) {
default:
err = -EINVAL;
goto out;
/*
该BSD socket已连接
*/
case SS_CONNECTED:
err = -EISCONN;
goto out;
/*
该BSD socket正在连接
*/
case SS_CONNECTING:
err = -EALREADY;
/* Fall out of switch with err, set for this state */
break;
case SS_UNCONNECTED:
err = -EISCONN;
if (sk->sk_state != TCP_CLOSE)
goto out;
err = sk->sk_prot->connect(sk, uaddr, addr_len);
if (err < )
goto out;
/*
上面的调用完成后,连接并没有完成
*/
sock->state = SS_CONNECTING; /* Just entered SS_CONNECTING state; the only
* difference is that return value in non-blocking
* case is EINPROGRESS, rather than EALREADY.
*/
err = -EINPROGRESS;
break;
}
...
}
EXPORT_SYMBOL(inet_stream_connect);

从源代码里可以看到,security_socket_connect()在每次sys_connect被调用时都会被调用,而我们的目的只是针对TCP Connect这个动作捕获一次包含实际数据的socket动作即可,因此需要对security_socket_connect进行过滤,可以用于过滤的字段有

. struct inet_sock->is_icsk
. struct socket->state
. struct socket->type
. struct sockaddr->sa_family

除此之外,针对socket中的IP、Port等信息的获取也存在问题,代码实现请参阅"0x4: 针对sys_connect使用LSM Hook方式获取socke TCP Connect连接的IP、Port参数"

参考一下TOMOYO Linux的做法,相关知识请参阅另一篇文章

http://www.cnblogs.com/LittleHann/p/4149509.html

我们可以模仿TOMOYO从SOCKET相关数据结构中获取IP、PORT的做法,在编程中,我们需要注意以下几点

. socket_connect的被调用频率是很高的,需要针对TCP Connect(IPv4、IPv6)进行过滤
) struct socket->type
1.1) case SOCK_STREAM: stream (connection) socket
1.2) case SOCK_SEQPACKET: sequential packet socket
//从所有sys_connect动作中过滤出TCP Socket之后,继续下一层过滤
) struct socket->state
2.1) case SS_UNCONNECTED: 只有在这个状态下,内核的SOCKET代码才会调用inet_stream_connect发起TCP连接
//过滤出TCP connect连接之后,继续下一层过滤
) struct sockaddr->sa_family
3.1) AF_INET6
3.2) AF_INET . 从网络的角度理解,SOCKET的建立本质上一次网络状态的建立过程,它有很多次的握手交互子过程组成,每一次获取和设置的信息都似乎不同的
) 对于kretprobe来说,它是在整个sys_socketcall调用结束之后才获得回调触发的,此时SOCKET的相关信息已经全部填充完成,是可以获取到参数的
) 而对于LSM Hook框架来说,针对sys_connect的LSM Hook点是在函数的入口就被触发调用的,这个时候,TCP Connect的建立还未完成,有很多的元数据是拿不到的

翻阅sys_connect的内核代码可以得出以下结论

. 目的(对端)SOCKET信息(IP、PORT)
在sys_connect传入的"struct sockaddr *uaddr"中保存,这个变量中保存的是最原始的数据,内核代码中其他的变量都是从这里开始获取的
/*
...
struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
daddr = usin->sin_addr.s_addr;
dport = usin->sin_port;
...
*/ . 源(本端)SOCKET信息(IP、PORT)
严格来说,源SOCKET信息应该是在sys_bind,即socket初始化建立的时候由用户传入配置的,这些源SOCKET信息在整个socket变量生命周期中都一直有效,所以,我们获取源SOCKET信息的来源应该是"struct sock *sk"变量
/*
...
struct inet_sock *inet = inet_sk(sk);
inet->sport
inet->saddr
*/

所以,我们的LSMs代码中对源、目的SOCKET信息的获取应该分别从"struct sock *sk"、"struct sockaddr *uaddr"中获取

相关的代码,请参阅"0x4: 针对sys_connect使用LSM Hook方式获取socke TCP Connect连接的IP、Port参数"

aaarticlea/png;base64,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" alt="" />

对于使用LSMs Hook方式获取SOCKET相关信息,存在一点局限性,即sport无法获取到

\linux-2.6.32.63\net\ipv4\tcp_ipv4.c

int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
...
/* Socket identity is still unknown (sport may be zero).
* However we set state to SYN-SENT and not releasing socket
* lock select source port, enter ourselves into the hash tables and
* complete initialization after this.
*/
tcp_set_state(sk, TCP_SYN_SENT);
err = inet_hash_connect(&tcp_death_row, sk);
if (err)
goto failure; err = ip_route_newports(&rt, IPPROTO_TCP, inet->sport, inet->dport, sk);
if (err)
goto failure; /* OK, now commit destination to socket. */
sk->sk_gso_type = SKB_GSO_TCPV4;
sk_setup_caps(sk, &rt->u.dst); if (!tp->write_seq)
tp->write_seq = secure_tcp_sequence_number(inet->saddr,
inet->daddr,
inet->sport,
usin->sin_port);
...

在内核代码的注释中对这一现象作出了解释,因为TCP连接中的"源端口"是一个系统稀缺资源,内核在收到TCP Connect动作的时候,需要从本地"端口池(/proc/sys/net/ipv4/ip_local_port_range 中配置)"中选取一个可用的端口,并分配给当前的socket,并填充路由表,然后才能发起真正的连接

关于内核中SOCKET端口选取的相关知识,请参阅另一篇文章

http://www.cnblogs.com/LittleHann/p/3875451.html
//搜索:2. connect() API原理

那现在问题来了,我们能不能像之前获取sys_execve的命令行参数一样,通过拷贝内核源代码,模拟这个端口选取的过程,在我们的LSMs代码中进行模拟执行,从而确定这个sport呢?答案是不行,原理还是一样的,我们要拷贝模拟执行的操作会对当前Linux内核的状态进行"改变",会破坏当前Kernel的一致性

. 会改变当前socket的state状态
. 会在hash表中增加entry
. 这两个操作涉及到的内核代码很逗,且如果模拟执行后无法进行逆向回滚

暂时没有解决方案

Relevant Link:

0x4: sys_init_module

\linux-2.6.32.63\security\security.c

int security_kernel_create_files_as(struct cred *new, struct inode *inode)
{
return security_ops->kernel_create_files_as(new, inode);
} int security_kernel_module_request(void)
{
return security_ops->kernel_module_request();
}

待研究

4. LSM编程示例

0x1: 获取当前执行进程的绝对路径

execve_lsm_hook.c

#include <linux/security.h>
#include <linux/sysctl.h>
#include <linux/ptrace.h>
#include <linux/prctl.h>
#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/dcache.h>
#include <linux/path.h>
#include <linux/kprobes.h>
#include <linux/module.h> static int (*register_security_p)(struct security_operations *ops);
static int (*unregister_security_p)(struct security_operations * ops); // do nothing
int kprobe_pre(struct kprobe *p, struct pt_regs *regs)
{
return ;
} static void* acquire_func_by_kprobe(char* func_name)
{
void *symbol_addr=NULL;
struct kprobe kp; do
{
memset(&kp, , sizeof(kp));
kp.symbol_name = func_name;
kp.pre_handler = kprobe_pre;
if(register_kprobe(&kp) != )
{
symbol_addr=(void*)kp.addr;
break;
}
//this is the address of "symbol_name"
symbol_addr = (void*)kp.addr; //now kprobe is not used any more,so unregister it
unregister_kprobe(&kp); }while(false); return symbol_addr;
} int execve_lsm_hook(struct linux_binprm *bprm)
{
struct cred *currentCred; if (bprm->filename)
{
printk("file: %s\n", bprm->filename);
//printk("file argument: %s\n",bprm->p);
}
else
{
printk("file exec\n");
} currentCred = current->cred;
printk(KERN_INFO "uid = %d\n", currentCred->uid);
printk(KERN_INFO "gid = %d\n", currentCred->gid);
printk(KERN_INFO "suid = %d\n", currentCred->suid);
printk(KERN_INFO "sgid = %d\n", currentCred->sgid);
printk(KERN_INFO "euid = %d\n", currentCred->euid);
printk(KERN_INFO "egid = %d\n", currentCred->egid); printk("comm: %s\n", current->comm); return ;
} static struct security_operations test_security_ops =
{
.name = "test",
.bprm_check_security = execve_lsm_hook,
}; static __init int test_init(void)
{
int ret_val = -; //获取register_security的导出地址
register_security_p = acquire_func_by_kprobe("register_security");
printk("register_security:%p\n", register_security_p);
if (!register_security_p)
{
printk("get register_security error\n");
} //获取unregister_security的导出地址
unregister_security_p = acquire_func_by_kprobe("unregister_security");
printk("unregister_security:%p\n", unregister_security_p);
if (!unregister_security_p)
{
printk("get unregister_security error\n");
} //注册LSMsbas
//if (register_security_p && unregister_security_p)
if (register_security_p)
{
ret_val = register_security_p(&test_security_ops);
printk("register_security:%d\n", ret_val);
} return ;
} static void test_cleanup(void)
{
int ret_val=-; //if (register_security_p && unregister_security_p)
if (unregister_security_p)
{
ret_val = register_security_p(&test_security_ops);
printk("register_security:%d\n", ret_val);
} return;
} module_init(test_init);
module_exit(test_cleanup); //一定要有这个声明,否则会有unknown module symbol error
MODULE_LICENSE("GPL");

Makefile

obj-m := execve_lsm_hook.o
PWD := $(shell pwd) all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean:
rm -rf *.o *~ core .*.cmd *.mod.c ./tmp_version *.ko modules.order Module.symvers clean_omit:
rm -rf *.o *~ core .*.cmd *.mod.c ./tmp_version modules.order Module.symvers

Relevant Link:

http://hi.baidu.com/wzt85/item/275a9651277866aaacc857d5

0x2: 通过arg_start、arg_end对应的内存获取进程参数

get_arc_from_current.c

#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/cred.h>
#include <linux/sched.h>
#include <linux/mm_types.h>
#include <linux//vmalloc.h>
#include <linux/cache.h>
#include <asm/cacheflush.h>
#include <linux/pagemap.h> static void util_get_task_name(struct task_struct* arg_task)
{
struct task_struct *task = arg_task;
char *name = NULL;
char *argv = NULL; if(task != NULL)
{
name = kmalloc(PATH_MAX, GFP_ATOMIC);
argv = kmalloc(PATH_MAX, GFP_ATOMIC);
char *buffer = NULL;
struct mm_struct *mm = get_task_mm(task);
int len = ;
unsigned long address = ; if(!name || !mm)
goto out; down_read(&mm->mmap_sem); len = mm->arg_end - mm->arg_start;
address = mm->arg_start;
buffer = name; while(len)
{
void *maddr = NULL;
struct page *page = NULL;
struct vm_area_struct *vma = NULL;
int bytes = , offset = ; int ret = get_user_pages(task, mm, address, , , , &page, &vma); if(ret <= )
{
bytes = ret;
goto next;
} bytes = len;
offset = address & (PAGE_SIZE-); if (bytes > PAGE_SIZE-offset)
{
bytes = PAGE_SIZE - offset;
} maddr = kmap(page);
copy_from_user_page(vma, page, address, buffer, maddr + offset, bytes);
kunmap(page); page_cache_release(page); next:
len -= bytes;
address += bytes;
buffer += bytes;
} up_read(&mm->mmap_sem);
mmput(mm); printk("name = %s, len = %d\n", name, len);
//这里需要调整一下参数,因为进程的参数是以空格作为分隔的,需要将以空格分隔的参数串分离出来分别打印
name += ;
printk("arg = %s, len = %d\n", name, len);
} out:
if(name)
{
kfree(name);
}
return;
} static int __init hello_init(void)
{
struct cred *currentCred;
currentCred = current->cred;
printk(KERN_INFO "uid = %d\n", currentCred->uid);
printk(KERN_INFO "gid = %d\n", currentCred->gid);
printk(KERN_INFO "suid = %d\n", currentCred->suid);
printk(KERN_INFO "sgid = %d\n", currentCred->sgid);
printk(KERN_INFO "euid = %d\n", currentCred->euid);
printk(KERN_INFO "egid = %d\n", currentCred->egid); util_get_task_name(current); printk(KERN_INFO "Hello world!\n");
return ; // Non-zero return means that the module couldn't be loaded.
} static void __exit hello_cleanup(void)
{
printk(KERN_INFO "Cleaning up module.\n");
} module_init(hello_init);
module_exit(hello_cleanup);
MODULE_LICENSE("GPL");

Makefile

obj-m := get_arc_from_current.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd) all:
$(MAKE) -C $(KDIR) M=$(PWD) modules clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean

Relevant Link:

http://laokaddk.blog.51cto.com/368606/694037/

0x3: 针对sys_execve使用LSM Hook方式获取进程命令行参数

get_arc_by_hacking.c

#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h> // included for KERN_INFO
#include <linux/init.h> // included for __init and __exit macros
#include <linux/cred.h>
#include <linux/sched.h>
#include <linux/mm_types.h>
#include <linux//vmalloc.h>
#include <linux/cache.h>
#include <asm/cacheflush.h>
#include <linux/pagemap.h> #ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/kallsyms.h>
#include <linux/syscalls.h>
#include <asm/unistd.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/kprobes.h>
#include <linux/security.h>
#include <linux/binfmts.h>
#include <asm/current.h>
#include <linux/threads.h>
#include <linux/mm.h>
#include <asm/page.h> static struct security_operations sec_ops;
static int (*register_security_p)(struct security_operations *ops);
static int (*unregister_security_p)(struct security_operations * ops);
static int (*access_process_vm_p)(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); // do nothing
int kprobe_pre(struct kprobe *p, struct pt_regs *regs)
{
return ;
} //使用kprobe获取内核中任意函数的地址
static void* acquire_func_by_kprobe(char* func_name)
{
void *symbol_addr = NULL;
struct kprobe kp; do
{
memset(&kp,,sizeof(kp));
kp.symbol_name=func_name;
kp.pre_handler=kprobe_pre;
if(register_kprobe(&kp)!=)
{
symbol_addr=(void*)kp.addr;
break;
}
symbol_addr=(void*)kp.addr;
//now kprobe is not used any more,so unregister it
unregister_kprobe(&kp); }while(false); return symbol_addr;
} //根据arg_start、arg_end从内核内存地址空间中直接复制出参数字符串,模拟proc_pid_cmdline这个函数的代码逻辑
static int proc_cmdline(unsigned long start, unsigned long end, char * buffer)
{
int res = , i;
unsigned int len; struct task_struct * task = current;
struct mm_struct *mm = get_task_mm(task);
//struct mm_struct *mm = bprm->mm;
printk("proc_cmdline, mm = %p, arg_start = %d , arg_end=%d\n", mm, mm->arg_start, mm->arg_end);
if (!mm)
goto out; if (!mm->arg_end)
{
if(end <= start)
goto out_mm;
} len = end - start;
printk("args len = %d\n", len); if (len > PAGE_SIZE)
len = PAGE_SIZE; if (access_process_vm_p)
{
res = access_process_vm_p(task, mm->arg_start, buffer, len, );
}
//res = access_vm(task, mm->arg_start, buffer, len, 0); // If the nul at the end of args has been overwritten, then
// assume application is using setproctitle(3).
if (res > && buffer[res-] != '\0' && len < PAGE_SIZE)
{
len = strnlen(buffer, res);
if (len < res)
{
res = len;
}
else
{
len = mm->env_end - mm->env_start;
if (len > PAGE_SIZE - res)
{
len = PAGE_SIZE - res;
}
if (access_process_vm_p)
{
res += access_process_vm_p(task, mm->env_start, buffer+res, len, );
}
//res += access_vm(task, mm->env_start, buffer+res, len, 0);
res = strnlen(buffer, res);
}
} printk("arg 1 :%s\n", buffer);
//命令行参数是以空格结尾的,这里临时跳过这段空格,真正编码的时候需要针对空格作"replace"处理,才能正常打印出来
printk("arg 2 : %s\n", buffer+); out_mm:
mmput(mm);
printk("out_mm\n");
out:
printk("out\n");
return res;
} void print_current()
{
struct cred *currentCred;
currentCred = current->cred;
printk(KERN_INFO "uid = %d\n", currentCred->uid);
printk(KERN_INFO "gid = %d\n", currentCred->gid);
//printk(KERN_INFO "suid = %d\n", currentCred->suid);
//printk(KERN_INFO "sgid = %d\n", currentCred->sgid);
printk(KERN_INFO "euid = %d\n", currentCred->euid);
printk(KERN_INFO "egid = %d\n", currentCred->egid);
printk(KERN_INFO "tid = %d\n", task_tgid_vnr(current));
printk(KERN_INFO "sid = %d\n", task_session_vnr(current));
printk(KERN_INFO "pid = %d\n", current->pid);
printk(KERN_INFO "tgid = %d\n", current->tgid); printk(KERN_INFO "tty name: %s\n", current->signal->tty);
printk(KERN_INFO "programe name: %s\n", current->comm);
return;
} //模拟内核代码对arg_start、arg_end的计算
int fake_cmdline(int argc)
{
char buffer[] = {};
unsigned long start ,end, p; start = current->mm->arg_start;
end = current->mm->arg_end;
p = current->mm->arg_start; printk("argc = %d, start =%p, end=%p, p =%p\n", argc, start, end, p); while (argc-- > )
{
size_t len;
len = strnlen_user((void __user *)p, MAX_ARG_STRLEN);
if (!len || len > MAX_ARG_STRLEN)
return -EINVAL;
//将p指针指向当前进程参数的结束地址内存区
p += len;
} end = p;
printk("argc = %d, start =%p, end=%p, p =%p\n", argc, start, end, p);
//根据arg_start、arg_end从内核内存地址空间中直接复制出参数字符串,模拟proc_pid_cmdline这个函数的代码逻辑
proc_cmdline(start, end , buffer); //打印current信息,验证当前LSM Hook点是否已经完成了current的赋值,因为Linux中所有的进程都是父进程"复制"出来的,在新进程创建的过程中,新进程的current是逐步填充设置为新进程的相关信息
print_current();
return ;
} void security_bprm_committed_creds(struct linux_binprm *bprm)
{
printk("security_bprm_committed_creds\n"); do
{
if (bprm->filename)
{
printk("in committed cred pid = %d, mm:%p, file:%s\n",current->pid, current->mm, bprm->filename);
}else
{
printk("file exec\n");
} //模拟内核代码对arg_start、arg_end的计算
fake_cmdline(bprm->argc);
} while (false); return;
} static int __init hello_init(void)
{
int ret_val = -; do
{
memset(&sec_ops, , sizeof(sec_ops));
sprintf(sec_ops.name,"aegis_lsm"); sec_ops.bprm_committed_creds = security_bprm_committed_creds; //获取access_process_vm函数的内核地址
access_process_vm_p = acquire_func_by_kprobe("access_process_vm");
printk("access_process_vm:%p\n", access_process_vm_p);
if (!access_process_vm_p)
{
printk("get access_process_vm error\n");
} //获取LSM注册函数register_security的内核地址
register_security_p = acquire_func_by_kprobe("register_security");
printk("register_security:%p\n", register_security_p);
if (!register_security_p)
{
printk("get register_security error\n");
} //获取LSM注销函数unregister_security的内核地址
unregister_security_p = acquire_func_by_kprobe("unregister_security");
printk("unregister_security:%p\n", unregister_security_p);
if (!unregister_security_p)
{
printk("get unregister_security error\n");
} //注册LSM Hook模块
if (register_security_p)
{
ret_val = register_security_p(&sec_ops);
printk("register_security successfully: %d\n", ret_val);
break;
}
}
while(false); printk(KERN_INFO "Hello world!\n");
return ret_val;
} static void __exit hello_cleanup(void)
{
if (unregister_security_p)
{
unregister_security_p(&sec_ops);
}
printk(KERN_INFO "Cleaning up module.\n");
} module_init(hello_init);
module_exit(hello_cleanup);
MODULE_LICENSE("GPL");

aaarticlea/png;base64,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" alt="" />

0x4: 针对sys_connect使用LSM Hook方式获取socke TCP Connect连接的IP、Port参数

get_ip_by_lsm.c

#ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kallsyms.h>
#include <linux/syscalls.h>
#include <asm/unistd.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/security.h>
#include <asm/current.h>
#include <linux/threads.h>
#include <linux/sched.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
#include <linux/pagemap.h> #include <linux/inet.h>
#include <linux/ipv6.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/string.h>
#include <linux/version.h> #include <linux/module.h>
#include <linux/binfmts.h>
#include <linux/kprobes.h>
#include <linux/slab.h>
#include <linux/tty.h> //thread header
#include <linux/kthread.h>
#include <linux/mm.h> //modinfo header
#include <linux/vmalloc.h> #include <net/ipv6.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 25)
#define SADDR saddr
#define DADDR daddr
#define SPORT sport
#define DPORT dport
#else
#define SADDR inet_saddr
#define DADDR inet_daddr
#define SPORT inet_sport
#define DPORT inet_dport
#endif typedef void* (*look_up_symbol_t)(char*); static void* (*look_up_symbol)(char*); static struct security_operations org_sec_ops_back_up;
static struct security_operations *org_sec_ops_p = NULL; static struct security_operations sec_ops;
static int (*register_security_p)(struct security_operations *ops);
static int (*unregister_security_p)(struct security_operations * ops); static unsigned int wpoff_cr0_32(void)
{
unsigned int cr0 = ;
unsigned int ret=;
asm volatile ("movl %%cr0, %%eax":"=a"(cr0)); //汇编代码,用于取出CR0寄存器的值
ret = cr0;
cr0 &= 0xfffeffff;
asm volatile ("movl %%eax, %%cr0": :"a"(cr0));//汇编代码,将修改后的CR0值写入CR0寄存器
return ret;
} static unsigned long int wpoff_cr0_64(void)
{
unsigned long int cr0 = ;
unsigned long int ret=;
asm volatile ("movq %%cr0, %%rax":"=a"(cr0)); //汇编代码,用于取出CR0寄存器的值
ret = cr0;
cr0 &= 0xfffffffffffeffff;
asm volatile ("movq %%rax, %%cr0": :"a"(cr0));//汇编代码,将修改后的CR0值写入CR0寄存器 return ret;
} static unsigned long int wpoff_cr0(void)
{
if(sizeof(void*)==)
{
return wpoff_cr0_32();
}else
{
return wpoff_cr0_64();
}
} static void set_cr0_32(unsigned int val)
{
asm volatile ("movl %%eax, %%cr0": :"a"(val));
return;
} static void set_cr0_64(unsigned long int val)
{
asm volatile ("movq %%rax, %%cr0": :"a"(val));
return;
} static void set_cr0(unsigned long int val)
{
if(sizeof(void*)==)
{
set_cr0_32((unsigned int)val);
}else
{
set_cr0_64(val);
}
} static void SLEEP_MILLI_SEC(int nMilliSec)
{ long timeout = (nMilliSec) * HZ / ; while(timeout > )
{
timeout = schedule_timeout(timeout);
}
} // do nothing
int kprobe_pre(struct kprobe *p, struct pt_regs *regs)
{
return ;
} //使用kprobe获取内核中任意函数的地址
static void* acquire_func_by_kprobe(char* func_name)
{
void *symbol_addr = NULL;
struct kprobe kp; do
{
memset(&kp,,sizeof(kp));
kp.symbol_name=func_name;
kp.pre_handler=kprobe_pre;
if(register_kprobe(&kp)!=)
{
symbol_addr=(void*)kp.addr;
break;
}
symbol_addr=(void*)kp.addr;
//now kprobe is not used any more,so unregister it
unregister_kprobe(&kp); }while(false); return symbol_addr;
} static look_up_symbol_t init_lookup_func(void)
{
if (!look_up_symbol)
{
look_up_symbol = (look_up_symbol_t)acquire_func_by_kprobe("kallsyms_lookup_name");
} return look_up_symbol;
} //判断当前socket连接是否为"SS_UNCONNECTED"状态,只有在这个状态下,才是TCP Connect最初发起连接的那一次
int is_inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
{
int ret = ;
int err = ;
struct sock *sk = sock->sk;
const unsigned int type = sock->type; //1. struct socket->type
switch (type)
{
case SOCK_DGRAM:
case SOCK_RAW:
ret = ;
break;
case SOCK_STREAM:
case SOCK_SEQPACKET:
ret = ;
//2. struct socket->state
if (uaddr->sa_family == AF_UNSPEC)
{
goto out;
}
if (sk->sk_state == TCP_CLOSE)
{
goto sock_error;
}
switch (sock->state)
{
case SS_CONNECTED:
ret = ;
break;
case SS_CONNECTING:
ret = ;
break;
//我们真正需要捕获的TCP Conncet动作
case SS_UNCONNECTED:
ret = ;
//3. struct sockaddr->sa_family
switch (uaddr->sa_family)
{
case AF_INET6:
case AF_INET:
ret = ;
break;
default:
ret = ;
}
break;
default:
ret = ;
}
break;
default:
ret = ;
} out:
return ret; sock_error:
goto out;
} void socket_connect_log(struct socket *sock, struct sockaddr *addr, int addr_len)
{
int ret = ;
const __be32 *daddr = NULL;
__be16 dport = ;
__be16 sport = ;
const __be32 *saddr = NULL; pid_t pid = current->pid; do
{
ret = ;
//过滤冗余事件
ret = is_inet_stream_connect(sock, (struct sockaddr *)&addr, addr_len, sock->file->f_flags);
if (ret != )
{
goto skip;
} //获取待连接的对端的IP、PORT信息
switch (addr->sa_family)
{
case AF_INET6:
if (addr_len < SIN6_LEN_RFC2133)
{
goto skip;
}
daddr = (__be32 *) ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
dport = ((struct sockaddr_in6 *) addr)->sin6_port;
saddr = &inet_sk(sock->sk)->SADDR;
//sport = ntohs(inet_sk(sock->sk)->SPORT);
sport = inet_sk(sock->sk)->SPORT;
break;
case AF_INET:
if (addr_len < sizeof(struct sockaddr_in))
{
goto skip;
}
daddr = (__be32 *) &((struct sockaddr_in *) addr)->sin_addr;
dport = ((struct sockaddr_in *) addr)->sin_port;
saddr = &inet_sk(sock->sk)->SADDR;
//sport = ntohs(inet_sk(sock->sk)->SPORT);
sport = inet_sk(sock->sk)->SPORT;
break;
default:
daddr = NULL;
dport = ;
saddr = NULL;
sport = ;
goto skip;
} //printk("process: %d, daddr: %s, dport: %d\n", pid, daddr, dport);
printk("process: %d, saddr: %d:%d, daddr: %d:%d\n", pid, saddr, sport, daddr, dport); } while (false); skip:
return;
} static int __init hello_init(void)
{
int ret_val = -;
unsigned long int cr0 = ; do
{
memset(&sec_ops, , sizeof(sec_ops));
//sprintf(sec_ops.name,"aegis_lsm"); //针对TCP CONNECT连接动作进行Hook
sec_ops.socket_connect = socket_connect_log; if (!init_lookup_func())
{
break;
} //获取LSM注册函数register_security的内核地址
register_security_p = acquire_func_by_kprobe("register_security");
printk("register_security:%p\n", register_security_p);
if (!register_security_p)
{
printk("get register_security error\n");
} //获取LSM注销函数unregister_security的内核地址
unregister_security_p = acquire_func_by_kprobe("unregister_security");
printk("unregister_security:%p\n", unregister_security_p);
if (!unregister_security_p)
{
printk("get unregister_security error\n");
} //注册LSM Hook模块
if (register_security_p)
{
ret_val = register_security_p(&sec_ops);
printk("register_security successfully: %d\n", ret_val);
break;
} memset(&org_sec_ops_back_up, , sizeof(org_sec_ops_back_up));
//获取内核中security_ops(LSM Table)的地址
org_sec_ops_p = look_up_symbol("security_ops");
if (!org_sec_ops_p)
{
break;
}
org_sec_ops_p = *(void**)org_sec_ops_p;
printk("org_sec_ops:%p\n", org_sec_ops_p);
//保存内核中的"security_ops"
memcpy(&org_sec_ops_back_up, org_sec_ops_p, sizeof(org_sec_ops_back_up)); cr0 = wpoff_cr0();
org_sec_ops_p->socket_connect = socket_connect_log;
set_cr0(cr0); ret_val = ;
}
while(false); printk(KERN_INFO "Hello world!\n");
return ret_val;
} static void __exit hello_cleanup(void)
{
unsigned long int cr0 = ; if (unregister_security_p)
{
unregister_security_p(&sec_ops);
}
else if(org_sec_ops_p)
{
cr0 = wpoff_cr0();
org_sec_ops_p->socket_connect = org_sec_ops_back_up.socket_connect;
set_cr0(cr0); SLEEP_MILLI_SEC();
}
printk(KERN_INFO "Cleaning up module.\n");
} module_init(hello_init);
module_exit(hello_cleanup);
MODULE_LICENSE("GPL");

5. Linux LSM stacking

我们知道,LSM Hook Function被保存在内核内存的一个全局数组(security_ops)中,在正常流程中,调用register_security()向系统注册一个LSM回调函数,如果当前已经开启了SELINUX,即当前挂载点已经注册了一个LSM回调函数,则后来的register_security()会失败,即默认情况下,每个LSM挂载点最多只能注册一个回调函数
LSM的一个Patch Project可以使得LSM支持"模块栈式函数挂载"
Linux kernel patches to support LSM (security module) stacking, plus a module which actively stacks LSMs.

LSM Stacking Patch使用了一个内核标准双链表将Stacking链式的LSM模块进行存储,采用FIFO的形式进行链式存储,这样,多个LSM模块可以堆叠式地注册到系统中,

Relevant Link:

http://lsm-stacker.sourceforge.net/
http://sourceforge.net/projects/lsm-stacker/files/
http://t75040.security-selinux.securetalk.info/current-future-plans-to-support-stacking-lsm-modules-t75040-20.html

Copyright (c) 2014 LittleHann All rights reserved

Linux LSM(Linux Security Modules) Hook Technology的更多相关文章

  1. Linux Overflow Vulnerability General Hardened Defense Technology、Grsecurity/PaX

    Catalog . Linux attack vector . Grsecurity/PaX . Hardened toolchain . Default addition of the Stack ...

  2. 计算机BIOS的简单设置(要安装Linux需关闭Security Boot选项)

    计算机BIOS的简单设置(要安装Linux需关闭Security Boot选项) 发布时间:2016-12-07 22:46:19来源:linux网站作者:乐百川 BIOS是什么 BIOS全称是基本输 ...

  3. Linux (Windows Linux子系统)

    Linux (Windows Linux子系统) 如果想体验Linux环境下开发和运行.NET Core应用,我们有多种选择.一种就是在一台物理机上安装原生的Linux,我们可以根据自身的喜好选择某种 ...

  4. rsync从linux到linux的文件同步备份

    rsync从linux到linux的文件同步备份 一.环境 需要备份文件的服务器(服务器端):192.168.1.201 (RHEL 5) 接收备份文件的服务器(客户端):192.168.1.202 ...

  5. 【原创】xenomai3.1+linux构建linux实时操作系统-基于X86_64和arm

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 一.概要 二.环境准备 1.1 安装内核编译工 ...

  6. 【Linux】Linux中在mate桌面和gnome桌面root自动登录设置

    [Linux]Linux中在mate桌面和gnome桌面root自动登录设置 GLL_ 2020-03-05 11:41:40  762  收藏 1 分类专栏: Linux 文章标签: linux 版 ...

  7. Linux 与 Linux Windows 文件共享 小知识

    Linux 与 Linux Windows 文件共享   前提说明:windows主机信息:192.168.1.100 帐号:abc 密码:123 共享文件夹:sharelinux主机信息:192.1 ...

  8. 【Linux】Linux中常用操作命令

    博客已转移,请借一步说话,http://www.weixuehao.com/archives/25 Linux简介及Ubuntu安装 常见指令 系统管理命令 打包压缩相关命令 关机/重启机器 Linu ...

  9. linux与linux,linux与windows之间用SSH传输文件

    linux与linux,linux与windows之间用SSH传输文件linux与linux之间传送文件:scp file username@hostIP:文件地址    例: scp abc.txt ...

随机推荐

  1. 日期选择器:jquery datepicker的使用

    helloweba.com 作者:月光光 时间:2012-04-08 21:05 标签: jquery  datepicker  jquery ui     在jquery ui中,提供了一个非常实用 ...

  2. [解决方案]在Sql Server 2008/2005 数据库还原出现 3154错误

    在Sql Server 2008/2005 数据库还原出现 3154错误 解决方法1:不要在数据库名字上点右键选择还原,而要是在根目录“数据库”三个字上点右键选择还原,然后再选择数据库,问题便可以解决 ...

  3. php基础22:上传并且保存文件

    <?php /* 文件上传的限制 && 保存被上传的文件 在这个脚本中,我们增加了对文件上传的限制.用户只能上传 .gif 或 .jpeg 文件,文件大小必须小于 20 kb: ...

  4. Sql语句里的递归查询

    Sql语句里的递归查询 SqlServer2005和Oracle 两个版本 以前使用Oracle,觉得它的递归查询很好用,就研究了一下SqlServer,发现它也支持在Sql里递归查询举例说明:Sql ...

  5. CSS 实现加载动画之六-大风车

    这个动画改编自光盘旋转,前几个步骤一样,最后一步不同.光盘旋转的最后一步是外层容器加个圆形的白色边框,多余部分隐藏,这个案例则是在每个旋转的子元素的顶部或底部增加一个三角形的元素,构成风车旋转的角. ...

  6. 在opencv3中进行图片人脸检测

    在opencv中,人脸检测用的是harr或LBP特征,分类算法用的是adaboost算法.这种算法需要提前训练大量的图片,非常耗时,因此opencv已经训练好了,把训练结果存放在一些xml文件里面.在 ...

  7. 学习Shell脚本编程(第4期)_在Shell程序中的使用变量

    变量的赋值 变量的访问 变量的输入 4.1 变量的赋值     在Shell编程中,所有的变量名都由字符串组成,并且不需要对变量进行声明.要赋值给一个变量,其格式如下: 变量名=值  注意: 等号(= ...

  8. 从0开始学Java——JSP&Servlet——Tomcat和Apache的区别

    从<JSP & Servlet 学习笔记>的第一章,了解到web容器:“Web容器是Servlet/jsp唯一认得的http服务器”. 在Java中,容器的类型有多种,这里要说的是 ...

  9. Linux及安全期中总结

    Chapter1 往期博客传送门 Linux内核分析——第一周学习笔记 Linux内核分析——第二周学习笔记 Linux内核分析——第三周学习笔记 <Linux内核设计与实现>学习记录一 ...

  10. 实践GDB

    调试工具简介:GDB  Unix程序员最常用的调试工具是GDB,这是由Richard Stallman(开源软件运动的领路人) 开发的GNU项目调试器,该工具在Linux开发中扮演了关键的角色. CG ...