Skip to content

Instantly share code, notes, and snippets.

@duanhjlt
Forked from jouyouyun/lsm_hookmanager_ifc.org
Created May 15, 2025 08:42
Show Gist options
  • Select an option

  • Save duanhjlt/eb471a1b13a4899ce94a8ae5d7232eae to your computer and use it in GitHub Desktop.

Select an option

Save duanhjlt/eb471a1b13a4899ce94a8ae5d7232eae to your computer and use it in GitHub Desktop.

Revisions

  1. @jouyouyun jouyouyun created this gist Sep 17, 2020.
    303 changes: 303 additions & 0 deletions lsm_hookmanager_ifc.org
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,303 @@
    #+OPTIONS: toc:nil num:nil timestamp:nil ^:nil <:nil
    #+TITLE: UOS LSM Hook Manager

    =Kernel LSM= 中提供了大量常用操作的 =hook= ,可以让开发者在这些操作执行前进行检查,便于对程序进行管控。
    但由于 =LSM Module= 必须编译进内核,因此需要公开源码,这通常不符合很多开发者的要求。
    基于这种情况, =uos= 基于 =LSM= 开发了一个 =hook manager= 的模块,可提供接口给开发者使用,达到了动态注册/移除 =LSM Hook= 的目的。


    ** 接口描述


    由于 =LSM= 提供的接口太多,有些接口基本上很少使用,因此 =uos= 经过调研, =hook manager= 计划部分接口的动态注册/移除的功能,接口说明和 =hook= 列表如下:

    #+BEGIN_SRC c
    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);
    #+END_SRC

    --------

    上面定义了 =hook manager= 提供的接口,开发者使用 =uos_hook_register= 进行 =hook= 的注册,使用 =uos_hook_cancel= 取消注册。

    与之对应的 =LSM Hook= 函数如下:

    #+BEGIN_SRC c
    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);
    #+END_SRC