Kernel LSM
中提供了大量常用操作的 hook
,可以让开发者在这些操作执行前进行检查,便于对程序进行管控。
但由于 LSM Module
必须编译进内核,因此需要公开源码,这通常不符合很多开发者的要求。
基于这种情况, uos
基于 LSM
开发了一个 hook manager
的模块,可提供接口给开发者使用,达到了动态注册/移除 LSM Hook
的目的。
由于 LSM
提供的接口太多,有些接口基本上很少使用,因此 uos
经过调研, hook manager
计划部分接口的动态注册/移除的功能,接口说明和 hook
列表如下:
enum UOS_HOOK_LIST {
UOS_PATH_UNLINK,
UOS_PATH_MKDIR,
UOS_PATH_RMDIR,
UOS_PATH_MKNOD,
UOS_PATH_TRUNCATE,
UOS_PATH_SYMLINK,
UOS_PATH_LINK,
UOS_PATH_RENAME,
UOS_PATH_CHMOD,
UOS_PATH_CHOWN,
UOS_PATH_CHROOT,
UOS_INODE_CREATE,
UOS_INODE_FREE_SECURITY,
UOS_INODE_FREE,
UOS_INODE_UNLINK,
UOS_INODE_SYMLINK,
UOS_INODE_MKDIR,
UOS_INODE_RMDIR,
UOS_INODE_MKNOD,
UOS_INODE_RENAME,
UOS_INODE_READLINK,
UOS_INODE_FOLLOW_LINK,
UOS_INODE_PERMISSION,
UOS_INODE_SETATTR,
UOS_INODE_SETXATTR,
UOS_INODE_REMOVEEXATTR,
UOS_FILE_PERMISSION,
UOS_FILE_IOCTL,
UOS_MMAP_ADDR,
UOS_MMAP_FILE,
UOS_FILE_LOCK,
UOS_FILE_FCNTL,
UOS_FILE_RECEIVE,
UOS_FILE_OPEN,
UOS_FILE_FREE_SECURITY,
UOS_BPRM_SET_CREDS,
UOS_BPRM_CHECK_SECURITY,
UOS_BPRM_COMMITTING_CREDS,
UOS_BPRM_COMMITTED_CREDS,
UOS_TASK_ALLOC,
UOS_TASK_FREE,
UOS_TASK_FIX_SETUID,
UOS_TASK_SETPGID,
UOS_TASK_GETPGID,
UOS_TASK_GETSID,
UOS_TASK_SETNICE,
UOS_TASK_SETIOPRIO,
UOS_TASK_GETIOPRIO,
UOS_TASK_PRLIMIT,
UOS_TASK_SETRLIMIT,
UOS_TASK_SETSCHEDULER,
UOS_TASK_GETSCHEDULER,
UOS_TASK_MOVEMEMORY,
UOS_TASK_KILL,
UOS_TASK_PRCTL,
UOS_SOCKET_CREATE,
UOS_SOCKET_POST_CREATE,
UOS_SOCKET_SOCKETPAIR,
UOS_SOCKET_BIND,
UOS_SOCKET_CONNECT,
UOS_SOCKET_LISTEN,
UOS_SOCKET_ACCEPT,
UOS_SOCKET_SENDMSG,
UOS_SOCKET_RECVMSG,
UOS_SOCKET_GETSOCKNAME,
UOS_SOCKET_GETPEERNAME,
UOS_SOCKET_GETSOCKOPT,
UOS_SOCKET_SETSOCKOPT,
UOS_SOCKET_SHUTDOWN,
UOS_TUN_DEV_CREATE,
UOS_TUN_DEV_ATTACH_QUEUE,
UOS_TUN_DEV_ATTACH,
UOS_TUN_DEV_OPEN,
UOS_SCTP_ASSOC_REQUEST,
UOS_SCTP_BIND_CONNECT,
UOS_NETLINK_SEND,
UOS_SB_REMOUNT,
UOS_SB_SHOW_OPTIONS,
UOS_SB_STATFS,
UOS_SB_MOUNT,
UOS_SB_UMOUNT,
UOS_SB_SET_MNT_OPTS,
UOS_SB_CLONE_MNT_OPTS,
UOS_SHM_ASSOCIATE,
UOS_SHM_SHMCTL,
UOS_SHM_SHMAT,
UOS_SEM_ASSOCIATE,
UOS_SEM_SEMCTL,
UOS_SEM_SEMOP,
UOS_AUDIT_RULE_INIT,
UOS_AUDIT_RULE_KNOWN,
UOS_AUDIT_RULE_MATCH,
UOS_PTRACE_ACCESS_CHECK,
UOS_PTRACE_TRACEME,
UOS_CAPGET,
UOS_CAPSET,
UOS_CAPABLE,
UOS_SYSLOG,
UOS_SETTIME,
UOS_HOOK_NONE,
};
enum UOS_HOOK_RETURN_TYPE {
UOS_HOOK_RET_TY_NONE,
UOS_HOOK_RET_TY_INT,
};
struct uos_hook_cb_entry {
char *owner; // the module name of the hook
unsigned long cb_addr; // the callback address of the hook
enum UOS_HOOK_RETURN_TYPE ret_type; // the return type of the hook
unsigned int arg_len; // the argument length of the hook
};
int uos_hook_register(enum UOS_HOOK_LIST hook_id, struct uos_hook_cb_entry *entry);
int uos_hook_cancel(enum UOS_HOOK_LIST hook_id, char *owner);
上面定义了 hook manager
提供的接口,开发者使用 uos_hook_register
进行 hook
的注册,使用 uos_hook_cancel
取消注册。
与之对应的 LSM Hook
函数如下:
int (*path_unlink)(const struct path *dir, struct dentry *dentry);
int (*path_mkdir)(const struct path *dir, struct dentry *dentry,
umode_t mode);
int (*path_rmdir)(const struct path *dir, struct dentry *dentry);
int (*path_mknod)(const struct path *dir, struct dentry *dentry,
umode_t mode, unsigned int dev);
int (*path_truncate)(const struct path *path);
int (*path_symlink)(const struct path *dir, struct dentry *dentry,
const char *old_name);
int (*path_link)(struct dentry *old_dentry, const struct path *new_dir,
struct dentry *new_dentry);
int (*path_rename)(const struct path *old_dir, struct dentry *old_dentry,
const struct path *new_dir,
struct dentry *new_dentry);
int (*path_chmod)(const struct path *path, umode_t mode);
int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid);
int (*path_chroot)(const struct path *path);
int (*inode_create)(struct inode *dir, struct dentry *dentry,
umode_t mode);
void (*inode_free_security)(struct inode *inode);
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 inode *inode,
bool rcu);
int (*inode_permission)(struct inode *inode, int mask);
int (*inode_setattr)(struct dentry *dentry, struct iattr *attr);
int (*inode_setxattr)(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
int (*inode_removexattr)(struct dentry *dentry, const char *name);
int (*file_permission)(struct file *file, int mask);
int (*file_ioctl)(struct file *file, unsigned int cmd,
unsigned long arg);
int (*mmap_addr)(unsigned long addr);
int (*mmap_file)(struct file *file, unsigned long reqprot,
unsigned long prot, unsigned long flags);
int (*file_lock)(struct file *file, unsigned int cmd);
int (*file_fcntl)(struct file *file, unsigned int cmd,
unsigned long arg);
int (*file_receive)(struct file *file);
int (*file_open)(struct file *file);
void (*file_free_security)(struct file *file);
int (*bprm_set_creds)(struct linux_binprm *bprm);
int (*bprm_check_security)(struct linux_binprm *bprm);
void (*bprm_committing_creds)(struct linux_binprm *bprm);
void (*bprm_committed_creds)(struct linux_binprm *bprm);
int (*task_alloc)(struct task_struct *task, unsigned long clone_flags);
void (*task_free)(struct task_struct *task);
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);
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_prlimit)(const struct cred *cred, const struct cred *tcred,
unsigned int flags);
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, const struct cred *cred);
int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
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_socketpair)(struct socket *socka, struct socket *sockb);
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);
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 (*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);
int (*sctp_assoc_request)(struct sctp_endpoint *ep,
struct sk_buff *skb);
int (*sctp_bind_connect)(struct sock *sk, int optname,
struct sockaddr *address, int addrlen);
int (*netlink_send)(struct sock *sk, struct sk_buff *skb);
int (*sb_remount)(struct super_block *sb, void *data);
int (*sb_show_options)(struct seq_file *m, struct super_block *sb);
int (*sb_statfs)(struct dentry *dentry);
int (*sb_mount)(const char *dev_name, const struct path *path,
const char *type, unsigned long flags, void *data);
int (*sb_umount)(struct vfsmount *mnt, int flags);
int (*sb_set_mnt_opts)(struct super_block *sb,
struct security_mnt_opts *opts,
unsigned long kern_flags,
unsigned long *set_kern_flags);
int (*sb_clone_mnt_opts)(const struct super_block *oldsb,
struct super_block *newsb,
unsigned long kern_flags,
unsigned long *set_kern_flags);
int (*shm_associate)(struct kern_ipc_perm *shp, int shmflg);
int (*shm_shmctl)(struct kern_ipc_perm *shp, int cmd);
int (*shm_shmat)(struct kern_ipc_perm *shp, char __user *shmaddr,
int shmflg);
int (*sem_associate)(struct kern_ipc_perm *sma, int semflg);
int (*sem_semctl)(struct kern_ipc_perm *sma, int cmd);
int (*sem_semop)(struct kern_ipc_perm *sma, struct sembuf *sops,
unsigned nsops, int alter);
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);
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 (*syslog)(int type);
int (*settime)(const struct timespec64 *ts, const struct timezone *tz);