In version 1.1.2, a generic list management has been added. It provides an infrastructure to simply define and register a list or a list of sublists, which can optionally be kept persistent or have a /proc/rsbac-info/backup entry. All management, like SMP locking, on-disk storage etc., is done internally without bothering the registering module.
Version 1.2.0 extended and added several list functions, this document will be updated soon to reflect these changes.
Keeping and using generic list managment has some advantages:
Examples of list usage can be found in REG sample 3 and in rsbac/data_structures/pm_data_structures.c, which has already been ported to generic lists and lost two thirds of its source code on the way.
All list registration handling is done with abstract handles of type rsbac_list_handle_t, which is just a void pointer. As usual, the NULL value is used for 'undefined' or 'not yet registered'.
List data type and function definitions can be found in include/rsbac/lists.h, other type definitions are in include/rsbac/types.h. These header files should always be included for registration.
The following help functions can be provided by the registrant:
int rsbac_list_compare_function_t (void * desc1, void * desc2);
int rsbac_list_conv_function_t( void * old_desc, void * old_data, void * new_desc, void * new_data);
rsbac_list_conv_function_t * rsbac_list_get_conv_t(rsbac_version_t old_version);
The rsbac_list_info and rsbac_lists_lol_info structs contain all data that will be stored persistently, i.e. written to disk. They have the following items:
struct rsbac_list_info_t { rsbac_version_t version; rsbac_list_key_t key; __u32 desc_size; __u32 data_size; rsbac_time_t max_age; }; struct rsbac_list_lol_info_t { rsbac_version_t version; rsbac_list_key_t key; __u32 desc_size; __u32 data_size; __u32 subdesc_size; __u32 subdata_size; rsbac_time_t max_age; };
For list registration, you first have to choose a positive, signed 32 Bit integer as your personal, secret registration key. All registration related actions will later require this key. If your list name happens to be already in use, registration will fail with an error value of -RSBAC_EEXIST.
The list_info structs (s.a.) hold all necessary values. Functions can be left out by setting their pointer to NULL. Your module will later be identified in list messages and proc files by its name, access will require the handle returned by registration. The current maximum name length is 30 characters.
Registration is quite easy. It usually happens in the init_module() function of kernel modules, deregistration in cleanup_module(). Unloading a kernel module without deregistration will keep all registered lists in memory and prevent their next registration until you reboot!
Registration flags are:
There are several registration parameters additional to the list_info struct:
int rsbac_list_register( rsbac_version_t ds_version, rsbac_list_handle_t *handle_p, struct rsbac_list_info_t info, u_int flags, rsbac_list_compare_function_t * compare, rsbac_list_get_conv_t * get_conv, char * name, kdev_t device); int rsbac_list_lol_register( rsbac_version_t ds_version, rsbac_list_handle_t *handle_p, struct rsbac_list_lol_info_t info, u_int flags, rsbac_list_compare_function_t * compare, rsbac_list_compare_function_t * subcompare, rsbac_list_get_conv_t * get_conv, rsbac_list_get_conv_t * get_subconv, char * name, kdev_t device);
Once successfully registered, you can use the (possibly restored) lists with the access functions, which are described below.
If the list is no longer needed, you can either destroy it, then the on-disk version is deleted, or detach from it, then the list is stored to disk and removed from memory only. For security, you need both your handle and the key from the list_info struct.
int rsbac_list_destroy( rsbac_list_handle_t * handle_p, rsbac_list_key_t key); int rsbac_list_lol_destroy( rsbac_list_handle_t * handle_p, rsbac_list_key_t key);
Finally, you can set or unset your list's no_write flag to temporarily enable or disable on-disk storage. This can e.g. be used for a simple transaction scheme. The no_write value is either TRUE (do not write) or FALSE (do write).
int rsbac_list_no_write( rsbac_list_handle_t handle, rsbac_list_key_t key, boolean no_write); int rsbac_list_lol_no_write( rsbac_list_handle_t handle, rsbac_list_key_t key, boolean no_write);
OK, your list is working. You should now have a look at its status, which is shown in /proc/rsbac-info/gen_lists.
Let me hint at the REG sample module 3 again - in the beginning using it as a base will be a good choice as well as save you a lot of typing.
Items can be added, modified, removed, looked up, retrieved and counted. For most functions, there is also a wrapper for unsigned 32 bit integer descriptors, so that you can pass values instead of pointers.
If item for desc exists, the data is updated. data can be NULL, if list is registered with data_size 0 (used as set).
int rsbac_list_add( rsbac_list_handle_t handle, void * desc, void * data);
int rsbac_list_add_u32 (rsbac_list_handle_t handle, __u32 desc, void * data);
Add list of lists sublist item, item for desc must exist.
int rsbac_list_lol_subadd( rsbac_list_handle_t handle, void * desc, void * subdesc, void * subdata); int rsbac_list_lol_subadd_u32( rsbac_list_handle_t handle, __u32 desc, __u32 subdesc, void * subdata);
Add list of lists top level item.
int rsbac_list_lol_add( rsbac_list_handle_t handle, void * desc, void * data); int rsbac_list_lol_add_u32 (rsbac_list_handle_t handle, __u32 desc, void * data);
int rsbac_list_remove (rsbac_list_handle_t handle, void * desc); int rsbac_list_remove_u32 (rsbac_list_handle_t handle, __u32 desc);
Remove all items.
int rsbac_list_remove_all(rsbac_list_handle_t handle);
Remove item from sublist - also succeeds, if item for desc or subdesc does not exist.
int rsbac_list_lol_subremove( rsbac_list_handle_t handle, void * desc, void * subdesc); int rsbac_list_lol_subremove_u32 (rsbac_list_handle_t handle, __u32 desc, __u32 subdesc); int rsbac_list_lol_subremove_all (rsbac_list_handle_t handle, void * desc); int rsbac_list_lol_subremove_all_u32 (rsbac_list_handle_t handle, __u32 desc); int rsbac_list_lol_remove( rsbac_list_handle_t handle, void * desc); int rsbac_list_lol_remove_u32 (rsbac_list_handle_t handle, __u32 desc);
int rsbac_list_lol_remove_all(rsbac_list_handle_t handle);
Item data is always copied - we cannot give a pointer, because item could be removed.
int rsbac_list_get_data( rsbac_list_handle_t handle, void * desc, void * data); int rsbac_list_get_data_u32( rsbac_list_handle_t handle, __u32 desc, void * data);
Get data from a subitem.
int rsbac_list_lol_get_subdata( rsbac_list_handle_t handle, void * desc, void * subdesc, void * subdata); int rsbac_list_lol_get_subdata_u32( rsbac_list_handle_t handle, __u32 desc, __u32 subdesc, void * data); int rsbac_list_lol_get_data( rsbac_list_handle_t handle, void * desc, void * data); int rsbac_list_lol_get_data_u32( rsbac_list_handle_t handle, __u32 desc, void * data);
Items can be simply checked for existence. All functions return TRUE, if item exists, and FALSE, if not.
int rsbac_list_exist( rsbac_list_handle_t handle, void * desc); int rsbac_list_exist_u32( rsbac_list_handle_t handle, __u32 desc); int rsbac_list_lol_subexist( rsbac_list_handle_t handle, void * desc, void * subdesc); int rsbac_list_lol_subexist_u32( rsbac_list_handle_t handle, __u32 desc, __u32 subdesc) int rsbac_list_lol_exist( rsbac_list_handle_t handle, void * desc); int rsbac_list_lol_exist_u32( rsbac_list_handle_t handle, __u32 desc);
All functions return the number of elements or a negative error code.
long rsbac_list_count(rsbac_list_handle_t handle); long rsbac_list_lol_subcount( rsbac_list_handle_t handle, void * desc); long rsbac_list_lol_all_subcount (rsbac_list_handle_t handle); long rsbac_list_lol_count(rsbac_list_handle_t handle);
All functions return the number of elements or a negative error code.
Get array of all descriptors. If the return value is positive, *array_p contains a pointer to a vmalloc'd array of descs, otherwise *array_p is set to NULL. If *array_p has been set, caller must call vfree(*array_p) after use!
long rsbac_list_get_all_desc( rsbac_list_handle_t handle, void ** array_p); long rsbac_list_lol_get_all_subdesc( rsbac_list_handle_t handle, void * desc, void ** array_p); long rsbac_list_lol_get_all_desc( rsbac_list_handle_t handle, void ** array_p);
Get array of all datas. If the return value is positive, *array_p contains a pointer to a vmalloc'd array of datas, otherwise *array_p is set to NULL. If *array_p has been set, caller must call vfree(*array_p) after use!
long rsbac_list_get_all_data( rsbac_list_handle_t handle, void ** array_p); long rsbac_list_lol_get_all_subdata( rsbac_list_handle_t handle, void * desc, void ** array_p); long rsbac_list_lol_get_all_data( rsbac_list_handle_t handle, void ** array_p);
Get item size.
int rsbac_list_get_item_size (rsbac_list_handle_t handle); int rsbac_list_lol_get_subitem_size (rsbac_list_handle_t handle); int rsbac_list_lol_get_item_size (rsbac_list_handle_t handle);
Get array of all items. If the return value is positive, *array_p contains a pointer to a vmalloc'd array of items, where desc and data are placed directly behind each other. If *array_p has been set, caller must call vfree(*array_p) after use!
long rsbac_list_get_all_items( rsbac_list_handle_t handle, void ** array_p); long rsbac_list_lol_get_all_subitems( rsbac_list_handle_t handle, void * desc, void ** array_p); long rsbac_list_lol_get_all_items( rsbac_list_handle_t handle, void ** array_p);
The RSBAC framework provides a lot of helper functions and variables, which should be used by your module, if appropiate. You can find a list of the most important ones in the REG description.
To top of page
05-Aug-02, -ao