Using the Kernel Security Module Interface

Greg shows how to create a simple kernel module that uses the LSM framework.

At the 2001 Linux Kernel Summit, NSA developers presented their work on Security-Enhanced Linux (SELinux) and emphasized the need for enhanced security support in the main Linux kernel. In the ensuing discussion, a consensus was reached that a general access-control framework for the Linux kernel was needed. This approach would allow different security models to work without modifying the main kernel code.

Out of this discussion grew the Linux Security Module Project (LSM). A number of developers worked together to create a framework of kernel hooks that would allow many security models to work as loadable kernel modules. A detailed description of the design of this general-purpose system was published in a paper at the 2002 USENIX Security Conference (lsm.immunix.org/docs/lsm-usenix-2002/html/) and a technical description of how the LSM interface works was presented in a paper at the 2002 Ottawa Linux Symposium (www.linux.org.uk/~ajh/ols2002_proceedings.pdf.gz).

During the 2002 Linux Kernel Summit, the technical description of the project was presented, and the first portion of the LSM framework appeared in the 2.5.29 kernel release. Further kernel releases contained more portions of the LSM framework, and hopefully the entire patch will be included by the time of the 2.6.0 release.

This article does not attempt to describe how the LSM framework works or the design decisions that were made in creating it; the previously mentioned references do an excellent job of that. Instead, this article shows how easy it is to create a simple kernel module that uses the LSM framework.

Root Plug

Our example uses the 2.5.31 kernel release, which contains enough of the LSM interface for us to create a useful module. In our module, we want to prevent any programs with the group ID of 0 (root) from running if a specific USB device is not plugged in to the machine at that moment. This provides us with a simple way of preventing root exploits from running on our machine, or for new users to log in when we are not present.

This example creates a kernel module called root_plug, which is available as a patch against a clean 2.5.31 kernel tree from the Linux Journal FTP site [ftp.linuxjournal.com/pub/lj/listings/issue103/6279.tgz].

For a description of UNIX systems that handle the user and group ID values and how they interact with the setuid class of system calls, see the excellent paper by Hao Chen, David Wagner and Drew Dean entitled “Setuid Demystified”, which was presented at the 2002 USENIX Security conference (www.cs.berkeley.edu/~daw/papers/setuid-usenix02.ps).

The LSM interface is four simple functions:

int register_security
    (struct security_operations *ops);
int unregister_security
    (struct security_operations *ops);
int mod_reg_security (const char *name,
                  struct security_operations *ops);
int mod_unreg_security  (const char *name,
                  struct security_operations *ops);

A security module registers a set of security_operations function callbacks with the kernel by calling the function register_security(). If that fails, it means that some other security module probably has been loaded already, so the mod_reg_security() function is called in an attempt to register with this security module. This can be seen in the following code:

/* register ourselves with the security framework */
if (register_security (&rootplug_security_ops)) {
   printk (KERN_INFO
       "Failure registering Root Plug module "
       "with the kernel\n");
   /* try registering with primary module */
   if (mod_reg_security (MY_NAME,
                         &rootplug_security_ops)) {
       printk (KERN_INFO "Failure registering "
               "Root Plug module with primary "
               "security module.\n");
       return -EINVAL;
   }
   secondary = 1;
}
When the module wants to unload itself, the reverse process must happen. If we used mod_reg_security() to register ourselves, the mod_unreg_security() function should be called, otherwise the unregister_security() function is the proper thing to call. The following code shows this logic:
/* remove ourselves from the security framework */
if (secondary) {
   if (mod_unreg_security (MY_NAME,
                           &rootplug_security_ops))
      printk (KERN_INFO
              "Failure unregistering Root Plug "
              " module with primary module.\n");
} else {
   if (unregister_security (
       &rootplug_security_ops)) {
      printk (KERN_INFO "Failure unregistering "
              "Root Plug module with the kernel\n");
   }
}
The rootplug_security_ops is a large structure of function pointers that are called when various events happen in the kernel. This includes such things as whenever an inode is accessed, a module is loaded or a task is created. As of the 2.5.31 kernel, there were 88 different function pointers needed. The majority of these functions not needed by most security models, but they must be implemented, or the kernel will not work properly. If a security module does not need to do anything for a specific hook, a “good” value needs to be returned to the kernel. An example of this can be seen in the following function:
static int rootplug_file_permission
    (struct file *file, int mask)
{
    return 0;
}
This function is called whenever the kernel wants to determine if a specific file can be accessed at this moment in time. A security module can look at the file, check whether the current user has proper authority and possibly refuse to grant it.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

modules should support multiple devices

Warren Crossing's picture

I know your magazine and buy/read it occasionally, generally it is a good read. This article provided good information in a clean uncomplicated style. I think LJ has the right to write/solicit articles and charge access for them in print. I think LJ should be committed to maintaining this document and allowing access now that kernel code refer to it.

I also think people shouldn't jump to conclusions and demand software information without any fiscal cost.

We are talking free as in freedom! Money doesn't grow on trees and there is no obligation for module developers to produce/provide their new cool code to the community.

Please be grateful, for SO many have given SO much before you!!

Huh

Anonymous's picture

WTF... i want to read this

very poor that we cannot view this

Anonymous's picture

i came here based on comments in the kernel which referred to this article. i was very disappointed to find that i have to be a financial member in order to read the article.

i will be making a recommendation for your site to be removed from any kernel comments.

Article Referenced in Kernel Docs...

cjsutton's picture

...yet you decide to deny access to it unless I pay you money.

"This still leaves more articles available for public viewing than are reserved for subscribers -- as of last count over 2000!"

Interesting that this isn't one of those.

Does Linus know about this?

Anonymous's picture

This is BS, open up the article.

I wonder how Linus would feel about this non-free scheme, of pay for docs, that are referenced in his kernel.

came here because of referenc

Anonymous's picture

came here because of reference in the kernel docs
looked interesting

Rest assured that, because of

Anonymous's picture

Rest assured that, because of this, I will NEVER subscribe to your magazine. This is complete and utter bull$hit!! Docs shouldn't be proprietary!

Settle down. It's not LJ's f

Anonymous's picture

Settle down. It's not LJ's fault that some kernel dev couldn't be bothered to write real documentation for the rootplug module...

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState