Using the Kernel Security Module Interface
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.
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.ssc.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.











This week 5 lucky Members will receive a copy of The Official Ubuntu Server Book by Benjamin Mako Hill and Linux Journal's very own Kyle Rankin. No entry necessary. Check back here early next week to find out who the lucky Online Members are.




Comments
modules should support multiple devices
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
WTF... i want to read this
very poor that we cannot view this
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...
...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?
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
came here because of reference in the kernel docs
looked interesting
Rest assured that, because of
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
Settle down. It's not LJ's fault that some kernel dev couldn't be bothered to write real documentation for the rootplug module...
Post new comment