rsbacl5s.gif (2243 Byte)  

Rule Set Based Access Control (RSBAC) for Linux - Module Registration


Module Registration (REG)

Basics

REG is not a decision module. It is an interface to register your own decision module, which can, but need not, be implemented as a Linux kernel module. It allows registration for all relevant calls to decision code as well as for maintenance calls to the data structure implementation. From 1.1.1-pre4 onwards, it also allows for registration of system call functions to the REG syscall dispatcher.

You can find example kernel modules in rsbac/adf/reg/adf_sample*.c. If you chose 'Compile REG samples' in kernel configuration, the examples will be compiled and installed like all other modules.

If you prefer separate compilation of modules, there is a copy of these examples with a working Makefile and (from 1.1.1-pre4 onwards) a demonstration syscall tool in Documentation/rsbac/reg_samples.

Please note that this text is targeted for RSBAC version 1.1.1-pre4 onwards, because of the added functionality and (hopefully) easier use.

Module Registration

All decision module registration handling is done with handles of type rsbac_reg_handle_t, which is just a signed 32 Bit integer. As often, positive values are used as real values and negative ones for errors.

REG data type and function definitions can be found in include/rsbac/reg.h, other type definitions are in include/rsbac/types.h. These header files should always be included by your model implementation.

A full list of RSBAC requests with possible targets is in targetsrequests.htm.

Callback Functions

You can register the following functions:

int rsbac_reg_request_func_t
  ( enum  rsbac_adf_request_t request,
          rsbac_pid_t caller_pid,
    enum  rsbac_target_t target,
    union rsbac_target_id_t tid,
    enum  rsbac_attribute_t attr,
    union rsbac_attribute_value_t attr_val,
    rsbac_uid_t owner); /* process owner */
int rsbac_reg_set_attr_func_t
  ( enum  rsbac_adf_request_t request,
          rsbac_pid_t caller_pid,
    enum  rsbac_target_t target,
    union rsbac_target_id_t tid,
    enum  rsbac_target_t new_target,
    union rsbac_target_id_t new_tid,
    enum  rsbac_attribute_t attr,
    union rsbac_attribute_value_t attr_val,
    rsbac_uid_t owner); /* process owner */                 
boolean rsbac_reg_need_overwrite_func
  (struct dentry * dentry_p);
int rsbac_reg_write_func_t(boolean need_lock);
int rsbac_reg_check_func_t(int correct, int check_inode);
int rsbac_reg_mount_func_t(kdev_t kdev);
int rsbac_reg_umount_func_t(kdev_t kdev);

Registration Functions

For module registration, you first have to choose a positive, signed 32 Bit integer as your personal, secret handle. All registration related actions will later require this unique handle. If your handle happens to be already in use, registration will fail with an error value of -RSBAC_EEXIST.

The struct rsbac_reg_entry holds all necessary values. Functions can be left out by setting their pointer to NULL. Your module will later be identified in REG messages and proc files by its name. The current maximum name length is 30 characters.

The switch value determines, whether your module will be switched on or off at the very beginning. For security reasons, switching only works, if enabled in the kernel config.

struct rsbac_reg_entry_t
  {
    rsbac_reg_handle_t                handle;
    char                              name[RSBAC_REG_NAME_LEN+1];
    rsbac_reg_request_func_t        * request_func;
    rsbac_reg_set_attr_func_t       * set_attr_func;
    rsbac_reg_need_overwrite_func_t * need_overwrite_func;
    rsbac_reg_write_func_t          * write_func;
    rsbac_reg_mount_func_t          * mount_func;
    rsbac_reg_umount_func_t         * umount_func;
    boolean                           switch_on; /* turned on initially? */
  };

Given this struct, registration is quite easy. Usually registration happens in the init_module() function of kernel modules, deregistration in cleanup_module(). Unloading a REG registered module without deregistration will kill your system!

The only thing added to the entry struct is a REG version value, which allows a version check for modules shipped as binaries. It should always be set to RSBAC_REG_VERSION. The registration function will return your positive handle or a negative error code (see include/rsbac/reg.h for more details).

rsbac_reg_handle_t rsbac_reg_register
  (       rsbac_version_t    version,
   struct rsbac_reg_entry_t  entry);

Once successfully registered, you can switch the module on or off, if enabled in kernel config. As usual, this function will return 0 on success and a negative error code otherwise.

int rsbac_reg_switch
  (rsbac_reg_handle_t handle, boolean value);

Unregistering is now simple.

int rsbac_reg_unregister
  (rsbac_reg_handle_t handle);

OK, now your module should be working. If it also registered syscalls or proc entries, you should now have a look at its status.

Let me hint at the sample modules again - in the beginning using them as a base will be a good choice as well as save you a lot of typing.

Syscall Registration

Registration of system calls is similar to that of the decision module itself. As with decision functions, there is no official limit on the number of syscalls you can register. Only the handles have to be different each time.

For security reasons, different handle values should be used for registration and syscall dispatching - syscall dispatcher handles must be public to be of any use.

Once you system call has been registered, it can be invoked by calling the official system call

int sys_rsbac_reg
  (rsbac_reg_handle_t handle,
   void * arg);

The handle is the dispatcher handle you registered your syscall function with, the arg pointer will be passed directly to your function. Its return value will be the system call return value.

Callback Functions

Your syscall function should look as follows:

int rsbac_reg_syscall_func_t(void * data);

The pointer this function will get is a user space pointer. To work with your data, you will have to get it from user space first using

#include <rsbac/helpers.h>
int rsbac_get_user
  (unsigned char * kern_p, unsigned char * user_p, int size);

Your function's return code is passed back to the calling process in case of a positive value. If the return code is negative (indicating an error), the value returned to the calling process is -1 and errno is set to -value (i.e. the sign of value is inverted).

Registration Functions

For syscall registration, you now have to choose a positive, signed 32 Bit integer as your personal, secret registration handle and another positive, signed 32 Bit value as your public syscall dispatcher handle. All registration related actions will later require the unique secret handle. If one of your handles happens to be already in use, registration will fail with an error value of -RSBAC_EEXIST.

The struct rsbac_reg_syscall_entry holds all necessary values. Nothing but the name can be left out. Your system call will later be identified in REG messages and proc files by its name and its public dispatcher handle. The current maximum name length is 30 characters.

struct rsbac_reg_syscall_entry_t
  {
    rsbac_reg_handle_t                registration_handle;
    rsbac_reg_handle_t                dispatcher_handle;
    char                              name[RSBAC_REG_NAME_LEN+1];
    rsbac_reg_syscall_func_t        * syscall_func;
  };

Given this struct, registration is similar to decision module registration. Unloading a module with a registered syscall without deregistration will kill your system on the next call to the syscall function!

Again added to the entry struct is a REG version value, which allows a version check for modules shipped as binaries. It should always be set to RSBAC_REG_VERSION. The registration function will return your positive handle or a negative error code (see include/rsbac/reg.h for more details).

rsbac_reg_handle_t rsbac_reg_register_syscall
  (       rsbac_version_t            version,
   struct rsbac_reg_syscall_entry_t  entry); 

Once successfully registered, you can use your new system call.Unregistering is now simple.

int rsbac_reg_unregister_syscall
  (rsbac_reg_handle_t registration_handle);

Another hint at the sample modules: in the beginning using them as a base will be a good choice as well as save you a lot of typing.

RSBAC Helper Functions

The RSBAC framework provides a lot of helper functions and variables, which should be used by your module, if appropiate. Here is a list of the most important ones.

Generic Lists

From version 1.1.2, RSBAC provides persistent generic lists and lists of lists with custom index and data sizes and automatic backup proc file generation. It is strongly recommended to use them for all data storage.

Value to Name Conversion

All these functions require preallocated space for the name string. For convenience, the same char pointer is returned. A declaration of

char name[RSBAC_MAXNAMELEN];

is sufficient for all functions except for target_id_name, if logging of full path has been enabled in kernel config. In this case, one page (Linux macro PAGE_SIZE) should do.

These and several name-to-value functions can also be used in user space tools, just copy getname.c, compile it to getname.o and link that to your program. Look into RSBAC admin tools to see how to use this.

#include <rsbac/getname.h>

Logging

#include <rsbac/debug.h>

Access to User Space

#include <rsbac/helpers.h>

General Attributes

Please do not change any values or remove items, unless you know exactly what you are doing - other models depend on them.

#include <rsbac/aci.h>

Access to /rsbac Dir and Files

Please note that file access must not be done with normal syscall functions - those are intercepted and possibly blocked. Hold rsbac_write_sem from before opening until file is closed.

Warning: reading and writing to and from kernel space requires the segment descriptor to be changed - see reg_sample2.c as an example how to do all this.

#include <rsbac/aci_data_structures.h>

Proc file/dir registration

Please use the standard Linux kernel functions create_proc_entry() and remove_proc_entry() to register to these directories.

#include <rsbac/procfs.h>

To top of page
Back to RSBAC Homepage -

Questions, tips, etc.

03-Dec-01, -ao