Implement your own access control using LSM

First, a brief introduction to LSM is given. Although everyone under linux basically knows something, it still needs to be wordy.
The full name of LSM in Chinese is Linux Security Module. The English full name is Linux Security Module.
LSM is a lightweight and general-purpose access control framework, which is suitable for various access control models to be implemented in the form of kernel modules. Its characteristics are universal, simple, efficient, and support POSIX.1e capability mechanism.
The structure diagram of LSM is as follows:

After entering the kernel through a system call, the system first performs traditional permission checks (traditional permission checks are mainly based on users, and users can access resources after passing authentication), and then mandatory access control will be performed after passing. Mandatory access control is a kind of access control that does not allow the subject to interfere. It uses information sensitivity such as security identification and information classification for access control. And determine whether to allow access by comparing the level of the principal and the sensitivity of the resource. For example, the system sets that user A is not allowed to access file B, even if A is the owner of file B, access is restricted. From the figure above, LSM implements access control mainly through the hook function of the security module.

The LSM framework is mainly composed of five parts (there are many online materials):

  • Added security domains to key specific kernel data structures;
  • Insert calls to security hook functions at different key points in the kernel source code;
  • Provides a common security system call;
  • Provides registration and logout functions, so that access control policies can be implemented as kernel modules;
  • Ported most of the capabilities logic as an optional security module.

Here we focus on explaining the LSM framework combined with the source code (the Linux kernel source code used is 3.5.4).
First, the security domain field is introduced, which is a pointer of empty type and exists in many kernel structures in the kernel. Such as inode, superblock, dentry, file, etc. The type field is void * security;.
So how does the security domain relate to the information in the security module?
After the security module is loaded, the pointer in the security domain points to the security information in the security module. Here we take SElinux as an example for introduction.
The security information of different objects is defined in security/selinux/include/objsec.h in the kernel, and the format is XXX_security_strut.

The security information of the above file includes the security ID when opening the file descriptor, the security ID of the file owner, and so on.
Several control hook functions are needed to contact the security information and security domain in the security module, and these hook functions implement the setting and management of key kernel information. Here we mainly introduce alloc_security and free_security.
In SELinux, association is achieved by implementing security information space allocation. Take file security information as an example:

After the space is allocated successfully, the association is realized through file->f_security = fsec.

To revoke the association is to call the file_free_security function after the security module is uninstalled.

This is achieved by setting file->f_secrity to NULL and then releasing the security information structure.

Now let's see how the kernel implements SELinux access control. The main thing here is to implement the hook function in LSM. The structure security_operations is given in LSM, and many hook functions are given in it, and access control can be realized by implementing related hook functions. 

The above function implements the file_permission hook function. You can look at the acquisition of the inode structure, and feel that the kernel is through file -> directory item -> inode. This function mainly implements its own access control strategy and it is OK.
Taking SELinux as an example, after obtaining the file security ID, it mainly checks the mask and the security information related to the file opening, and if it matches, it passes the access control.

SELinux basically implements all hook functions in LSM. After the hook functions are implemented, it is OK to fill the hook field in LSM.

 

After completing the above, you need to register the security module to LSM. Here, register_security and unregister_security are used for registration and deregistration .
For example, SELinux is implemented using the statement register_security(&selinux_ops) when registering.

Next, through the above analysis, we can implement simple LSM-based access control. The code example is as follows:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

static int lsm_test_file_permission(struct file *file,int mask)
{
    int path=0;
    struct file *filp;
    struct nameidata nd;

    path = path_lookup(FILENAME,LOOKUP_FOLLOW,&nd);
   
    if(!mask)
            return 0;

    if(path)
    {
        printk("lookup file failed!\n");
        return -1;
    }

    filp = filp_open("/home/yuyunchao/code/sb.c",O_RDONLY,0);
    {
    printk("open failed!\n");
    }
    return 0;
}

static struct security_operations lsm_test_security_ops = {
    .file_permission = lsm_test_file_permission,
};

static int __init lsm_file_init(void)
{    
    if(register_security(&lsm_test_security_ops)){
        printk("register error ..........\n");
        return -1;
    }
   
    printk("lsm_file init..\n ");
    return 0;
}

static void __exit lsm_file_exit(void)
{
    if(unregister_security(&lsm_test_security_ops)){
        printk("unregister error................\n");
        return ;
    }

    printk("module exit.......\n");
}

MODULE_LICENSE("GPL");
module_init(lsm_file_init);
module_exit(lsm_file_exit);

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/130767127