diff --git a/Documentation/rsbac/COPYING b/Documentation/rsbac/COPYING
new file mode 100644
index 0000000..7e08278
--- /dev/null
+++ b/Documentation/rsbac/COPYING
@@ -0,0 +1,19 @@
+Copyright Notice
+----------------
+
+All RSBAC code is copyrighted by me (Amon Ott) unless specified otherwise,
+and published under the restrictions of the GNU General Public Licence
+as to be read in file COPYING in the main directory of the kernel source tree.
+All statements therein apply fully to all RSBAC sources.
+
+RSBAC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This software is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Amon Ott <ao@rsbac.org>
diff --git a/Documentation/rsbac/Changes b/Documentation/rsbac/Changes
new file mode 100644
index 0000000..f6aba53
--- /dev/null
+++ b/Documentation/rsbac/Changes
@@ -0,0 +1,702 @@
+RSBAC Changes
+-------------
+1.4.9:
+ - Port to 3.12 and 3.14.
+ - debug_adf_rc|jail: only log, if rsbac_log_levels[request][target] != LL_none
+ - new JAIL flag JAIL_allow_netdev_mod_system, MODIFY_SYSTEM_DATA on NETDEV
+ - Do not check SEND_SIGNAL to a process that is already exiting.
+ - JAIL: DO_NOT_CARE about SIGCHLD signal to process outside jail
+ - Add kernel parameter rsbac_list_noread to avoid reading lists from disk.
+ - Make sys_rsbac_rc_set_item() work in softmode, if current role is undefined
+
+1.4.8:
+	- Remove PM module
+	- Add UDF module
+	- Various small fixes
+
+1.4.7:
+	- Port to kernel 3.10.1
+	- Add optional MOVETO request with kernel config option:
+	  used when moving into a dir instead of old WRITE on DIR target.
+
+1.4.6:
+	- Port everything to kernel 3.1.5
+	- Show process name and parent when logging PROCESS target accesses
+	- Add RSBAC syscalls to get and set UM password history size per
+	  user.
+	- Do not allow to set attributes for FD targets with
+	  sys_rsbac_set_attr()
+
+1.4.5:
+	- Fix symlink's stat() call to return the real symlink size
+	  Fixes program that would assert on stat->s_size being the same size as when using readlink()
+	- Remove use of task_capability_lock.
+	- Fixes FS object hidding for most cases (still experimental)
+	- Backport fixes and internal features from 1.5:
+		- Add generic list option to use a separate kmem cache / slab per list.
+		- Use that option for several lists, general ACI, RC, ACL, UM.
+		- rkmem.h: define RSBAC_MAX_KMALLOC KMALLOC_MAX_SIZE
+		- Do not create our kmem caches with SLAB_DESTROY_BY_RCU, not needed.
+		- Big cleanup of DAZ code.
+		- Make DAZ path subselection by scanners optional, default is on in 1.4.
+		- Change DAZ module filename allocation to fixed size slabs.
+		- Remove rsbac_get_full_path_length(), which is not used anywhere any more.
+		- Use fixed DAZ filename size PATH_MAX, defined in include/linux/limits.h.
+		- DAZ: allocate memory with _unlocked functions where possible.
+		- Put device items into own slabs.
+		- Fix memory leak in case of failed list rehashing.
+	- Fix notification for setuid() etc: move after commit_creds().
+	- In Unix send and receive, use remote peercred.pid, if local is not available.
+	- Fix NULL pointer deref, if sk_socket is unset.
+	- Move SEND and RECEIVE for Unix sockets from net/socket.c to net/unix/af_inet.c.
+	- This makes interception code cleaner and more reliable, specially for named
+	  sockets.
+	- Fix file_p handling in list read functions.
+	- Use mntget() instead of path_get() in rsbac_read_open().
+
+1.4.4:
+	- Port to 2.6.33.2
+	- Fix RC check for CREATE right on new objects.
+	- Backport rsbac_read_open() and rsbac_read_close() fixes from 1.5.
+
+1.4.3:
+	- Depend CONFIG_RSBAC_RC_LEARN on CONFIG_RSBAC_DEBUG.
+	- Show transaction number in learning info messages.
+	- Add transaction names for human use and set names for learn transactions.
+	- Move CREATE checks in rc_main.c into common function rc_check_create() with lea
+	- Fix proc function return types in reg samples.
+	- Remove rsbac_read_lock(), rsbac_write_lock() etc.
+	- Remove rsbac_vmalloc, rsbac_vkmalloc, rsbac_vfree, rsbac_vkfree.
+	- New kernel config RSBAC_SWITCH_BOOT_OFF: 'Allow to switch modules off with kernel parameter'
+	- Join ta_committing and ta_forgetting to ta_committing.
+	- Fix three small memory leaks.
+	- Show program path in CAP learning messages and use INFO level, not DEBUG.
+	- Allow SCD mlock in PM.
+	- Show program path in AUTH learning messages.
+	- When committing or forgetting, lock per list and make other list functions sleep while committing or forgetting.
+	- Optionally put learning mode results into transactions, one per module.
+	- Add global RC learning mode for role rights to types.
+	- Control CAP learning mode switch in CAP module.
+	- Implement CAP learning mode for user and program max_caps.
+	- Move AUTH auth_program_file kernel-only attribute to GEN program_file.
+	- Fix lockup in rehashing, after failing of new hashed struct memory allocation, forgot to spin_unlock. Alloc unlocked instead, better anyway.
+	- Add notes for locking to generic lists.
+	- Store compare results in variable to avoid doing same compare twice.
+	- Only reset curr pointer, if same as removed item (usually the case).
+	- Show rcu_batches_completed() in proc gen_list_counts.
+	- Store nr_hashes in variable, if used after unlocking - might change.
+	- Fix *remove_count(): calling rcu_free on wrong updated pointer, so store.
+	- Do not use count values for checks, can be wrong. Always use head.
+	- Allow rcu rate >= 1 for testing purposes, config help still says 100.
+	- Reorder syscall case struct by frequency of calls (stats from real systems).
+	- Ifdef syscalls for disabled modules instead of returning error in them.
+	- Make RCU rate limit boot and runtime configurable.
+
+1.4.2:
+	- Change generic lists to use RCU instead of rw spinlocks
+	- Show a total of reads and writes in list statistics in gen_lists_count
+	- Disable rsbac attributes store on fuse
+	- Fix RC dev inheritance: Explicitely set minor to 0 before getting major attr
+	- Use Pseudo also for RC ADF debug messages
+	- Use RCU callbacks with a rate limit of 1000/s, use sync, if exceeded, configurable in kernel config
+
+1.4.1:
+	- Support ANY value 255 for NETLINK protocol
+	- Return -EPERM in sys_rsbac_um_check_account, if user does not exist.
+	- Add config option RSBAC_ENFORCE_CLOSE to really deny close, if decided.
+	- Check CLOSE requests in RC.
+	- Add SCD target videomem and kernel attribute pagenr.
+	- Split SCD kmem into kmem and videomem, split hooks in drivers/char/mem.c.
+	- Allow R_MODIFY_SYSTEM_DATA notifications on SCD in adf_check.c.
+	- ext4 secure delete support
+1.4.0:
+	- Added VUM (Virtual User Management) support	
+	- OTP support for UM
+	- Converted the common code to 2.6 only. From now on changes will be 2.6 only as well.
+1.3.5:
+	- Check crypto return codes (2.6) and fixed UM password hashing.
+	- Fix compilation issues for "disable writing to disk". See bug #98.
+	- Safety mesures for inheritence in case of null pointers.
+	- Disable debug message "rsbac_get_parent(): oops - d_parent == dentry_p".
+	- Increase string lengths in user and group items significantly.
+	- Add RSBAC memory slab 384 for new user item sizes.
+	- Do not try to write lists, if device is not writable.
+	- Do not sleep in rsbac_get_vfsmount(), can be called while atomic.
+	- Do not write attributes on Oracle Cluster FS 2 (OCFS2).
+	- Complete hook review.
+1.3.4:
+	- No changes :)
+1.3.3:
+	- Change FD cache counters to 64 Bit to avoid wrapping.
+	- Make FD Cache xstats output look nicer.
+	- Make an adf_request permission check when modyfing capabilities is the new set >> old one.
+	- Copy auth_last_auth on CLONE, gets reset on EXECUTE.
+	- Provide pid and process name in some UM debug output.
+	- 2.6 WARNING: sysrq key 'w' is GONE! no more wake up trigger possible
+1.3.2:
+	- mark FS_OBJ_HIDE as EXPERIMENTAL and depends on it
+	- clean compilation warnings, data types and such.
+	- removed double "ready" message in rsbac_do_init()
+	- disable partner process check for unix socks by default.
+	- Show fd cache hits/misses ratio in xstats. Really inline rsbac_is_initialized().
+	- Change fd cache descriptor to get rid of separate compare function in 2.4 kernels.
+	- Add FD inherited attribute value cache. Hash device list. Allow per-list max_ite
+ms_per_hash.
+	- Change return code in AUTH syscalls to INVALIDATTR, if group or eff/fs support i
+s not compiled in.
+	- port from ex 1.4 trunk: do not intercept PTRACE_DETACH request
+	- rewrite of error handling to be more logical in rsbac_handle_filldir().
+	- Also take partner pid from other on Unix socket stream connects.
+	- Accept syscalls from tools with all versions 1.3.x.
+	- Take partner process on UNIXSOCK CONNECT from other->sk_peercred.
+	- Try to get partner process for UNIXSOCK RECEIVE from other sources, if peercred is not filled.
+	- New error code INVALIDLIST, if list handle is invalid.
+	- New jail flags for syslog jail. 
+	- Extra check before reiserfs secure_delete call.
+	- Fix Dazuko device registration in 2.6. Return INVALIDPOINTER for invalid pointer
+s in some syscalls.
+	- lvm/md automount fix
+	- Fix oops on loop umounts: device was auto-mounted, if there were dirty lists. Ne
+ver auto-mount loop devices.
+	- 
+1.3.1:
+	- Add xstats counter for get_parent calls.
+	- Fix sort order of network templates.
+	- Add missing DAZ request in vector. Add role number in RC syscall denied log message.
+	- Create bitmasks for each module of which requests it is interested in and only call request_xy and set_attr_xy, if necessary.
+	- small performance tunning: removed usage of rsbac_list_compare_u32 (always use memcmp which is asm-tuned per arch)
+	- Reduce stack usage in list, ACL and RC init.
+	- Optimize list hash functions with bit masks instead of % operation.
+	- make sure that rsbac_list_max_hashes and rsbac_list_lol_max_hashes are always potential of 2 and warn the user at configuration time. (127 will round to 64).
+
+1.3.0:
+	- Restarted 1.3 tree from the 1.2.7 release
+	- System call rsbac_version to return numeric version without checking the caller’s version provided to syscall.
+	- JAIL: allow_parent_ipc to allow IPC into parent jail. Useful with Apache mod_jail and others. Needs another process attribute jail_parent
+	- JAIL: add a flag to allow suid/sgid files and dirs.
+	- Optionally check CHANGE_OWNER for PROCESS targets also as CHANGE_OWNER on the new USER. This allows fine grained control also in RC and ACL models.
+	- Change network templates to hold up to 25 ip networks and up to 10 port ranges.
+	- Automatic online resizing of per-list hash table. As list identifiers are pointers to list headers, which must not change, the arrays of list heads are allocated separately and accessed through a pointer.
+	- Change named UNIX sockets to be new filesystem target type T_UNIXSOCK and unnamed to be new IPC type anonunix (like pipes)
+	- RC role def_unixsock_create_type, which overrides the def_(ind_)fd_create_type. Default value use_def_fd.
+	- Change aci, acl and auth devices lists to use RCU on 2.6 kernels
+	- Dazuko udev support
+	- UM password history with configurable length to avoid password reuse.
+	- Update HTML doc in Documentation/rsbac, or point all docs to the website.
+	- Hide dir entries a process has no SEARCH right for
+	- Limit number of items per single list to 50000, so real limit is at 50000 * nr_hashes.
+	- New request type AUTHENTICATE against USER targets. No authentication against RSBAC UM without this right in RC and ACL.
+	- Complete hook review with several small fixes.
+	- More detailed JAIL decision logging for IPC and UNIXSOCK targets with rsbac_debug_adf_jail.
+
+1.2.7:
+	- Use new PaX flags location at current->mm->pax_flags.
+	- Removed remaining non-RSBAC code
+1.2.6:
+	- DAZ Renaming of files from non-scanned to scanned directory
+	  now works correctly (does not cache results from non scanned
+	  as CLEAN - and/but keep INFECTED status if set when moving file
+	  from scanned to non-scanned)
+	- DAZ unscanned files decision is now DO_NOT_CARE instead of
+	  GRANTED
+	- Full pathes returned by RSBAC do not display double
+	  (or more) / with double (or more) mounts anymore.
+	  ex: /home//bob => /home/bob
+	  This allows DAZ path based scanning to function normally.
+	- Fix setting of RC IPC type with def_ipc_create_type.
+	- Added ptrace hook for m32r architecture.
+	- New kthread notification code.
+	- Fix xstats to include GROUP targets.
+	- Mark lists dirty again, if saving failed.
+	- Fix FF to allow file READ (but not READ_OPEN) even with execute_only.
+	- Stop making SEND and RECEIVE requests for STREAM sockets, if
+	  CONFIG_RSBAC_NET_OBJ_RW is not set.
+	- Notify that shm is destroyed only when it really is (thanks rtp).
+	- Minor compile fixes
+
+1.2.5: - AUTH config switch to globally allow setuid to user (real, eff, fs),
+         who started the program. Boot time option and proc setting to enable
+         per uid type.
+       - Show missing Linux caps in JAIL like in CAP.
+       - Change device attribute backup to use a list of attribute objects
+         instead of traversing /dev and possibly missing some.
+       - Device attribute inheritance: Use values at type:major as default for
+         type:major:minor.
+       - Add a generic request directly in sys_ioctl with new request type
+         IOCTL on DEV and NETOBJ target.
+       - Finish ioctl extra interception with GET_STATUS_DATA and
+         MODIFY_SYSTEM_DATA, e.g. for SCSI.
+       - Store remote IP when process accepted its first INET connection as
+         process attribute and pass on to children. Log remote IP in request
+         log.
+       - Symlink redirection based on remote IP.
+       - Optional UM password limits: Min length, non-alpha char required
+       - Fix EINVALIDPOINTER when changing UM password with passwd via
+         pam_rsbac.
+       - Complete system call interception review with additional hooks where
+         necessary. See Interceptions log for details.
+       - Change USER attribute backup to list of known items.
+       - Fix dereference bug related to rsbac_get_parent: set_attr call in
+         do_exec sometimes used file struct after freeing.
+       - Fix 2.6.11 random file not found errors, caused by symlink redirection
+         and ext2/ext3 kernel fs layer violation.
+       - Add CREATE and DELETE notifications in um syscalls.
+       - Make RC apply default_{user|group}_create_type on {USER|GROUP} CREATE.
+       - Configure module switching per module. Only allow switching stateful
+         models on after switching off with extra kernel config switch.
+       - Review all devision modules, whether they decide on all relevant
+         request to target combinations and whether they protect all relevant
+         attributes.
+       - Full review of all interceptions to make them locks safe
+       - Fix initrd problems showing up with the Adamantix kernel
+
+1.2.4: - Per dir FD type RC default_fd_create_type
+       - Full kernel space user management as a replacement for /etc/passwd,
+         /etc/shadow, /etc/group
+       - Add GROUP target type
+       - Change RC copy_role to be allowed with role in admin_roles
+       - Log full program path, get dentry from mappings for this
+       - Make RSBAC remote logging target configurable at boot or runtime.
+         Suppress remote logging, if address or port is 0.
+       - audit_uid: Default value "unset". Set at CHANGE_OWNER away from a uid
+         != 0, kept, inherited to child processes and logged. Allows to log
+         actions of users who did an su etc. Configurable additional uid per
+         program which works like uid 0, e.g. for SSHD privilege separation
+         (new attr auid_exempt).
+       - AUTH protection for Linux group IDs.
+       - New kernel flag: rsbac_softmode_once: Sets softmode, but denies
+         setting it again during runtime. For those systems that for some
+         reason must start in softmode, disable it and do not want to have it
+         set again later.
+       - New kernel flag: rsbac_softmode_never: Disallows setting softmode
+         during this runtime.
+       - Keep last UM authenticated users in a per-process attribute
+         auth_last_auth. Allow processes with auth_may_set_cap flag to set
+         last_auth.
+       - New kernel flag: rsbac_freeze: Disallows all modifying administration
+         in RSBAC syscalls. Added new switch target FREEZE.
+       - Make PaX default flags configurable.
+       - RC check access to UNIX socket partner process
+       - Transaction support for administration: begin, add a set of desired
+         changes, commit atomically or forget.
+       - Add RC copy_type, to be allowed with ADMIN right.
+       - User Management "exclusive mode": Only users and groups known to
+         RSBAC UM can be reached. Kernel parameter and /proc setting to
+         temporarily disable the restrictions.
+       - Randomize UM password salt better
+       - Optionally randomize transaction numbers
+       - Reduce memory consumption of rsbac_do_init.
+       - Further reduce RSBAC's stack usage to prepare for 4 KB kernel stack
+         size.
+       - Password protection for transaction operations refresh, forget, commit
+       - Add hooks with MODIFY_SYSTEM_DATA on SCD network to queueing
+         administration
+       - Warn explicitely, if CAP max_caps do not get applied because of
+         running in softmode.
+       - Update Dazuko interface to 2.0.5
+       - Update defconfig in all archs 
+       - ACLs for Users and Linux groups
+       - Extend AUTH auth_may_setuid flag with values last_auth_only and
+         last_auth_and_gid to allow last authenticated uid to be reached.
+         The second allows all group ids, too, because you cannot auth for
+         them. No longer add process cap at UM authentication, but rather
+         check at CHANGE_OWNER with last_auth process attribute.
+       - Fix severe Oopses when forgetting transactions with lists of lists.
+       - Optionally log all denied calls to capable() function with
+         CONFIG_RSBAC_CAP_LOG_MISSING 
+
+1.2.3: - Port to linux kernel 2.6.0-test with LSM
+       - New JAIL flag allow_clock for ntpd encapsulation
+       - Removed LSM support (see http://rsbac.org/documentation/why_rsbac_does_not_use_lsm).
+       - Global AUTH learning mode
+       - AUTH cap inheritance from parent dir (single step only, not
+         accumulated)
+       - RC pretty-print config output
+       - Remove 2.2 kernel support.
+       - Improve AUTH learning mode to use special value for same user
+       - Trigger AUTH learning mode per program
+       - Show type, name and mode of new object in T_DIR/CREATE request log. 
+       - Statix PaX support decision module
+       - Faked (root) user ID in ''getuid()'' to make stupid programs with uid
+         checks happy.
+       - Full log separation between syslog and RSBAC log, also for debug
+         messages (except rsbac_debug_aef). RSBAC now really shuts up, if
+         rsbac_nosyslog is set, and sends everything to RSBAC own log only.
+       - ACL learning mode for user rights to filesystem objects, parameter
+         rsbac_acl_learn
+       - New RC syscall to get current role
+       - mac_trusted_for_user with list instead of single user.
+       - Block fchdir outside the jail, if some stupid program opened a dir,
+         called rsbac_jail() and then called fchdir(). Done by simply closing
+         all open dirs after rsbac_jail() called chroot.
+       - Fixed some JAIL bugs found, all relevant chroot items from regression
+         suite solved. Not urgent enough and too many changes to make a 1.2.2
+         bugfix.
+       - Added JAIL Linux Capability restriction
+       - Dazuko integration as fixed module, as replacement for MS module
+       - Dazuko result caching with generic lists (as in old MS module)
+       - AUTH special value for eff and fs uid (thanks to Arnout Engelen)
+       - New optional rsbac_jail parameter max_caps, which limits the Linux
+         capabilities of all processes in the jail
+       - Optionally hide process ids without GET_STATUS_DATA in /proc/
+         dir listing
+       - /proc/rsbac-info/active to get current version and list of active
+         modules: One line each for version, mode: Secure/Softmode/Maintenance,
+         softmode: available/unavailable and one line per module: on/softmode/off
+       - Solve the new "kernel complains about vmalloc with lock" uglyness:
+         removed all vmalloc use in 2.6 kernels, too many workarounds needed.
+       - Protect sysfs objects in 2.6 kernels
+       - Added three real life example REG modules to rsbac/adf/reg,
+         contributed by Michal Purzynski
+       - Changed DEV list descriptor to be compatible between 2.4 and 2.6
+         kernels
+       - Added RC types and compatibility settings for USER targets
+       - Allow to set a different RC boot role than that of user root
+       - Add RC process type for kernel threads
+
+1.2.2: - Added ms_need_scan attribute for selective scanning
+       - MS module support for F-Protd as scanning engine
+       - ms_need_scan FD attribute for selective scanning
+       - JAIL flag allow_inet_localhost to additionally allow to/from
+         local/remote IP 127.0.0.1
+       - RSBAC syscall version numbers
+       - New RES module with minimum and maximum resource settings for
+         users and programs
+       - Moved AUTH module to generic lists with ttl
+       - Added new requests CHANGE_DAC_(EFF|FS)_OWNER on PROCESS targets
+         for seteuid and setfsuid (configurable)
+       - Added caps and checks for effective and fs owner to AUTH module
+         (optional)
+       - Changed behaviour on setuid etc.: Notification is always sent, even
+         if the uid was set to the same value. This allows for restricted RC
+         initial roles with correct role after setuid to root.
+       - New Process Hiding feature in CAP module
+       - Delayed init for initial ramdisks: delay RSBAC init until the first
+         real device mount.
+       - rsbac_init() syscall to trigger init by hand, if not yet
+         initialized - can be used with e.g. rsbac_delayed_root=99:99, which
+         will never trigger init automatically.
+       - MS module support for clamd as scanning engine.
+       - Almost complete reimplementation of the MAC model with many new
+         features.
+       - New system role 'auditor' for most models, which may read and flush
+         RSBAC own log.
+
+1.2.1: - Added support for all other architectures.
+       - Cleaned up rsbac syscall filesystem name lookup and target type
+         checks.
+       - New module JAIL: preconfigured process encapsulation (see kernel
+         config help).
+
+1.2.0: - Moved most lists to generic lists, splitting up between modules on
+         the way (GEN = general for all modules).
+       - DS for each module only included, if module is compiled in.
+       - New Linux Capabilities (CAP) module
+       - Split system_role into mac_role, fc_role, etc. Please do not use
+         old A_system_role attribute any longer.
+       - Changed rsbac_get/set_attr interface to include target module
+       - Added module guessing from attribute into sys_rsbac_get/set_attr,
+         if module is not given (value SW_NONE).
+       - Added user and RC role based symlink redirection
+       - Added network and firewall config protection as SCD network and
+         firewall targets
+       - Added NETDEV, NETTEMP and NETOBJ targets for network access control.
+       - Added network templates for default NETOBJ attribute values
+       - Renamed /rsbac dir to /rsbac.dat to avoid name conflicts.
+       - RC model with unlimited roles and types
+       - Selective dir tree disabling of Linux DAC
+       - Generic list ordering (needed for templates and optimization)
+       - List optimization
+       - Generic time-to-live support in generic lists (new on-disk version)
+       - Support time-to-live for ACL group members and ACL entries
+       - copy_net_temp
+       - Individual module soft mode
+       - Support time-to-live for RC entries
+       - Backport to 2.2.20
+
+1.1.2: - Own RSBAC memory allocation functions. Own RSBAC mem slabs in 2.4
+         kernels.
+       - Generic lists - simply register your list item sizes with filename
+         and persist flag, and a persistent list will be kept for you.
+       - Generic lists of lists, two level version.
+       - Moved pm_data_structures.c to new lists with proc backup files
+         Attention: There is no auto-update from older versions possible!
+       - proc backup files for RC and ACL are now optional
+       - New proc subdir pm, replaces old write_list call
+       - rsbac_pm write_list call removed
+       - New FD aci version with new rc_initial_role and 16 bit ff_flags
+       - New FF flag append_only, which limits all write accesses to
+         APPEND_OPEN and WRITE
+       - Fix for rename hole: rename could replace and thus delete an
+         existing file without DELETE check. Also performs secure_delete, if
+         necessary
+       - New rsbac_mount hook in change_root for initial ramdisk
+       - Fixed missing Linux check in bad_signal
+       - Added optional switch rsbac_dac_disable to disable Linux filesystem
+         access control
+       - Added count support for multiple mounts
+       - Added optional switch rsbac_nosyslog to temporarily disable logging
+         to syslog
+       - Added config option for DEBUG code
+
+1.1.1: - New target type FIFO, with a lot of cleanup, e.g. IPC type fifo
+         removed
+       - MAC module reworked, including MAC-Light option
+       - Several bugfixes
+       - Port to 2.4.0, 2.4.1 and 2.4.2
+       - New Makefiles with lists for 2.4 and without for 2.2 kernels
+         (Thanks to Edward Brocklesby for samples)
+       - init process default ACI now partly depends on root's ACI
+       - Optional interception of sys_read and sys_write.
+         Attention: you might have to add READ and WRITE rights to files,
+         fifos, dirs and sockets first, if upgrading from an older version
+       - REG overhaul. Now you can register syscall functions, everything is
+         kept in unlimited lists instead of arrays and registering is
+         versioned to allow for binary module shipping with REG version
+         checks.
+       - Inheritance is now fixed, except for MAC model
+       - MAC: optional inheritance, new option Smart Inheritance that tries
+         to avoid new attribute objects (see config help)
+       - New soft mode option: all decisions and logging are performed, but
+         DO_NOT_CARE is returned to enforcement. Off by default. See config
+         help for details.
+       - Optional initialization in extra rsbac_initd thread.
+
+1.1.0: - Port to 2.4.0-test11
+       - Interception of sys_mmap and sys_mprotect added. Now execution of
+         library code requires EXECUTE privilege on the library file, and
+         setting non-mmapped memory to EXEC mode requires EXECUTE on target
+         NONE.
+       - MAC Light option by Stanislav Ievlev added. See kernel config help or
+         modules.htm.
+
+1.0.9c:
+       - Port to 2.4.0-test{[789]|10}, this means major changes to the lookup and
+         inheritance code - of course #ifdef'd
+       - Change string declarations to kmalloc. On the way moved
+         MAX_PATH_LEN restriction from 1999 to max_kmalloc - 256
+         (>127K).
+       - Renamed several PM xy.class to xy.object_class for C++
+         compatibility
+       - Added SCD type ST_kmem
+       - Changed rc_force_role default to rc_role_inherit_parent,
+         terminated at root dir with old default rc_role_inherit_mixed.
+         This makes it much easier to keep a dir of force-roled binaries.
+1.0.9b:
+       - Port to 2.3.42 - 2.3.99-pre3
+       - Port to 2.2.14 - 2.2.16
+       - 32 Bit Uid/Gid with new attribute versions
+       - User and program based logging
+       - AUTH capability ranges
+       - Made write to MSDOS fs a config option, so use it on your own risk
+         (see config help)
+       - MAC levels 0-252
+       - Added config option for ioport access (X support)
+      
+1.0.9a:
+       - Added group management to ACL module.
+       - Removed CONFIG_RSBAC_SYNC option.
+       - Added module hints to logging
+       - Added RC separation of duty (see models.htm)
+       - Added RC force role inherit_up_mixed and made it default setting
+
+1.0.9: - Added registration of additional decision modules (REG)
+       - Wrote decision module examples (see README-reg and reg_samples dir)
+       - Port to 2.2.8, 2.2.9, 2.2.10, 2.2.11, 2.2.12 (pre versions)
+       - Heavily changed RC model: Now it has a distinguished role-to-type
+         compatibility setting for each request type, instead of one setting
+         for all request types. This allows for much finer grained access
+         control.
+         Unfortunately there was no way to update existing role settings,
+         so those have to be reentered by hand. Still, the types entries are
+         kept.
+       - Set all MSDOS based file systems to read-only, because inode
+         numbers are likely to change between boots.
+       - Added Access Control List module. ACLs are kept on FILE, DIR,
+         DEV, IPC, SCD and PROCESS targets (IPC and PROCESS have only
+         one default ACL each). Each entry contains subject type (user,
+         rc_role, group), subject id and the rights this subject has. Also,
+         rights are inherited from parents and from a target specific default
+         ACL.
+         See html/models.htm for details.
+       - Added optional full path logging.
+
+1.0.8a:
+       - Port to 2.2.7
+       - File Flag no_execute added to prevent execution, e.g. of user
+         binaries under /home tree. Can be circumvented by scripts via
+         'interpreter scriptname'.
+
+1.0.8: - Port to 2.2.1
+       - Added /proc/rsbac-info/backup to provide an easier means of backup
+         for not device dependent stuff. To be extended.
+       - Added new Role Compatibility (RC) module.
+       - New on-disk binary layout, auto update from all versioned data
+         (1.0.5 upwards).
+       - AUTH module added to support proper authentification by enforcing
+         externally granted CHANGE_OWNER capabilities.
+       - Save to disk inconsistency in PM sets fixed.
+       - MAC categories added, but limited to a fixed number of 64. Apart
+         from that, the MAC module categories are as proposed in the
+         Bell-LaPadula model.
+       - Port to 2.2.2
+       - Port to 2.2.3 with minor changes
+       - Port to 2.2.4
+       - Port to 2.2.5
+
+1.0.7a:
+       - Added alpha support (with Shaun Savage). Has different storage sizes,
+         so default useraci does not work and you need a maint kernel.
+       - Added new error detection features for file/dir entries.
+       - Increasing of NR_FD_LISTS is now handled differently for error
+         detection reasons. See README-nrlists.
+       - Marked init functions as __init - though saving a few KB doesn't
+         make such a big difference while using RSBAC... ;)
+       - Fixed memory leaks in write_*_list while introducing vmalloc for
+         large lists. The number of file/dir lists is now only a matter of
+         performance and available memory.
+       - Added two flags to File Flags
+       - Port to 2.2.0-pre6
+       - Added secure deletion/truncation, needs a config switch to be
+         enabled. If on, all files marked with (inheritable) FF-flag
+         secure_delete and all files marked as PM-personal data are zeroed on
+         deletion and truncation - if the regarding modules are switched on.
+
+1.0.7: - Port to 2.1.131
+       - Added more fs types to non-writable: smbfs, ncpfs, codafs - so
+         there should be no writing on network mounts (unfortunately there
+         is no afs SUPER_MAGIC)
+       - Added configuration option NO_DECISION_ON_NETMOUNTS, which
+         additionally turns off all decisions for all these fs, so that
+         they are completely ignored
+       - Added attribute inheritance: Some attributes for files and dirs
+         have a special value 'inherit'. If this is set, the value of the
+         parent dir's attribute is used instead. This mechanism ends on
+         fs boundaries - each fs root dir gets old style standard values,
+         if attribute is set to 'inherit'.
+         Currently security_level, object_category and data_type are
+         inheritable.
+       - Added configuration option DEF_INHERIT. If set, default values for
+         inheritable attributes are *inherit, rather than the old default.
+         This option setting should not differ between different RSBAC
+         kernels to avoid deeper confusion for administrators and
+         rsbac_check().
+       - To support inheritance, added parameter inherit to both get_attr
+         system calls. If on, the effective (possibly inherited) value is
+         returned, if off, the real value is returned.
+       - Corrected a security hole in receiving from / sending via datagram
+         sockets (thanks to Simone). Now a read/append open and a close
+         request are done for every datagram (if net support is configured,
+         as usual).
+         Attention: Programs that open an UDP socket as one user (e.g. root)
+                    and then setuid to another (e.g. bin) may not be able
+                    to access that socket, if the new user has insufficent
+                    rights! (see config help)
+         Checking of net access can as before be turned on/off via
+         CONFIG_RSBAC_NET.
+       - Worked on rsbac_check(). Is more stable now, but should only be
+         called under maximum of moderate load.
+
+1.0.6: - Moved to 2.1.128
+       - Cleaned up old includes in syscalls.c
+       - Added RSBAC own logging in /proc/rsbac-info/rmsg, to be accessed
+         by modified klogd or sys_rsbac_log, restricted by most modules to
+         security officers.
+         Additionally, logging to standard syslog can be turned off to hide
+         security relevant log from all but those with explicit access.
+       - Added module File Flags with attribute ff_flags for FILE/DIR
+         targets
+       - Added auto-update of last version attributes (only FD changed
+         though)
+       - Changed ms_trusted from boolean to tristate: non-trusted, read,
+         full
+       - Fixed rm -r hang bug
+       - Added consistency check for RSBAC items, which can remove items for
+         deleted inodes (ext2 only) and entries containing only default
+         values (FILE/DIR targets only). It also recalculates item counts.
+       - Added sys_rsbac_check to trigger this check.
+
+1.0.5:
+       - Rewrote most of attribute saving to disk. Now disk writing is never
+         done with a spinlock held, increasing stability significantly
+         (is this a taboo? if yes, where is it documented?)
+       - Changed write-to-disk behaviour: The old immediate write is no
+         longer default, but optional (CONFIG_RSBAC_SYNC_WRITE). Instead,
+         sys_rsbac_write can be used from user space or a kernel daemon can
+         be activated to write changes automatically every n seconds
+         (CONFIG_RSBAC_AUTO_WRITE)
+       - Added kernel param rsbac_debug_auto for the daemon - gives a good
+         overview of attribute change rate
+       - Added proc interface for statistics and many RSBAC settings
+       - Added rsbac_adf_request calls MODIFY_SYSTEM_DATA to sysctl.c
+       - Wrote man pages for all RSBAC syscalls (in Documentation/rsbac/man)
+       - Added version information and check for all file/dir/dev aci and
+         for log_levels
+       - Added some more scan strings to Malware Scan module, had to change
+         string representation to a more general way
+
+1.0.4:
+       - Port via 2.1.115 and 2.1.124 to 2.1.125
+       - IPC targets: changed ids for sockets from pid/fd combination to
+         pointer to sock structure, including (many) changes in the
+         handling.
+       - Added socket level scanning (tcp and udp) to module Malware Scan.
+         This feature can stop malware while still being transferred to
+         your system. Added new attributes for IPC, process and file/dir
+         targets to manage socket scan.
+       - Reordered configuration options
+       - Added CONFIG_RSBAC_NO_WRITE to totally disable writing to disk for
+         testing purposes and kernel parameter rsbac_debug_no_write to
+         temporarily disable disk writing 
+       - Added CONFIG_RSBAC_*_ROLE_PROTection for all role dependant
+         modules: Now change-owner (setuid etc.) can be restricted between
+         users with special roles - see configuration help for details
+       - Some more bugfixes, mostly to decision modules
+
+1.0.4-pre2:
+       - Port to 2.1.111
+       - Attribute mac_trusted_for_user added to FILE aci. Value meanings:
+         RSBAC_NO_USER (-3): program is not MAC-trusted
+         RSBAC_ALL_USERS (-4): program is MAC-trusted for all users
+         other user-ID: program is MAC-trusted, if invoked by this user
+         Especially the last is useful for daemon programs that can be
+         started by all users.
+         Init process is checked, too, but is MAC-trusted by default.
+       - Syscalls rsbac_mac_set/get_max_seclevel added. Now a process can
+         reduce its own maximum security level. Useful for wrapper daemons
+         like inetd after forking and before invoking another program.
+       - Object dependent logging #ifdef'd with configuration option.
+       - Configuration option 'Maintenance Kernel' added. Disables all other
+         options.
+       - removed CONFIG_RSBAC_ADMIN and rsbac_admin() stuff - now we have
+         capabilities, and there is no suser() anymore to extend
+       - changed locking for Data Structures component from semaphores to
+         read/write spinlocks
+       - added (U)MOUNT requests for target DEV to sys_(u)mount. Now both
+         target dir and device are checked for access (MAC: dir: read-write,
+         dev: depending on mount mode read or read-write). Note: After
+         mount, all file/dir accesses on this device are checked as usual.
+       - Moved checks for valid request/target combinations from MAC module
+         to extra functions in rsbac/adf/check.c.
+
+1.0.3: - Target DEV added. Now devices can get their own attributes based
+         on major/minor numbers. Attributes based on their file representations
+         in /dev are no longer used for open, but still for all other calls.
+         MAC decisions on open requests for devices must be explicitely enabled
+         by mac_check to keep system bootable.
+         Short rule: Only if contents is accessed, DEV attributes apply.
+       - Attribute object_type removed, was not used anyway and maintained in
+         linux structures.
+       - Attributes log_array_low and log_array_high for FILE/DIR/DEV added,
+         providing individial request based logging for those objects.
+       - PM module: if DEV is personal_data, neccessary access is checked
+         for new class DEV (can be changed to custom class)
+       - A couple of minor bugfixes done
+
+1.0.2A: - Port to 2.0.34
+        - A few #ifdef CONFIG_RSBAC_USE_RSBAC_OWNER were missing, causing
+          error messages "rsbac_set/get_attr returned error" -> added
+
+
+13/Jun/2001
+Amon Ott <ao@rsbac.org>
diff --git a/Documentation/rsbac/Credits b/Documentation/rsbac/Credits
new file mode 100644
index 0000000..7f5921a
--- /dev/null
+++ b/Documentation/rsbac/Credits
@@ -0,0 +1,18 @@
+Credits
+-------
+
+You can find information about the RSBAC team on: <http://rsbac.org/contact>
+
+Credits for many patches showing bugs and possible fixes and lots of good
+ideas go to many people. We cannot recall them all so only a few are included
+here, if you are missing let us know :)
+
+  - 'Our Russian RSBAC Team',
+  - AltLinux with their AltLinux Castle distribution.
+  - Adamantix
+  - rtp, addobie, and the people from #rsbac[-dev]
+
+Also, there are several people doing lots of helpful promotion, too many to
+name them here. Their part cannot be rated too low.
+
+The RSBAC team.
diff --git a/Documentation/rsbac/INSTALL b/Documentation/rsbac/INSTALL
new file mode 100644
index 0000000..6c6f9fe
--- /dev/null
+++ b/Documentation/rsbac/INSTALL
@@ -0,0 +1,18 @@
+RSBAC INSTALL
+=============
+
+Installation from a RSBAC tarball
+---------------------------------
+
+You probably already untar'ed the rsbac-x.y.z.tar.gz archive. You can safely
+untar this archive into your kernel main directory, or copy all files there
+- no file should be overwritten.
+
+To get RSBAC working, you must then patch the kernel using an RSBAC kernel
+patch patch-x.y.z-va.b.c.bz2, matching your kernel version. In kernel main dir
+call
+bzip2 -dc patch-x.y.z-va.b.c.bz2 | patch -p1 &>perr
+After patching, everything should be in place and a log should be in perr.
+
+If your kernel version is not supported, check at
+<http://www.rsbac.org/download> for newer patch files.
diff --git a/Documentation/rsbac/Interceptions-2.4 b/Documentation/rsbac/Interceptions-2.4
new file mode 100644
index 0000000..e279865
--- /dev/null
+++ b/Documentation/rsbac/Interceptions-2.4
@@ -0,0 +1,97 @@
+Interceptions for access decisions (AEF) in RSBAC 1.2.5 for 2.4.30:
+(ordered as in asm-i386/unistd.h)
+
+Not necessary:
+sys_waitpid, sys_time, sys_lseek, sys_getpid, sys_alarm, sys_pause,
+sys_sync, sys_getuid, sys_alarm, sys_ftime, sys_dup, sys_times, sys_brk,
+sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_olduname, sys_umask,
+sys_ustat, sys_dup2, sys_getppid, sys_getpgrp, sys_setsid, sys_sigaction,
+sys_sgetmask, sys_ssetmask, sys_sigsuspend, sys_sigpending, sys_getrlimit,
+sys_getrusage, sys_gettimeofday, sys_getgroups, sys_select, sys_munmap,
+sys_getpriority, sys_setitimer, sys_getitimer, sys_uname, sys_vhangup,
+sys_vm86old, sys_wait4, sys_sysinfo, sys_fsync, sys_sigreturn, sys_newuname,
+sys_modify_ldt, sys_sigprocmask, sys_get_kernel_syms(? - see discussion),
+sys_sysfs, sys_personality, sys__llseek, sys_newselect, sys_flock,
+sys_msync, sys_fdatasync, sys_mlock, sys_munlock, sys_mlockall,
+sys_munlockall, sys_sched_getparam, sys_sched_getscheduler, sys_sched_yield,
+sys_sched_get_priority_max, sys_sched_get_priority_min,
+sys_sched_rr_get_interval, sys_nanosleep, sys_mremap, sys_getresuid,
+sys_vm86, sys_poll, sys_getresgid, sys_prctl, sys_rt_sigreturn,
+sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending,
+sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_getcwd,
+sys_sigaltstack, sys_ugetrlimit, sys_getuid32, sys_getgid32, sys_geteuid32,
+sys_getegid32, sys_getgroups32, sys_getresuid32, sys_getresgid32,
+sys_mincore, sys_madvise, sys_gettid, sys_readahead, sys_setxattr,
+sys_munlockl, sys_munlockall
+
+Not implemented in this kernel:
+sys_ftime, sys_break, sys_stty, sys_gtty, sys_prof, sys_lock, sys_mpx,
+sys_ulimit, sys_profil, sys_idle, sys_afs_syscall, sys_getpmsg,
+sys_putpmsg, sys_security (used by RSBAC where available)
+
+Intercepted:
+sys_exit, sys_fork, sys_read, sys_write, sys_open, sys_close, sys_creat,
+sys_link, sys_unlink, sys_execve, sys_chdir, sys_mknod, sys_chmod,
+sys_lchmod, sys_oldstat, sys_mount, sys_umount (= oldumount), sys_setuid,
+sys_stime, sys_ptrace, sys_oldfstat, sys_utime, sys_access, sys_nice (if
+priority is raised), sys_rename, sys_mkdir, sys_rmdir, sys_setgid, sys_acct
+(APPEND_OPEN on file), sys_umount2 (= umount), sys_ioctl (socket_ioctl,
+tty_ioctl (tiocsti)), sys_fcntl (except locking - see discussion),
+sys_setpgid, sys_chroot, sys_setreuid, sys_setregid, sys_sethostname,
+sys_setrlimit, sys_settimeofday, sys_setgroups, sys_symlink, sys_oldlstat,
+sys_readlink, sys_uselib, sys_swapon, sys_reboot, sys_readdir,
+sys_mmap (for MAP_EXEC), sys_truncate, sys_ftruncate, sys_fchmod,
+sys_fchown, sys_setpriority, sys_statfs, sys_fstatfs, sys_ioperm,
+sys_socketcall, sys_stat, sys_lstat, sys_fstat, sys_iopl, sys_swapoff,
+sys_ipc, sys_clone, sys_setdomainname, sys_adjtimex, sys_mprotect, 
+sys_create_module, sys_init_module, sys_delete_module, 
+sys_getpgid, sys_fchdir, sys_setfsuid, sys_setfsgid, sys_vfsreaddir,
+sys_readv, sys_writev, sys_getsid, sys_sysctl, sys_setresuid, 
+sys_setresgid, sys_pread, sys_pwrite, sys_chown, sys_capget, sys_capset,
+sys_vfork, sys_mmap2, sys_truncate64, sys_ftruncate64, sys_stat64,
+sys_lstat64, sys_fstat64, sys_lchown32, sys_setreuid32, sys_setregid32,
+sys_setgroups32, sys_fchown, sys_setresuid32, sys_setresgid32,
+sys_chown32, sys_setuid32, sys_setgid32, sys_setfsuid32, sys_setfsgid32,
+sys_pivot_root, sys_getdents64, sys_fcntl64, sys_tkill, sys_sendfile64,
+
+
+Found missing in 1.2.4-bf5 and intercepted in 1.2.5-pre:
+ptrace (on sparc and sparc64), ioctl: BRCTL* (bridging control),
+sys_reboot: add reboot_cmd parameter to see command in log,
+sys_mount: lookback mounts in do_loopback(),
+sys_mount: move mounts in do_move_mounts(),
+sys_socketcall (sys_socketpair, sys_setsockopt, sys_getsockopt,
+sys_getsockname, sys_getpeername),
+sys_getxattr, sys_lgetxattr, sys_fgetxattr, sys_setxattr, sys_lsetxattr,
+sys_fsetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
+sys_removexattr, sys_lremovexattr, sys_fremovexattr,
+sys_quotactl (new SCD quota), sys_bdflush, sys_sched_setparam,
+sys_sched_setscheduler, sys_query_module, sys_nfsservctl, sys_sendfile,
+NETLINK sockets (additional IP addresses, routing, firewall, tcpdiag, rules),
+sys_ioctl: fs/ext[3]2/ioctl.c:ext[23]_ioctl(), sys_pipe,
+sys_ioctl: drivers/ide/ide.c:ide_ioctl(),
+sys_ioctl: tty_ioctl,
+sys_fcntl: fs/fcntl.c:do_fcntl(): Control file locking,
+sys_flock: fs/locks.c:sys_flock(): Control file advisory locking,
+sys_get_kernel_syms: kernel/module.c: SCD ksyms, same for /proc/ksyms,
+sys_mlock, sys_mlockall: SCD mlock,
+sys_swapon: Also check access to the device as ADD_TO_KERNEL and
+REMOVE_FROM_KERNEL
+
+Not yet intercepted, for discussion:
+
+- netlink-sockets: iptables_ULOG, decnet, ipv6
+
+Other notes:
+- Added SCD target sysctl, now used by sys_sysctl and /proc/sys instead of
+  non-intuitive ST_other
+
+- Added SCD target nfsd for kernel NFS server control
+
+- Added IPC type anonpipe, used by anonymous T_FIFO (if inode on PIPEFS)
+
+- Added requests GET_STATUS_DATA, GET_PERMISSIONS_DATA, MODIFY_PERMISSIONS_DATA,
+  SEND for target type DEV
+
+- JAIL module: generally deny read, write, GET_STATUS_DATA and MODIFY_SYSTEM_DATA
+  accesses to devices, flags to allow
diff --git a/Documentation/rsbac/Interceptions-2.6 b/Documentation/rsbac/Interceptions-2.6
new file mode 100644
index 0000000..bac1409
--- /dev/null
+++ b/Documentation/rsbac/Interceptions-2.6
@@ -0,0 +1,330 @@
+Interceptions for access decisions (AEF) in RSBAC for the kernel 2.6 as of 2.6.23.13:
+to check against LSM interceptions:
+egrep "static inline (.*) security_" include/linux/security.h |cut -d ' ' -f4|cut -d '(' -f1
+
+#define __NR_restart_syscall      0
+#define __NR_exit		  1 *
+#define __NR_fork		  2 *
+#define __NR_read		  3 *
+#define __NR_write		  4 * 
+#define __NR_open		  5 *
+#define __NR_close		  6 *
+#define __NR_waitpid		  7 -
+#define __NR_creat		  8 *
+#define __NR_link		  9 * [we do not need to check for T_DIR - hardlinks are not allowed for dirs anyway]
+#define __NR_unlink		 10 *
+#define __NR_execve		 11 *
+#define __NR_chdir		 12 *
+#define __NR_time		 13 *
+#define __NR_mknod		 14 *
+#define __NR_chmod		 15 *
+#define __NR_lchown		 16 *
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19 -
+#define __NR_getpid		 20 -
+#define __NR_mount		 21 !
+[do_loopback(), do_move_mount(), do_remount() are missing. we should take care of them, also reading rsbac attributes dirs when necesary]
+#define __NR_umount		 22 *
+#define __NR_setuid		 23 *
+#define __NR_getuid		 24 -
+#define __NR_stime		 25 *
+#define __NR_ptrace		 26 *
+#define __NR_alarm		 27 -
+#define __NR_oldfstat		 28 
+#define __NR_pause		 29 -
+#define __NR_utime		 30 *
+#define __NR_stty		 31 
+#define __NR_gtty		 32 
+#define __NR_access		 33 *
+#define __NR_nice		 34 *
+#define __NR_ftime		 35 
+#define __NR_sync		 36 -
+#define __NR_kill		 37 * 
+#define __NR_rename		 38 *
+#define __NR_mkdir		 39 *
+#define __NR_rmdir		 40 *
+#define __NR_dup		 41 -
+#define __NR_pipe		 42 ! [see Interceptions-2.4]
+#define __NR_times		 43 -
+#define __NR_prof		 44 
+#define __NR_brk		 45 -
+#define __NR_setgid		 46 *
+#define __NR_getgid		 47 -
+#define __NR_signal		 48 -
+#define __NR_geteuid		 49 -
+#define __NR_getegid		 50 -
+#define __NR_acct		 51 ! [missing in 2.6, _and_ also on intercepted on 2.4 !!]
+#define __NR_umount2		 52 
+#define __NR_lock		 53 
+#define __NR_ioctl		 54 ! [missing interception - should be fine grained]
+#define __NR_fcntl		 55 ! [missing interception - should be fine grained]
+#define __NR_mpx		 56 
+#define __NR_setpgid		 57 *
+#define __NR_ulimit		 58 
+#define __NR_oldolduname	 59 
+#define __NR_umask		 60 -
+#define __NR_chroot		 61 *
+#define __NR_ustat		 62 -
+#define __NR_dup2		 63 -
+#define __NR_getppid		 64 -
+#define __NR_getpgrp		 65 -
+#define __NR_setsid		 66 -
+#define __NR_sigaction		 67 -
+#define __NR_sgetmask		 68 -
+#define __NR_ssetmask		 69 -
+#define __NR_setreuid		 70 *
+#define __NR_setregid		 71 *
+#define __NR_sigsuspend		 72 -
+#define __NR_sigpending		 73 -
+#define __NR_sethostname	 74 *
+#define __NR_setrlimit		 75 *
+#define __NR_getrlimit		 76 -
+#define __NR_getrusage		 77 -
+#define __NR_gettimeofday	 78 -
+#define __NR_settimeofday	 79 *
+#define __NR_getgroups		 80 -
+#define __NR_setgroups		 81 *
+#define __NR_select		 82 -
+#define __NR_symlink		 83 *
+#define __NR_oldlstat		 84 
+#define __NR_readlink		 85 *
+#define __NR_uselib		 86 *
+#define __NR_swapon		 87 *
+#define __NR_reboot		 88 *
+#define __NR_readdir		 89 
+#define __NR_mmap		 90 *
+#define __NR_munmap		 91 -
+#define __NR_truncate		 92 *
+#define __NR_ftruncate		 93 * 
+#define __NR_fchmod		 94 *
+#define __NR_fchown		 95 *
+#define __NR_getpriority	 96 -
+#define __NR_setpriority	 97 *
+#define __NR_profil		 98 
+#define __NR_statfs		 99 *
+#define __NR_fstatfs		100 *
+#define __NR_ioperm		101 *
+#define __NR_socketcall		102 ! [missing interception]
+#define __NR_syslog		103 *
+#define __NR_setitimer		104 -
+#define __NR_getitimer		105 -
+#define __NR_stat		106 *
+#define __NR_lstat		107 *
+#define __NR_fstat		108 *
+#define __NR_olduname		109 -
+#define __NR_iopl		110 *
+#define __NR_vhangup		111 
+#define __NR_idle		112 
+#define __NR_vm86old		113 
+#define __NR_wait4		114 -
+#define __NR_swapoff		115 *
+#define __NR_sysinfo		116 -
+#define __NR_ipc		117 ! [missing interception]
+#define __NR_fsync		118 -
+#define __NR_sigreturn		119 -
+#define __NR_clone		120 *
+#define __NR_setdomainname	121 *
+#define __NR_uname		122 -
+#define __NR_modify_ldt		123 
+#define __NR_adjtimex		124 *
+#define __NR_mprotect		125 *
+#define __NR_sigprocmask	126 -
+#define __NR_create_module	127 
+#define __NR_init_module	128 *
+#define __NR_delete_module	129 
+#define __NR_get_kernel_syms	130 
+#define __NR_quotactl		131 ! [missing interception]
+#define __NR_getpgid		132 -
+#define __NR_fchdir		133 *
+#define __NR_bdflush		134 -
+#define __NR_sysfs		135 -
+#define __NR_personality	136 ? [what about it]
+#define __NR_afs_syscall	137 
+#define __NR_setfsuid		138 *
+#define __NR_setfsgid		139 *
+#define __NR__llseek		140 -
+#define __NR_getdents		141 ! [missing interception - should be in vfs_readdir]
+#define __NR__newselect		142 -
+#define __NR_flock		143 -
+#define __NR_msync		144 -
+#define __NR_readv		145 *
+#define __NR_writev		146 *
+#define __NR_getsid		147 *
+#define __NR_fdatasync		148 -
+#define __NR__sysctl		149 ! [missing interception]
+#define __NR_mlock		150 ? [to care or not to care. this is a question !]
+#define __NR_munlock		151 ? [see above]
+#define __NR_mlockall		152 ? [see above]
+#define __NR_munlockall		153 ? [see above]
+#define __NR_sched_setparam		154 ! [missing interception]
+#define __NR_sched_getparam		155 -
+#define __NR_sched_setscheduler		156 ! [missing interception]
+#define __NR_sched_getscheduler		157 -
+#define __NR_sched_yield		158 -
+#define __NR_sched_get_priority_max	159 -
+#define __NR_sched_get_priority_min	160 -
+#define __NR_sched_rr_get_interval	161 -
+#define __NR_nanosleep		162 -
+#define __NR_mremap		163 -
+#define __NR_setresuid		164 *
+#define __NR_getresuid		165 -
+#define __NR_vm86		166 
+#define __NR_query_module	167 ! [intercepted on 2.4, not found on 2.6]
+#define __NR_poll		168 
+#define __NR_nfsservctl		169 ! [missing interception]
+#define __NR_setresgid		170 *
+#define __NR_getresgid		171 -
+#define __NR_prctl              172 -
+#define __NR_rt_sigreturn	173 -
+#define __NR_rt_sigaction	174 -
+#define __NR_rt_sigprocmask	175 -
+#define __NR_rt_sigpending	176 -
+#define __NR_rt_sigtimedwait	177 -
+#define __NR_rt_sigqueueinfo	178 -
+#define __NR_rt_sigsuspend	179 -
+#define __NR_pread64		180 *
+#define __NR_pwrite64		181 *
+#define __NR_chown		182 *
+#define __NR_getcwd		183 -
+#define __NR_capget		184 *
+#define __NR_capset		185 *
+#define __NR_sigaltstack	186 -
+#define __NR_sendfile		187 *
+#define __NR_getpmsg		188 
+#define __NR_putpmsg		189 
+#define __NR_vfork		190 *
+#define __NR_ugetrlimit		191 -
+#define __NR_mmap2		192 *
+#define __NR_truncate64		193 *
+#define __NR_ftruncate64	194 *
+#define __NR_stat64		195 * vfs_stat() seems to be ok, but there is also cp_new_stat()/cp_new_stat64()]
+#define __NR_lstat64		196 *
+#define __NR_fstat64		197 *
+#define __NR_lchown32		198 *
+#define __NR_getuid32		199 -
+#define __NR_getgid32		200 -
+#define __NR_geteuid32		201 -
+#define __NR_getegid32		202 -
+#define __NR_setreuid32		203 
+#define __NR_setregid32		204 
+#define __NR_getgroups32	205 -
+#define __NR_setgroups32	206 
+#define __NR_fchown32		207 
+#define __NR_setresuid32	208  
+#define __NR_getresuid32	209 -
+#define __NR_setresgid32	210 
+#define __NR_getresgid32	211 -
+#define __NR_chown32		212 
+#define __NR_setuid32		213 
+#define __NR_setgid32		214 
+#define __NR_setfsuid32		215 
+#define __NR_setfsgid32		216 
+#define __NR_pivot_root		217 *
+#define __NR_mincore		218 ? [not intercepted - i do not think it is necesary thought]
+#define __NR_madvise		219 ? [not intercepted - maybe this one should be]
+#define __NR_madvise1		219 
+#define __NR_getdents64		220 ! [same as sys_getdents()]
+#define __NR_fcntl64		221 ! [same as sys_fcntl()]
+/* 223 is unused */
+#define __NR_gettid		224 ? [not intercepted, rather no need to]
+#define __NR_readahead		225 ? [not intercepted - shall we ?]
+#define __NR_setxattr		226 ? [do we care about xattr ?]
+#define __NR_lsetxattr		227 ? [see above]
+#define __NR_fsetxattr		228 ? [see above]
+#define __NR_getxattr		229 ? [see above]
+#define __NR_lgetxattr		230 ? [see above]
+#define __NR_fgetxattr		231 ? [see above]
+#define __NR_listxattr		232 ? [see above]
+#define __NR_llistxattr		233 ? [see above]
+#define __NR_flistxattr		234 ? [see above]
+#define __NR_removexattr	235 ? [see above]
+#define __NR_lremovexattr	236 ? [see above]
+#define __NR_fremovexattr	237 ? [see above]
+#define __NR_tkill		238 *
+#define __NR_sendfile64		239 *
+#define __NR_futex		240 ! [multiplexer - check it out]
+#define __NR_sched_setaffinity	241 ! [not intercepted - shall we ?] 
+#define __NR_sched_getaffinity	242 ! [not intercepted, there is no need to]
+#define __NR_set_thread_area	243 
+#define __NR_get_thread_area	244 
+#define __NR_io_setup		245 ? [not intercepted - wtf is it ?]
+#define __NR_io_destroy		246 [see above]
+#define __NR_io_getevents	247 [see above]
+#define __NR_io_submit		248 [see above]
+#define __NR_io_cancel		249 [see above]
+#define __NR_fadvise64		250 ? [not intercepted - don't ask me what the heck is it]
+
+#define __NR_exit_group		252 ? [not intercepted - should be treated like sys_exit() ?]
+#define __NR_lookup_dcookie	253 ? [not intercepted - not necesary]
+#define __NR_epoll_create	254 ? [do we care about epool ?]
+#define __NR_epoll_ctl		255 ? [see above]
+#define __NR_epoll_wait		256 ? [see above]
+#define __NR_remap_file_pages	257 ? [not intercepted - may be dangerous ?]
+#define __NR_set_tid_address	258 ? [not intercepted - no need to]
+#define __NR_timer_create	259 ? [not intercepted - no need to ?]
+#define __NR_timer_settime	    ? [see above]
+#define __NR_timer_gettime	    ? [see above]
+#define __NR_timer_getoverrun	    ? [see above]
+#define __NR_timer_delete	    ? [see above]
+#define __NR_clock_settime	    *
+#define __NR_clock_gettime	    -
+#define __NR_clock_getres	    -
+#define __NR_clock_nanosleep	    -
+#define __NR_statfs64		268 *
+#define __NR_fstatfs64		269 *
+#define __NR_tgkill		270 *
+#define __NR_utimes		271 *
+#define __NR_fadvise64_64	272 ? [not intercepted - look fadvise above]
+#define __NR_vserver		273 - [reservation for friendly project]
+#define __NR_mbind		274 ? [not intercepted - i am borring, but will ask once more - what the heck ? (memory allocation policy stuff ?)]
+#define __NR_get_mempolicy	275 ? [see above]
+#define __NR_set_mempolicy	276 ? [see above]
+#define __NR_mq_open 		277 ? [message queues - i think that may be security revelant]
+#define __NR_mq_unlink		    ? [see above]
+#define __NR_mq_timedsend	    ? [see above]
+#define __NR_mq_timedreceive	    ? [see above]
+#define __NR_mq_notify		    ? [see above]
+#define __NR_mq_getsetattr	    ? [see above]
+#define __NR_sys_kexec_load	283 ! [not found, but kexec is very dangerous - should be imidiatelly be taken care of]
+#define __NR_waitid		284 ? [not intercepted, probably no need to]
+/* #define __NR_sys_setaltroot	285 ? [if any day it will come out from deep shadows we will be playing with it hard] */
+#define __NR_add_key		286 ? [key infrastructure recently hit kernels, another redhat (read: stupid, wastefull and security risky) idea ?]
+#define __NR_request_key	287 ? [see above]
+#define __NR_keyctl		288 ? [see above]
+#define __NR_ioprio_set         289 *
+#define __NR_ioprio_get         290 - 
+#define __NR_inotify_init       291
+#define __NR_inotify_add_watch  292
+#define __NR_inotify_rm_watch   293
+#define __NR_migrate_pages      294
+#define __NR_openat             295
+#define __NR_mkdirat            296
+#define __NR_mknodat            297
+#define __NR_fchownat           298
+#define __NR_futimesat          299
+#define __NR_fstatat64          300
+#define __NR_unlinkat           301
+#define __NR_renameat           302
+#define __NR_linkat             303
+#define __NR_symlinkat          304
+#define __NR_readlinkat         305
+#define __NR_fchmodat           306
+#define __NR_faccessat          307
+#define __NR_pselect6           308
+#define __NR_ppoll              309
+#define __NR_unshare            310
+#define __NR_set_robust_list    311
+#define __NR_get_robust_list    312
+#define __NR_splice             313
+#define __NR_sync_file_range    314
+#define __NR_tee                315
+#define __NR_vmsplice           316
+#define __NR_move_pages         317
+#define __NR_getcpu             318
+#define __NR_epoll_pwait        319
+#define __NR_utimensat          320
+#define __NR_signalfd           321
+#define __NR_timerfd            322
+#define __NR_eventfd            323
+#define __NR_fallocate          324 *
diff --git a/Documentation/rsbac/README b/Documentation/rsbac/README
new file mode 100644
index 0000000..fd676e9
--- /dev/null
+++ b/Documentation/rsbac/README
@@ -0,0 +1,49 @@
+RSBAC README
+------------
+
+Documentation in this section is here for information only.
+
+The full RSBAC documentation is available online, at:
+<http://www.rsbac.org/documentation>
+
+New RSBAC versions as well as support for other kernel versions and bugfixes
+can be downloaded from: <http://www.rsbac.org>
+
+For installation instructions read INSTALL.
+
+Files description:
+------------------
+
+README-kernparam:
+Describes the various kernel parameters that can be used with RSBAC.
+
+README-proc:
+Describes the proc interface to RSBAC.
+
+Information about the registration of additional RSBAC decision modules
+(option CONFIG_RSBAC_REG) can be found in README-reg and html/reg.htm.
+
+(Quite old) man pages for many RSBAC syscalls are in the man directory.
+Russian versions can be found in man-rus.
+
+README-nrlists:
+For large systems (very many files per partition) you might consider
+increasing RSBAC_NR_FD_LISTS in include/rsbac/aci_data_structures.h before
+compiling. Please read README-nrlists first.
+There is also now a kernel configuration option.
+
+README-patching:
+If you patched against another kernel version than stated in the patch
+filename, it is important to work through README-patching.
+
+README-reg:
+Information about the registration of additional RSBAC decision modules
+(option CONFIG_RSBAC_REG) can be found in README-reg.
+
+
+If you run into problems or have questions, please write to the RSBAC
+mailing list at rsbac@rsbac.org (commands like 'subscribe rsbac' as single
+line in the message body to majordomo@rsbac.org), or see:
+<http://www.rsbac.org/contact>
+
+The RSBAC team.
diff --git a/Documentation/rsbac/README-kernparam b/Documentation/rsbac/README-kernparam
new file mode 100644
index 0000000..55c70df
--- /dev/null
+++ b/Documentation/rsbac/README-kernparam
@@ -0,0 +1,93 @@
+RSBAC README for the kernel parameters.
+---------------------------------------
+
+Also see: <http://rsbac.org/documentation/kernel_parameters>
+
+The RSBAC system accepts the following parameters:
+ - rsbac_debug_ds: Debug messages from the Data Structures component.
+ - rsbac_debug_aef: Debug messages from the enforcement component (AEF).
+ - rsbac_debug_no_adf: Set default log level value for all request
+   types to 0: Do not log.
+ - rsbac_debug_adf (default, so obsolete): Set default log level value for all
+   request types to 1: Logging messages
+   from the decision component (ADF) for all requests that were denied (highly
+   recommended for testing, even in normal use). If provided, pseudonyms of
+   users are used.
+ - rsbac_debug_adf_all: Set default log level value for all request types to 2:
+   Logging messages from the decision component (ADF) for all requests. If
+   provided, pseudonyms of users are used. Gives a real lot of logging stuff
+    - never try this, if checking of sys_syslog is turned on and log levels
+   have not yet been saved to keep them permanent...
+ - rsbac_debug_ds_pm: Debug messages from the Data Structures component,
+   on access to privacy model data.
+ - rsbac_debug_aef_pm: Debug messages for privacy model specific system
+   calls.
+ - rsbac_debug_adf_pm: Debug messages for access control in privacy module.
+ - rsbac_debug_pm: Sets rsbac_debug_ds_pm, rsbac_debug_aef_pm,
+   rsbac_debug_adf_pm (recommended for testing privacy model).
+ - rsbac_debug_adf_ms: Debug messages for access control in Malware Scan.
+ - rsbac_debug_ds_rc: Debug messages from the Data Structures component,
+   on access to Role Compatibility model data.
+ - rsbac_debug_aef_rc: Debug messages for Role Compatibility model specific
+   system calls.
+ - rsbac_debug_adf_rc: Debug messages for access control in RC module.
+ - rsbac_debug_rc: Sets rsbac_debug_ds_rc, rsbac_debug_aef_rc,
+   rsbac_debug_adf_rc.
+ - rsbac_debug_ds_auth: Debug messages from the Data Structures component,
+   on access to AUTH model data.
+ - rsbac_debug_aef_auth: Debug messages for AUTH model specific system calls.
+ - rsbac_debug_adf_auth: Debug messages for access control in AUTH module.
+ - rsbac_debug_auth: Sets rsbac_debug_ds_auth, rsbac_debug_aef_auth,
+   rsbac_debug_adf_auth.
+ - rsbac_debug_ds_acl: Debug messages from the Data Structures component,
+   on access to Access Control Lists (ACL) model data.
+ - rsbac_debug_aef_acl: Debug messages for ACL model specific
+   system calls.
+ - rsbac_debug_adf_acl: Debug messages for access control in ACL module.
+ - rsbac_debug_acl: Sets rsbac_debug_ds_acl, rsbac_debug_aef_acl,
+   rsbac_debug_adf_acl.
+ - rsbac_debug_all: Sets all debug options - in fact turns on a huge amount
+   of logging. Beware of a fast growing system log. Hardly ever recommended.
+ - rsbac_debug_no_write: Turn writing to disk off for this
+   single boot time. For testing.
+ - rsbac_debug_auto: Debug messages from auto-write / rsbacd. Recommended
+   for a good disk saving overview.
+ - rsbac_debug_write: Debug messages from all attribute writing related
+   procedures.
+ - rsbac_no_defaults: suppress creation of default settings, useful for
+   restore from existing backup. Warning: An unconfigured system will only
+   come up in softmode or maint mode, and softmode will produce loads of
+   logging (see rsbac_nosyslog option...).
+ - rsbac_auth_enable_login: Sets auth_may_setuid for /bin/login, if AUTH
+   module is on. A good emergency helper, if you cannot login anymore.
+ - rsbac_softmode (only, if enabled on kernel config): switch to softmode
+ - rsbac_softmode_once (only, if enabled on kernel config): switch to softmode
+   and disallow to switch it on again later
+ - rsbac_softmode_never (only, if softmode enabled on kernel config):
+   disallow to switch softmode on during this runtime
+ - rsbac_softmode_<mod> (module name in lowercase, e.g. rc, only if enabled):
+   switch individual model softmode to on
+ - rsbac_freeze (only, if enabled in kernel config): Disallow RSBAC
+   administration for this runtime.
+ - rsbac_dac_disable (only, if enabled in kernel config): disable Linux DAC
+ - rsbac_nosyslog: do not log to syslog for this boot time
+ - rsbac_no_init_delay: disable delayed init for this single boot (if
+   init delay is enabled in kernel config)
+ - rsbac_delayed_root=major[:minor]: initialize, when this device gets
+   mounted. Omit minor or set to 00 to match all devices with this major
+   number. Delayed init must be enabled in kernel config.
+ - rsbac_auth_learn (only, if enabled in kernel config): enable AUTH
+   learning mode, where AUTH module adds all missing capabilities
+   automatically instead of denying the request.
+ - rsbac_acl_learn and rsbac_acl_learn_fd (only, if enabled in kernel
+   config): enable ACL learning mode for user rights to filesystem objects
+ - rsbac_log_remote_addr=a.b.c.d: Set remote logging address to a.b.c.d
+ - rsbac_log_remote_port=n: Set remote logging port to n. Remote logging
+   must be enabled in kernel config.
+ - rsbac_um_no_excl: Disable exlusive user management for this uptime.
+ - rsbac_daz_ttl=n: Set DAZ cache item ttl to n seconds for this boot.
+ - rsbac_cap_log_missing: Log all calls to capable() for caps, which are
+   not in the process set of effective Linux capabilities, i.e., failed
+   capable() checks.
+
+Last updated: 28/Jan/2005
diff --git a/Documentation/rsbac/README-nrlists b/Documentation/rsbac/README-nrlists
new file mode 100644
index 0000000..496aad4
--- /dev/null
+++ b/Documentation/rsbac/README-nrlists
@@ -0,0 +1,28 @@
+RSBAC README-nrlists
+--------------------
+
+For large systems (very many files per partition) you should increase
+RSBAC_NR_FD_LISTS in include/rsbac/aci_data_structures.h before compiling.
+
+You should earnestly consider increasing, if you get warning messages like
+"write_fd_list(): list n too large (m bytes), calling partial_write_fd_list()!"
+(this does not lead to data loss though - it only decreases stability a
+bit). This should not happen any longer though - if it does, please send a
+note to RSBAC mailing list containing your /proc/rsbac-info/stats output and
+the output of free at the time when the messages appear for examination.
+
+CAUTION:
+- When restarting with a larger number of lists for the first time, you *must*
+  use the kernel parameter rsbac_change_nr! Only then old attributes are
+  allowed to be sorted into the now correct lists, otherwise they get lost and
+  that's it.
+- Please remember mounting rw all partitions used by RSBAC so far, while
+  rsbac_change_nr is still active.
+- There is definately no way back to a smaller number. All following RSBAC
+  versions must be set to the same value, and rebooting with an older kernel
+  can result in unnoticable attribute losses.
+
+To test this feature, you can use rsbac_debug_no_write. This prevents
+attribute saving and thus attribute loss from previous runs. Those
+partitions that are not mounted rw at boot time can be tested by mounting
+read-only.
diff --git a/Documentation/rsbac/README-patching b/Documentation/rsbac/README-patching
new file mode 100644
index 0000000..2cf1691
--- /dev/null
+++ b/Documentation/rsbac/README-patching
@@ -0,0 +1,27 @@
+RSBAC README for patching against other versions.
+-------------------------------------------------
+
+To make my point clear: I do not recommend patching against other kernel
+versions than stated in the patch filename. Rather check RSBAC homepage
+for new versions or send a note to the RSBAC mailing list (see README).
+
+If you had to patch against another version, you will have to do the following:
+ - Make sure you understand how rsbac_adf_request() and rsbac_adf_set_attr()
+   calls work
+ - Patch in all rejects by hand.
+ - Edit fs/namei.c:
+     rsbac_lookup_one_len/hash must be lookup_one_len/hash minus
+     checks (permission(), rsbac_adf_request()).
+     Please do not forget to change the call to lookup_hash in
+     rsbac_lookup_one_len into rsbac_lookup_hash.
+ - arch/i386/kernel/entry.S must contain the RSBAC syscall number added,
+   embraced by #ifdef CONFIG_RSBAC.
+   You may have to adjust syscall numbers there and in
+   include/rsbac/unistd-i386.h. After that make sure you recompiled the
+   admin tools.
+ - Same for all other archs
+ - Check in rsbac/data_structures/aci_data_structures.c, if file opening and
+   closing are done correctly (rsbac_read_open, rsbac_write_open,
+   rsbac_read_close, rsbac_write_close).
+ - Check in rsbac/help/debug.c, whether the logging in rsbac_log() is
+   implemented correctly - see sys_syslog() in kernel/printk.c
diff --git a/Documentation/rsbac/README-proc b/Documentation/rsbac/README-proc
new file mode 100644
index 0000000..168516e
--- /dev/null
+++ b/Documentation/rsbac/README-proc
@@ -0,0 +1,93 @@
+RSBAC README for the proc interface.
+------------------------------------
+
+Also see: <http://rsbac.org/documentation/proc_interface>
+
+If enabled in the kernel configuration, RSBAC adds one directory to the
+main proc dir: rsbac-info. Since proc is treated as a normal read-only fs,
+rsbac could not be used.
+
+All successful write accesses are logged via syslog at KERN_INFO level.
+The rsbac-info dir contains the following entries:
+
+ - stats: shows rsbac status, same contents as sys_rsbac_stats writes into
+   syslog
+
+ - active: short summary of version, mode and module states, good for scripts
+
+ - stats_pm (if PM is enabled): shows PM status, same contents as
+   sys_rsbac_stats_pm writes into syslog
+
+ - stats_rc (if RC is enabled): shows RC status
+
+ - stats_auth (if AUTH is enabled): shows AUTH status
+
+ - stats_acl (if ACL is enabled): shows ACL status
+
+ - xstats (if extended status is enabled): shows extended status, e.g. table
+   of call counts for requests and targets
+
+ - devices: shows all rsbac-mounted devices in n:m notation and their
+   no_write status (no_write is set on fd-list read, if wrong version).
+   No_write status can be changed by calling
+          echo "devices no_write n:m k" >devices
+   with n:m is the device in major:minor notation, k is 0 or 1.
+
+ - acl_devices, auth_devices: same for ACL and AUTH data structures
+
+ - debug: shows all RSBAC debug settings, softmode, dac_disable and nosyslog.
+   Levels can be changed by calling
+          echo "debug name n" >debug
+   Valid names are ds, aef, no_write, ds_pm, aef_pm, adf_pm, adf_ms, ds_rc,
+   aef_rc, adf_rc, ds_acl, aef_acl, adf_acl, auto, softmode, dac_disable and 
+   nosyslog, but only, if shown when reading this file. Valid levels are 0
+   and 1.
+   Debug levels can be preset to 1 by kernel parameters with same name as
+   variable name shown, e.g. rsbac_debug_ds or rsbac_softmode.
+   Individual model softmode can be switched by calling
+          echo "debug ind_softmode <modname> n" >debug
+   Remote logging address and port can be changed with
+          echo "debug log_remote_addr a.b.c.d" >debug
+          echo "debug log_remote_port n" >debug
+   DAZ cache ttl is set via
+          echo "debug daz_ttl n" >debug
+
+ - log_levels: shows adf log levels for all requests. Log levels can be
+   changed by calling
+   echo "log_levels request n" >log_levels
+   with request = request name, e.g. WRITE, n = level.
+
+ - auto_write (if auto-write is enabled): shows auto write status, currently
+   auto interval in jiffies and auto debug level only.
+   Auto interval can be changed by calling
+          echo "auto interval n" >auto_write
+   with n = number of jiffies, debug level (0 or 1) by calling
+          echo "auto debug n" >auto_write
+
+ - versions: shows aci versions for dev and user list and adf request array
+   version for log_level array and the no_write status of each (set on boot,
+   if wrong version is tried to be read). No_write status can be changed by
+   calling
+          echo "no_write listname n" >versions
+   with listname is one of dev, user, log_levels, n is 0 or 1.
+
+ - rmsg (if own logging is enabled): similar to kmsg in main proc dir, logging
+   of RSBAC requests. This file can be used by programs like klogd.
+
+ - auth_caplist (if AUTH is enabled): shows all AUTH capabilities currently
+   set.
+
+ - reg_modules (if REG is enabled): shows currently registered additional
+   decision modules and syscalls.
+
+ - acl_acllist (if ACL is enabled): Detailed listing of all ACL entries and
+   masks in the system.
+
+ - backup subdir: It contains backups of what would be
+   current aci data files. You can use cp for backups of system independent aci
+   data structures, e.g. rc_roles, rc_types, and the admin backup tools for
+   system dependent ones, e.g. file/dir attributes or AUTH file capabilities.
+   Using the backup_all script or single lines from it is however strongly
+   recommended.
+
+Last updated: 18/Jan/2005
diff --git a/Documentation/rsbac/README-reg b/Documentation/rsbac/README-reg
new file mode 100644
index 0000000..10d6b8b
--- /dev/null
+++ b/Documentation/rsbac/README-reg
@@ -0,0 +1,37 @@
+RSBAC README for the REG facility.
+----------------------------------
+
+Also see: <http://rsbac.org/documentation/write_your_decision_module>
+
+If enabled in the kernel configuration, RSBAC REG allows the registration
+and unregistration of additional decision modules at runtime, usually from
+a kernel module.
+
+These modules register with a name and a chosen magic handle, which can be
+used for switching on/off and for unregistration.
+
+By registration, a request (the decision itself), a set_attr (called after 
+successful syscall completion) and a need_overwrite (called to determine,
+whether a file needs to be securely deleted/truncated) function can be
+installed.
+
+Apart from these decision functions some support routines can be registered.
+Currently these are write (signal asynchronous attribute writing to disk,
+called regularly by rsbacd), mount and umount (a device has been (u)mounted).
+
+However, each of these function pointers can be set to NULL, if
+no call of this type is wanted.
+
+All functions are *additional* to the existing functions from builtin
+modules, e.g. MAC or RC. This way, they can only further restrict access,
+but not grant anything denied by other models.
+
+Also, you can now register system calls and generic lists.
+
+For examples of builtin real decision modules and their functions see
+subdirs below rsbac/adf/.
+
+Working example modules with simple call counters and a proc pseudo file
+for counter display can be found in the examples/reg/ directory of the
+rsbac-admin tools. These are basically the same modules that are built if
+you enabled building of sample modules in kernel config.
diff --git a/MAINTAINERS b/MAINTAINERS
index ecd0eb8..fdfaca0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8393,6 +8393,13 @@ T:	git git://linuxtv.org/anttip/media_tree.git
 S:	Maintained
 F:	drivers/media/dvb-frontends/rtl2832_sdr*
 
+RSBAC
+P:	Amon Ott
+M:	ao@rsbac.org
+L:	rsbac@rsbac.org
+W:	http://www.rsbac.org
+S:	Maintained
+
 RTL8180 WIRELESS DRIVER
 L:	linux-wireless@vger.kernel.org
 W:	http://wireless.kernel.org/
diff --git a/Makefile b/Makefile
index 1f55602..0dbbac1 100644
--- a/Makefile
+++ b/Makefile
@@ -838,6 +838,13 @@ export	INSTALL_PATH ?= /boot
 export INSTALL_DTBS_PATH ?= $(INSTALL_PATH)/dtbs/$(KERNELRELEASE)
 
 #
+
+# Add RSBAC version
+ifeq ($(CONFIG_RSBAC),y)
+EXTRAVERSION:=$(EXTRAVERSION)-rsbac
+core-y		+= rsbac/
+endif
+
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
 # relocations required by build roots.  This is not defined in the
 # makefile but the argument can be passed to make if needed.
diff --git a/arch/alpha/include/uapi/asm/unistd.h b/arch/alpha/include/uapi/asm/unistd.h
index aa33bf5..6a74a85 100644
--- a/arch/alpha/include/uapi/asm/unistd.h
+++ b/arch/alpha/include/uapi/asm/unistd.h
@@ -338,7 +338,11 @@
 #define __NR_getdents64			377
 #define __NR_gettid			378
 #define __NR_readahead			379
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac                      380
+#else
 /* 380 is unused */
+#endif
 #define __NR_tkill			381
 #define __NR_setxattr			382
 #define __NR_lsetxattr			383
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
index 6ff8886..658ecc4 100644
--- a/arch/alpha/kernel/asm-offsets.c
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -35,6 +35,9 @@ void foo(void)
 	DEFINE(PT_PTRACED, PT_PTRACED);
 	DEFINE(CLONE_VM, CLONE_VM);
 	DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
+#ifdef CONFIG_RSBAC
+	DEFINE(CLONE_KTHREAD, CLONE_KTHREAD);
+#endif
 	DEFINE(SIGCHLD, SIGCHLD);
 	BLANK();
 
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index d9ee817..539390c 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -22,6 +22,8 @@
 
 #include "proto.h"
 
+#include <rsbac/hooks.h>
+
 #define DEBUG	DBG_MEM
 #undef DEBUG
 
@@ -276,6 +278,26 @@ long arch_ptrace(struct task_struct *child, long request,
 	unsigned long tmp;
 	size_t copied;
 	long ret;
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rcu_read_lock();
+	rsbac_target_id.process = task_pid(child);
+	rsbac_attribute_value.trace_request = request;
+	if (!rsbac_adf_request(R_TRACE,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_trace_request,
+				rsbac_attribute_value))
+	{
+		rcu_read_unlock();
+		return -EPERM;
+	}
+	rcu_read_unlock();
+#endif
 
 	switch (request) {
 	/* When I and D space are separate, these will need to be fixed.  */
diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h
index 0c3f5a0..f2fc814 100644
--- a/arch/arm/include/uapi/asm/unistd.h
+++ b/arch/arm/include/uapi/asm/unistd.h
@@ -248,7 +248,12 @@
 #define __NR_madvise			(__NR_SYSCALL_BASE+220)
 #define __NR_fcntl64			(__NR_SYSCALL_BASE+221)
 					/* 222 for tux */
+/* RSBAC - we use 223, the old sys_security */
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac                      (__NR_SYSCALL_BASE+223)
+#else
 					/* 223 is unused */
+#endif
 #define __NR_gettid			(__NR_SYSCALL_BASE+224)
 #define __NR_readahead			(__NR_SYSCALL_BASE+225)
 #define __NR_setxattr			(__NR_SYSCALL_BASE+226)
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index 05745eb..2481276 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -232,7 +232,11 @@
 /* 220 */	CALL(sys_madvise)
 		CALL(ABI(sys_fcntl64, sys_oabi_fcntl64))
 		CALL(sys_ni_syscall) /* TUX */
+#ifdef CONFIG_RSBAC
+		CALL(sys_rsbac)
+#else
 		CALL(sys_ni_syscall)
+#endif
 		CALL(sys_gettid)
 /* 225 */	CALL(ABI(sys_readahead, sys_oabi_readahead))
 		CALL(sys_setxattr)
diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
index 81570fc..904fa38 100644
--- a/arch/cris/arch-v10/kernel/entry.S
+++ b/arch/cris/arch-v10/kernel/entry.S
@@ -826,7 +826,11 @@ sys_call_table:
 	.long sys_getdents64	/* 220 */
 	.long sys_fcntl64
 	.long sys_ni_syscall	/* reserved for TUX */
-	.long sys_ni_syscall
+#ifdef CONFIG_RSBAC
+	.long sys_rsbac 	/*	reserved for sys_security */
+#else
+	.long sys_ni_syscall 	/*	reserved for sys_security */
+#endif
 	.long sys_gettid
 	.long sys_readahead	/* 225 */
 	.long sys_setxattr
diff --git a/arch/ia64/include/uapi/asm/unistd.h b/arch/ia64/include/uapi/asm/unistd.h
index 4610795..9f579ea 100644
--- a/arch/ia64/include/uapi/asm/unistd.h
+++ b/arch/ia64/include/uapi/asm/unistd.h
@@ -298,6 +298,9 @@
 #define __NR_utimensat			1306
 #define __NR_signalfd			1307
 #define __NR_timerfd			1308
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac                      1308
+#endif
 #define __NR_eventfd			1309
 #define __NR_timerfd_create		1310
 #define __NR_timerfd_settime		1311
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 60ef83e..69e0388 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -202,6 +202,9 @@ void foo(void)
     /* for assembly files which can't include sched.h: */
 	DEFINE(IA64_CLONE_VFORK, CLONE_VFORK);
 	DEFINE(IA64_CLONE_VM, CLONE_VM);
+#ifdef CONFIG_RSBAC
+	DEFINE(IA64_CLONE_KTHREAD, CLONE_KTHREAD);
+#endif
 
 	BLANK();
 	DEFINE(IA64_CPUINFO_NSEC_PER_CYC_OFFSET,
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index fcf8b8c..3dd90b0 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1745,7 +1745,11 @@ sys_call_table:
 	data8 sys_epoll_pwait			// 1305
 	data8 sys_utimensat
 	data8 sys_signalfd
+#ifdef CONFIG_RSBAC
+	data8 sys_rsbac
+#else
 	data8 sys_ni_syscall
+#endif
 	data8 sys_eventfd
 	data8 sys_timerfd_create		// 1310
 	data8 sys_timerfd_settime
diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
index 51f5e9a..a9da573 100644
--- a/arch/m32r/kernel/ptrace.c
+++ b/arch/m32r/kernel/ptrace.c
@@ -32,6 +32,8 @@
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
 
+#include <rsbac/hooks.h>
+
 /*
  * This routine will get a word off of the process kernel stack.
  */
@@ -624,6 +626,25 @@ arch_ptrace(struct task_struct *child, long request,
 	    unsigned long addr, unsigned long data)
 {
 	int ret;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = task_pid(child);
+		rsbac_attribute_value.trace_request = request;
+		if (!rsbac_adf_request(R_TRACE,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_trace_request,
+					rsbac_attribute_value))
+		{
+			return -EPERM;
+		}
+#endif
+
 	unsigned long __user *datap = (unsigned long __user *) data;
 
 	switch (request) {
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
index 61fb6cb..4428fc4 100644
--- a/arch/m68k/include/uapi/asm/unistd.h
+++ b/arch/m68k/include/uapi/asm/unistd.h
@@ -223,7 +223,9 @@
 #define __NR_setfsuid32		215
 #define __NR_setfsgid32		216
 #define __NR_pivot_root		217
-/* 218*/
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac              218
+#endif
 /* 219*/
 #define __NR_getdents64		220
 #define __NR_gettid		221
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index a0ec430..e4c3828 100644
--- a/arch/m68k/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
@@ -377,3 +377,10 @@ ENTRY(sys_call_table)
 	.long sys_bpf
 	.long sys_execveat		/* 355 */
 
+#ifdef CONFIG_RSBAC
+	/* we use 400, until sys_security gets defined here */
+	.rept 399-346
+		.long sys_ni_syscall
+	.endr
+	.long sys_rsbac
+#endif
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index d516765..7d5c957 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -434,7 +434,11 @@ EXPORT(sys_call_table)
 	PTR	sys_madvise
 	PTR	sys_getdents64
 	PTR	sys_fcntl64			/* 4220 */
+#ifdef CONFIG_RSBAC
+	PTR	sys_rsbac
+#else
 	PTR	sys_ni_syscall
+#endif
 	PTR	sys_gettid
 	PTR	sys_readahead
 	PTR	sys_setxattr
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index a60edb49..80148b7 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -296,7 +296,11 @@ EXPORT(sys_call_table)
 	PTR	sys_ni_syscall			/* res. for getpmsg */
 	PTR	sys_ni_syscall			/* 5175	 for putpmsg */
 	PTR	sys_ni_syscall			/* res. for afs_syscall */
+#ifdef CONFIG_RSBAC
+	PTR	sys_rsbac			/* Security */
+#else
 	PTR	sys_ni_syscall			/* res. for security */
+#endif
 	PTR	sys_gettid
 	PTR	sys_readahead
 	PTR	sys_setxattr			/* 5180 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 185092b..7f9bba0 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -431,7 +431,11 @@ EXPORT(sys32_call_table)
 	PTR	sys_madvise
 	PTR	sys_getdents64
 	PTR	compat_sys_fcntl64		/* 4220 */
+#ifdef CONFIG_RSBAC
+	PTR	sys_rsbac			/* Security */
+#else
 	PTR	sys_ni_syscall
+#endif
 	PTR	sys_gettid
 	PTR	sys32_readahead
 	PTR	sys_setxattr
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 3781b8c..21d3503 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -404,6 +404,9 @@
 	ENTRY_SAME(timerfd_create)
 	ENTRY_COMP(timerfd_settime)
 	ENTRY_COMP(timerfd_gettime)
+#ifdef CONFIG_RSBAC
+	ENTRY_SAME(rsbac)
+#endif
 	ENTRY_COMP(signalfd4)
 	ENTRY_SAME(eventfd2)		/* 310 */
 	ENTRY_SAME(epoll_create1)
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index f1863a1..72cd826 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -228,7 +228,11 @@ SYSCALL_SPU(fremovexattr)
 COMPAT_SYS_SPU(futex)
 COMPAT_SYS_SPU(sched_setaffinity)
 COMPAT_SYS_SPU(sched_getaffinity)
+#ifdef CONFIG_RSBAC
+SYSCALL(rsbac)
+#else
 SYSCALL(ni_syscall)
+#endif
 SYSCALL(ni_syscall)
 SYS32ONLY(sendfile64)
 COMPAT_SYS_SPU(io_setup)
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h
index e4aa173..09f0327 100644
--- a/arch/powerpc/include/uapi/asm/unistd.h
+++ b/arch/powerpc/include/uapi/asm/unistd.h
@@ -238,6 +238,10 @@
 #define __NR_futex		221
 #define __NR_sched_setaffinity	222
 #define __NR_sched_getaffinity	223
+/* RSBAC - we use 224, the old sys_security */
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac              224
+#endif
 /* 224 currently unused */
 #define __NR_tuxcall		225
 #ifndef __powerpc64__
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 23fe603..528b736 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -367,6 +367,9 @@ int main(void)
 #endif
 	DEFINE(CLONE_VM, CLONE_VM);
 	DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
+#ifdef CONFIG_RSBAC
+	DEFINE(CLONE_KTHREAD, CLONE_KTHREAD);
+#endif
 
 #ifndef CONFIG_PPC64
 	DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h
index d13a1d6..883d27c 100644
--- a/arch/sh/include/uapi/asm/unistd_32.h
+++ b/arch/sh/include/uapi/asm/unistd_32.h
@@ -232,7 +232,11 @@
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
 				/* 222 is reserved for tux */
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac              223
+#else
 				/* 223 is unused */
+#endif
 #define __NR_gettid		224
 #define __NR_readahead		225
 #define __NR_setxattr		226
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h
index e6820c8..b467b29 100644
--- a/arch/sh/include/uapi/asm/unistd_64.h
+++ b/arch/sh/include/uapi/asm/unistd_64.h
@@ -270,7 +270,11 @@
 #define __NR_getdents64		248
 #define __NR_fcntl64		249
 				/* 250 is reserved for tux */
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac              251
+#else
 				/* 251 is unused */
+#endif
 #define __NR_gettid		252
 #define __NR_readahead		253
 #define __NR_setxattr		254
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 734234b..d6ae567 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -239,7 +239,11 @@ ENTRY(sys_call_table)
 	.long sys_getdents64	/* 220 */
 	.long sys_fcntl64
 	.long sys_ni_syscall	/* reserved for TUX */
+#ifdef CONFIG_RSBAC
+        .long sys_rsbac
+#else
 	.long sys_ni_syscall	/* Reserved for Security */
+#endif
 	.long sys_gettid
 	.long sys_readahead	/* 225 */
 	.long sys_setxattr
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 579fcb9..05e67f7 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -276,7 +276,11 @@ sys_call_table:
 	.long sys_getdents64
 	.long sys_fcntl64
 	.long sys_ni_syscall		/* 250 reserved for TUX */
+#ifdef CONFIG_RSBAC
+        .long sys_rsbac
+#else
 	.long sys_ni_syscall		/* Reserved for Security */
+#endif
 	.long sys_gettid
 	.long sys_readahead
 	.long sys_setxattr
diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h
index 6f35f4d..f89223b 100644
--- a/arch/sparc/include/uapi/asm/unistd.h
+++ b/arch/sparc/include/uapi/asm/unistd.h
@@ -417,7 +417,13 @@
 #define __NR_bpf		349
 #define __NR_execveat		350
 
+#ifdef CONFIG_RSBAC
+#define __NR_rsbac              351
+#define NR_SYSCALLS            352
+#else
 #define NR_syscalls		351
+#endif
+
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK	0x00000001
diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c
index a331fdc..d49f03c 100644
--- a/arch/sparc/kernel/ptrace_32.c
+++ b/arch/sparc/kernel/ptrace_32.c
@@ -28,6 +28,8 @@
 
 #include "kernel.h"
 
+#include <rsbac/hooks.h>
+
 /* #define ALLOW_INIT_TRACING */
 
 /*
@@ -215,6 +217,28 @@ static int fpregs32_get(struct task_struct *target,
 	const unsigned long *fpregs = target->thread.float_regs;
 	int ret = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rcu_read_lock();
+	rsbac_target_id.process = find_pid_ns(pid, &init_pid_ns);
+	rsbac_attribute_value.trace_request = request;
+	if (!rsbac_adf_request(R_TRACE,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_trace_request,
+				rsbac_attribute_value))
+	{
+		rcu_read_unlock();
+		return -EPERM;
+	}
+	rcu_read_unlock();
+#endif
+
+
 #if 0
 	if (target == current)
 		save_and_clear_fpu();
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index c156617..94a0e17 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -39,6 +39,8 @@
 #include <asm/cpudata.h>
 #include <asm/cacheflush.h>
 
+#include <rsbac/hooks.h>
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
@@ -872,9 +874,32 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 	unsigned long data = cdata;
 	int ret;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	pregs = (struct pt_regs32 __user *) addr;
 	fps = (struct compat_fps __user *) addr;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rcu_read_lock();
+	rsbac_target_id.process = task_pid(child);
+	rsbac_attribute_value.trace_request = request;
+	if (!rsbac_adf_request(R_TRACE,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_trace_request,
+				rsbac_attribute_value))
+	{
+		rcu_read_unlock();
+		return -EPERM;
+	}
+	rcu_read_unlock();
+#endif
+
 	switch (request) {
 	case PTRACE_PEEKUSR:
 		ret = (addr != 0) ? -EIO : 0;
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index e31a905..51dd487 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -48,7 +48,11 @@ sys_call_table:
 /*145*/	.long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/	.long sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
 /*155*/	.long sys_fcntl64, sys_inotify_rm_watch, sys_statfs, sys_fstatfs, sys_oldumount
+#ifdef CONFIG_RSBAC /* we use 164, which seems to be unused */
+/*160*/	.long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_rsbac
+#else
 /*160*/	.long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
+#endif
 /*165*/	.long sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr
 /*170*/	.long sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
 /*175*/	.long sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index d72f76a..72c65c6 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -50,7 +50,11 @@ sys_call_table32:
 	.word compat_sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/	.word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
 	.word compat_sys_fcntl64, sys_inotify_rm_watch, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
+#ifdef CONFIG_RSBAC /* we use 164, which seems to be unused */
+/*160*/	.word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_rsbac
+#else
 /*160*/	.word compat_sys_sched_setaffinity, compat_sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
+#endif
 	.word sys_quotactl, sys_set_tid_address, compat_sys_mount, compat_sys_ustat, sys_setxattr
 /*170*/	.word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, compat_sys_getdents
 	.word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 589b319..f4fbd15 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -17,6 +17,8 @@
 #include <linux/bitmap.h>
 #include <asm/syscalls.h>
 
+#include <rsbac/hooks.h>
+
 /*
  * this changes the io permissions bitmap in the current task.
  */
@@ -26,11 +28,31 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 	struct tss_struct *tss;
 	unsigned int i, max_long, bytes, bytes_updated;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
 		return -EINVAL;
 	if (turn_on && !capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_ioports;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	/*
 	 * If it's the first ioperm() call in this thread's lifetime, set the
 	 * IO bitmap up. ioperm() is much less timing critical than clone(),
@@ -104,6 +126,11 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
 	 */
 	unsigned int old = t->iopl >> X86_EFLAGS_IOPL_BIT;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (level > 3)
 		return -EINVAL;
 	/* Trying to gain more privileges? */
@@ -111,9 +138,26 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
 	}
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_ioports;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
 		(level << X86_EFLAGS_IOPL_BIT);
 	t->iopl = level << X86_EFLAGS_IOPL_BIT;
+
 	set_iopl_mask(t->iopl);
 
 	return 0;
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index f3a443d..cf37875 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -229,7 +229,7 @@
 220	i386	getdents64		sys_getdents64			compat_sys_getdents64
 221	i386	fcntl64			sys_fcntl64			compat_sys_fcntl64
 # 222 is unused
-# 223 is unused
+223	i386	rsbac			sys_rsbac
 224	i386	gettid			sys_gettid
 225	i386	readahead		sys_readahead			sys32_readahead
 226	i386	setxattr		sys_setxattr
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index 9ef32d5..4fb80c7 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -191,7 +191,7 @@
 182	common	putpmsg
 183	common	afs_syscall
 184	common	tuxcall
-185	common	security
+185	common	rsbac			sys_rsbac
 186	common	gettid			sys_gettid
 187	common	readahead		sys_readahead
 188	common	setxattr		sys_setxattr
diff --git a/block/ioctl.c b/block/ioctl.c
index 7d8befd..15cd13a 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -9,6 +9,12 @@
 #include <linux/blktrace_api.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_RSBAC
+#include <rsbac/adf.h>
+#include <linux/hdreg.h>
+#endif
+
+
 static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg)
 {
 	struct block_device *bdevp;
@@ -280,6 +286,61 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	int ret, n;
 	unsigned int max_sectors;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "blkdev_ioctl(): calling ADF\n");
+
+	/* values taken from include/linux/fs.h and hdreg.h */
+	switch (cmd) {
+		case BLKGETSIZE:   /* Return device size */
+		case BLKGETSIZE64:
+		case BLKROGET:
+		case BLKRAGET:
+		case BLKFRAGET:
+		case BLKSECTGET:
+		case BLKSSZGET:
+		case BLKBSZGET:
+		case HDIO_GETGEO:
+		case HDIO_OBSOLETE_IDENTITY:
+		case HDIO_GET_UNMASKINTR:
+		case HDIO_GET_IDENTITY:
+		case HDIO_GET_NICE:
+		case HDIO_GET_BUSSTATE:
+		case HDIO_GET_QDMA:
+		case HDIO_GET_MULTCOUNT:
+		case HDIO_GET_KEEPSETTINGS:
+		case HDIO_GET_32BIT:
+		case HDIO_GET_NOWERR:
+		case HDIO_GET_DMA:
+		case HDIO_GET_WCACHE:
+		case HDIO_GET_ACOUSTIC:
+		case HDIO_GET_ADDRESS:
+			rsbac_request = R_GET_STATUS_DATA;
+			break;
+
+		default:
+			rsbac_request = R_MODIFY_SYSTEM_DATA;
+	}
+
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(bdev->bd_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(bdev->bd_dev);
+
+	rsbac_attribute_value.ioctl_cmd = cmd;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_ioctl_cmd,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	switch(cmd) {
 	case BLKFLSBUF:
 		if (!capable(CAP_SYS_ADMIN))
diff --git a/block/ioprio.c b/block/ioprio.c
index 5634356..0cddcee 100644
--- a/block/ioprio.c
+++ b/block/ioprio.c
@@ -27,6 +27,7 @@
 #include <linux/capability.h>
 #include <linux/syscalls.h>
 #include <linux/security.h>
+#include <rsbac/hooks.h>
 #include <linux/pid_namespace.h>
 
 int set_task_ioprio(struct task_struct *task, int ioprio)
@@ -68,6 +69,26 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
 	kuid_t uid;
 	int ret;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_priority;
+	rsbac_attribute_value.priority = ioprio;
+
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_priority,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	switch (class) {
 		case IOPRIO_CLASS_RT:
 			if (!capable(CAP_SYS_ADMIN))
@@ -145,6 +166,27 @@ static int get_task_ioprio(struct task_struct *p)
 {
 	int ret;
 
+#ifdef CONFIG_RSBAC
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+        rsbac_pr_debug(aef, "calling ADF\n");
+        rsbac_target_id.scd = ST_priority;
+        rsbac_attribute_value.dummy = 0;
+
+        if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                                task_pid(current),
+                                T_SCD,
+                                rsbac_target_id,
+                                A_none,
+                                rsbac_attribute_value)) {
+                ret = -EPERM;
+                goto out;
+        }
+#endif
+
 	ret = security_task_getioprio(p);
 	if (ret)
 		goto out;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 53d22cc..daace37 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -80,6 +80,8 @@
 
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 static DEFINE_IDR(loop_index_idr);
 static DEFINE_MUTEX(loop_index_mutex);
 
@@ -680,6 +682,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	int		error;
 	loff_t		size;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* This is safe, since we have a reference from open(). */
 	__module_get(THIS_MODULE);
 
@@ -726,6 +734,47 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 	size = get_loop_size(lo, file);
 	if ((loff_t)(sector_t)size != size)
 		goto out_putf;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[lo_ioctl()]: calling ADF for FILE/DEV\n");
+	if (S_ISREG(inode->i_mode)) {
+		rsbac_target = T_FILE;
+		rsbac_target_id.dir.device = file->f_path.dentry->d_sb->s_dev;
+		rsbac_target_id.dir.inode  = inode->i_ino;
+		rsbac_target_id.dir.dentry_p = file->f_path.dentry;
+	}
+	else { /* must be block */
+		rsbac_target = T_DEV;
+		rsbac_target_id.dev.type = D_block;
+		rsbac_target_id.dev.major = RSBAC_MAJOR(inode->i_rdev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(inode->i_rdev);
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out_putf;
+	}
+	rsbac_pr_debug(aef, "[lo_ioctl()]: calling ADF for DEV\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(bdev->bd_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(bdev->bd_dev);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out_putf;
+	}
+#endif
+
 	error = -ENOMEM;
 	lo->wq = alloc_workqueue("kloopd%d",
 			WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16,
@@ -821,6 +870,12 @@ static int loop_clr_fd(struct loop_device *lo)
 	gfp_t gfp = lo->old_gfp_mask;
 	struct block_device *bdev = lo->lo_device;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
 
@@ -843,6 +898,44 @@ static int loop_clr_fd(struct loop_device *lo)
 	if (filp == NULL)
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[lo_ioctl()]: calling ADF for FILE/DEV\n");
+	if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) {
+		rsbac_target = T_FILE;
+		rsbac_target_id.dir.device = filp->f_path.dentry->d_sb->s_dev;
+		rsbac_target_id.dir.inode  = filp->f_path.dentry->d_inode->i_ino;
+		rsbac_target_id.dir.dentry_p = filp->f_path.dentry;
+	}
+	else { /* must be block dev */
+		rsbac_target = T_DEV;
+		rsbac_target_id.dev.type = D_block;
+		rsbac_target_id.dev.major = RSBAC_MAJOR(filp->f_path.dentry->d_inode->i_rdev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(filp->f_path.dentry->d_inode->i_rdev);
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_UMOUNT,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+	rsbac_pr_debug(aef, "[lo_ioctl()]: calling ADF for DEV\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = LOOP_MAJOR;
+	rsbac_target_id.dev.minor = lo->lo_number;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_UMOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_state = Lo_rundown;
 	lo->lo_backing_file = NULL;
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 2898d19..2c053ac 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -36,6 +36,8 @@
 
 #define DEVPORT_MINOR	4
 
+#include <rsbac/hooks.h>
+
 static inline unsigned long size_inside_page(unsigned long start,
 					     unsigned long size)
 {
@@ -110,6 +112,11 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 	ssize_t read, sz;
 	void *ptr;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (p != *ppos)
 		return 0;
 
@@ -144,6 +151,25 @@ static ssize_t read_mem(struct file *file, char __user *buf,
 			/* Show zeros for restricted memory. */
 			remaining = clear_user(buf, sz);
 		} else {
+#ifdef CONFIG_RSBAC
+			rsbac_attribute_value.pagenr = p >> PAGE_SHIFT;
+			if (rsbac_is_videomem(rsbac_attribute_value.pagenr, count))
+				rsbac_target_id.scd = ST_videomem;
+			else
+				rsbac_target_id.scd = ST_kmem;
+			rsbac_pr_debug(aef, "calling ADF\n");
+			if (!rsbac_adf_request(R_GET_STATUS_DATA,
+						task_pid(current),
+						T_SCD,
+						rsbac_target_id,
+						A_pagenr,
+						rsbac_attribute_value)) {
+				rsbac_printk(KERN_INFO "read_mem(): RSBAC denied read access to kernel mem page %u, size %u\n",
+						rsbac_attribute_value.pagenr, count);
+				return -EPERM;
+			}
+#endif
+
 			/*
 			 * On ia64 if a page has been mapped somewhere as
 			 * uncached, then it must also be accessed uncached
@@ -179,6 +205,11 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
 	unsigned long copied;
 	void *ptr;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (p != *ppos)
 		return -EFBIG;
 
@@ -210,6 +241,25 @@ static ssize_t write_mem(struct file *file, const char __user *buf,
 
 		/* Skip actual writing when a page is marked as restricted. */
 		if (allowed == 1) {
+#ifdef CONFIG_RSBAC
+			rsbac_attribute_value.pagenr = p >> PAGE_SHIFT;
+			if (rsbac_is_videomem(rsbac_attribute_value.pagenr, sz))
+				rsbac_target_id.scd = ST_videomem;
+			else
+				rsbac_target_id.scd = ST_kmem;
+			rsbac_pr_debug(aef, "calling ADF\n");
+			if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+						task_pid(current),
+						T_SCD,
+						rsbac_target_id,
+						A_pagenr,
+						rsbac_attribute_value)) {
+				rsbac_printk(KERN_INFO "write_mem(): RSBAC denied write access to kernel mem page %u, size %u\n",
+						rsbac_attribute_value.pagenr, sz);
+				return -EPERM;
+			}
+#endif
+
 			/*
 			 * On ia64 if a page has been mapped somewhere as
 			 * uncached, then it must also be accessed uncached
@@ -345,6 +395,11 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 	size_t size = vma->vm_end - vma->vm_start;
 	phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* It's illegal to wrap around the end of the physical address space. */
 	if (offset + (phys_addr_t)size - 1 < offset)
 		return -EINVAL;
@@ -362,6 +417,25 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma)
 						&vma->vm_page_prot))
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	rsbac_attribute_value.pagenr = vma->vm_pgoff;
+	if (rsbac_is_videomem(rsbac_attribute_value.pagenr, size))
+		rsbac_target_id.scd = ST_videomem;
+	else
+		rsbac_target_id.scd = ST_kmem;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_pagenr,
+				rsbac_attribute_value)) {
+		rsbac_printk(KERN_INFO "mmap_mem(): RSBAC denied mmap access to kernel mem page %u, size %u\n",
+				rsbac_attribute_value.pagenr, size);
+		return -EPERM;
+	}
+#endif
+
 	vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
 						 size,
 						 vma->vm_page_prot);
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c
index 6233fa2c..08b711b 100644
--- a/drivers/ide/ide-ioctls.c
+++ b/drivers/ide/ide-ioctls.c
@@ -6,6 +6,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/slab.h>
+#include <rsbac/hooks.h>
 
 static const struct ide_ioctl_devset ide_ioctl_settings[] = {
 { HDIO_GET_32BIT,	 HDIO_SET_32BIT,	&ide_devset_io_32bit  },
@@ -236,6 +237,58 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,
 {
 	int err;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	/* values taken from include/linux/fs.h and hdreg.h */
+	switch (cmd) {
+		case BLKGETSIZE:   /* Return device size */
+		case BLKGETSIZE64:
+		case BLKROGET:
+		case BLKRAGET:
+		case BLKFRAGET:
+		case BLKSECTGET:
+		case BLKSSZGET:
+		case BLKBSZGET:
+		case HDIO_GETGEO:
+		case HDIO_OBSOLETE_IDENTITY:
+		case HDIO_GET_UNMASKINTR:
+		case HDIO_GET_IDENTITY:
+		case HDIO_GET_NICE:
+		case HDIO_GET_BUSSTATE:
+		case HDIO_GET_QDMA:
+		case HDIO_GET_MULTCOUNT:
+		case HDIO_GET_KEEPSETTINGS:
+		case HDIO_GET_32BIT:
+		case HDIO_GET_NOWERR:
+		case HDIO_GET_DMA:
+		case HDIO_GET_WCACHE:
+		case HDIO_GET_ACOUSTIC:
+		case HDIO_GET_ADDRESS:
+			rsbac_request = R_GET_STATUS_DATA;
+			break;
+
+		default:
+			rsbac_request = R_MODIFY_SYSTEM_DATA;
+	}
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(bdev->bd_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(bdev->bd_dev);
+	rsbac_attribute_value.ioctl_cmd = cmd;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_ioctl_cmd,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
 	if (err != -EOPNOTSUPP)
 		return err;
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 9c27ee0..08e90a3 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -51,6 +51,11 @@
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
 
+#ifdef CONFIG_RSBAC
+#include <rsbac/types.h>
+#include <rsbac/debug.h>
+#endif
+
 /* Whether we react on sysrq keys or just ignore them */
 static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
 static bool __read_mostly sysrq_always_enabled;
@@ -196,6 +201,24 @@ static struct sysrq_key_op sysrq_mountro_op = {
 	.enable_mask	= SYSRQ_ENABLE_REMOUNT,
 };
 
+#ifdef CONFIG_RSBAC_SOFTMODE_SYSRQ
+static void sysrq_handle_rsbac_softmode(int key) {
+	if (rsbac_softmode) {
+		rsbac_printk(KERN_WARNING "Soft mode disabled via SysRq!\n");
+		rsbac_softmode = 0;
+	}
+	else {
+		rsbac_printk(KERN_WARNING "Soft mode enabled via SysRq!\n");
+		rsbac_softmode = 1;
+	}
+}
+static struct sysrq_key_op sysrq_rsbac_softmode_op = {
+	handler:	sysrq_handle_rsbac_softmode,
+	help_msg:	"rsbac_toggle_softmode_X",
+	action_msg:	"RSBAC toggle softmode\n",
+};
+#endif
+
 #ifdef CONFIG_LOCKDEP
 static void sysrq_handle_showlocks(int key)
 {
@@ -473,7 +496,11 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
 	&sysrq_showstate_blocked_op,	/* w */
 	/* x: May be registered on ppc/powerpc for xmon */
 	/* x: May be registered on sparc64 for global PMU dump */
+#ifdef CONFIG_RSBAC_SOFTMODE_SYSRQ
+	&sysrq_rsbac_softmode_op,	/* x */
+#else
 	NULL,				/* x */
+#endif
 	/* y: May be registered on sparc64 for global register dump */
 	NULL,				/* y */
 	&sysrq_ftrace_dump_op,		/* z */
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 152cd36..4f0ff71 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -105,6 +105,8 @@
 #include <linux/kmod.h>
 #include <linux/nsproxy.h>
 
+#include <rsbac/hooks.h>
+
 #undef TTY_DEBUG_HANGUP
 
 #define TTY_PARANOIA_CHECK 1
@@ -2296,10 +2298,33 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
 	char ch, mbz = 0;
 	struct tty_ldisc *ld;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	if (get_user(ch, p))
 		return -EFAULT;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dev.type = D_char;
+	rsbac_target_id.dev.major = tty->driver->major;
+	rsbac_target_id.dev.minor = tty->driver->minor_start + tty->index;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_SEND,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	tty_audit_tiocsti(tty, ch);
 	ld = tty_ldisc_ref_wait(tty);
 	ld->ops->receive_buf(tty, &ch, &mbz, 1);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 7bbf86b..f5e9adf 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -24,6 +24,8 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 #undef TTY_DEBUG_WAIT_UNTIL_SENT
 
 #undef	DEBUG
@@ -938,14 +940,57 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 	int ret = 0;
 	struct ktermios kterm;
 
-	BUG_ON(file == NULL);
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
+	BUG_ON(file == NULL);
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver->subtype == PTY_TYPE_MASTER)
 		real_tty = tty->link;
 	else
 		real_tty = tty;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	switch (cmd) {
+#ifdef TIOCGETP
+		case TIOCGETP:
+#endif
+#ifdef TIOCGETC
+		case TIOCGETC:
+#endif
+#ifdef TIOCGLTC
+		case TIOCGLTC:
+#endif
+		case TCGETS:
+		case TCGETA:
+		case TIOCOUTQ:
+		case TIOCINQ:
+		case TIOCGLCKTRMIOS:
+		case TIOCGSOFTCAR:
+			rsbac_request = R_GET_PERMISSIONS_DATA;
+			break;
+		default:
+			rsbac_request = R_MODIFY_PERMISSIONS_DATA;
+	}
+	rsbac_target_id.dev.type = D_char;
+	rsbac_target_id.dev.major = tty->driver->major;
+	rsbac_target_id.dev.minor = tty->driver->minor_start + tty->index;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	switch (cmd) {
 #ifdef TIOCGETP
 	case TIOCGETP:
diff --git a/fs/dcache.c b/fs/dcache.c
index c19576f..7f38116 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1425,7 +1425,7 @@ static enum d_walk_ret umount_check(void *_data, struct dentry *dentry)
 	if (dentry == _data && dentry->d_lockref.count == 1)
 		return D_WALK_CONTINUE;
 
-	printk(KERN_ERR "BUG: Dentry %p{i=%lx,n=%pd} "
+	printk(KERN_CRIT "BUG: Dentry %p{i=%lx,n=%pd} "
 			" still in use (%d) [unmount of %s %s]\n",
 		       dentry,
 		       dentry->d_inode ?
diff --git a/fs/exec.c b/fs/exec.c
index 3ba35c2..6994014 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -66,6 +66,8 @@
 
 #include <trace/events/sched.h>
 
+#include <rsbac/hooks.h>
+
 int suid_dumpable = 0;
 
 static LIST_HEAD(formats);
@@ -118,6 +120,11 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 		.lookup_flags = LOOKUP_FOLLOW,
 	};
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (IS_ERR(tmp))
 		goto out;
 
@@ -131,10 +138,36 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 	if (!S_ISREG(file_inode(file)->i_mode))
 		goto exit;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(file->f_path.dentry))
+		error = 0;
+	else
+#endif
 	error = -EACCES;
 	if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
 		goto exit;
 
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.file.device = file->f_path.dentry->d_inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = file->f_path.dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = file->f_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MAP_EXEC,
+				task_pid(current),
+				T_FILE,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		rsbac_pr_debug(aef, "request not granted, my PID: %i\n",
+			       task_pid(current));
+		error = -EPERM;
+		goto exit;
+	}
+#endif
+
 	fsnotify_open(file);
 
 	error = -ENOEXEC;
@@ -154,6 +187,28 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 	}
 	read_unlock(&binfmt_lock);
 exit:
+
+	/* RSBAC: notify ADF of mapped segment */
+#ifdef CONFIG_RSBAC
+	if (!error) {
+		union rsbac_target_id_t rsbac_new_target_id;
+
+		rsbac_pr_debug(aef, "calling ADF_set_attr\n");
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_MAP_EXEC,
+					task_pid(current),
+					T_FILE,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_uselib(): rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 	fput(file);
 out:
   	return error;
@@ -801,6 +856,13 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
 	if (file->f_path.mnt->mnt_flags & MNT_NOEXEC)
 		goto exit;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(file->f_path.dentry))
+		err = 0;
+	else
+#endif
+
+
 	err = deny_write_access(file);
 	if (err)
 		goto exit;
@@ -1513,6 +1575,12 @@ static int do_execveat_common(int fd, struct filename *filename,
 	struct files_struct *displaced;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (IS_ERR(filename))
 		return PTR_ERR(filename);
 
@@ -1591,6 +1659,25 @@ static int do_execveat_common(int fd, struct filename *filename,
 	if ((retval = bprm->envc) < 0)
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_execve()]: calling ADF\n");
+	rsbac_target_id.file.device = file->f_path.dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = file->f_path.dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = file->f_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_EXECUTE,
+				task_pid(current),
+				T_FILE,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		rsbac_pr_debug(aef, "[sys_execve()]: request not granted, my PID: %i\n",
+				task_pid(current));
+		retval = -EPERM;
+		goto out;
+	}
+#endif
+
 	retval = prepare_binprm(bprm);
 	if (retval < 0)
 		goto out;
@@ -1612,6 +1699,25 @@ static int do_execveat_common(int fd, struct filename *filename,
 	if (retval < 0)
 		goto out;
 
+/* RSBAC: notify ADF of changed program in this process
+ * Most structures are already filled
+ */
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_execve()]: calling ADF_set_attr\n");
+	rsbac_new_target_id.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_EXECUTE,
+					task_pid(current),
+					T_FILE,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+			"do_execve() [sys_execve]: rsbac_adf_set_attr() returned error\n");
+	}
+#endif
+
 	/* execve succeeded */
 	current->fs->in_exec = 0;
 	current->in_execve = 0;
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index 5d46c09..0ae70c1 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -16,6 +16,10 @@
 #include <asm/current.h>
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_RSBAC
+#include <net/sock.h>
+#include <rsbac/hooks.h>
+#endif
 
 long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
@@ -25,6 +29,73 @@ long ext2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	unsigned short rsv_window_size;
 	int ret;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request;
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	switch (cmd) {
+		case EXT2_IOC_GETFLAGS:
+		case EXT2_IOC_GETVERSION:
+			rsbac_request = R_GET_PERMISSIONS_DATA;
+			break;
+		case EXT2_IOC_SETFLAGS:
+		case EXT2_IOC_SETVERSION:
+			rsbac_request = R_MODIFY_PERMISSIONS_DATA;
+			break;
+		default:
+			rsbac_request = R_NONE;
+	}
+	if(S_ISSOCK(inode->i_mode)) {
+		if(SOCKET_I(inode)->ops
+				&& (SOCKET_I(inode)->ops->family == AF_UNIX)) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = filp->f_path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = filp->f_path.dentry;
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p
+				= SOCKET_I(inode);
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+	}
+	else {
+		if (S_ISDIR(inode->i_mode))
+			rsbac_target = T_DIR;
+		else if (S_ISFIFO(inode->i_mode))
+			rsbac_target = T_FIFO;
+		else if (S_ISLNK(inode->i_mode))
+			rsbac_target = T_SYMLINK;
+		else
+			rsbac_target = T_FILE;
+		rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+		rsbac_target_id.file.inode  = inode->i_ino;
+		rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	}
+	rsbac_attribute_value.ioctl_cmd = cmd;
+	if(   (rsbac_request != R_NONE)
+			&& !rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_ioctl_cmd,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	ext2_debug ("cmd = %u, arg = %lu\n", cmd, arg);
 
 	switch (cmd) {
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3e074a9..294277a 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -36,6 +36,8 @@
 #include "xattr.h"
 #include "acl.h"
 
+#include <rsbac/hooks.h>
+
 static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
 {
 	int err = ext2_add_link(dentry, inode);
@@ -290,6 +292,11 @@ static int ext2_unlink(struct inode * dir, struct dentry *dentry)
 	if (err)
 		goto out;
 
+#ifdef CONFIG_RSBAC_SECDEL
+	if (inode->i_nlink == 1)
+		rsbac_sec_del(dentry, TRUE);
+#endif
+
 	inode->i_ctime = dir->i_ctime;
 	inode_dec_link_count(inode);
 	err = 0;
@@ -350,6 +357,12 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry,
 		new_de = ext2_find_entry (new_dir, &new_dentry->d_name, &new_page);
 		if (!new_de)
 			goto out_dir;
+
+#ifdef CONFIG_RSBAC_SECDEL
+		if (new_inode->i_nlink == 1)
+			rsbac_sec_del(new_dentry, TRUE);
+#endif
+
 		ext2_set_link(new_dir, new_de, new_page, old_inode, 1);
 		new_inode->i_ctime = CURRENT_TIME_SEC;
 		if (dir_de)
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 4d96e9a..db5ead2 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -12,6 +12,11 @@
 #include <asm/uaccess.h>
 #include "ext3.h"
 
+#ifdef CONFIG_RSBAC
+#include <net/sock.h>
+#include <rsbac/hooks.h>
+#endif
+
 long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
@@ -19,6 +24,83 @@ long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	unsigned int flags;
 	unsigned short rsv_window_size;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request;
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	switch (cmd) {
+#ifdef CONFIG_JBD_DEBUG
+		case EXT3_IOC_WAIT_FOR_READONLY:
+#endif
+		case EXT3_IOC_GETFLAGS:
+		case EXT3_IOC_GETVERSION:
+		case EXT3_IOC_GETVERSION_OLD:
+		case EXT3_IOC_GETRSVSZ:
+			rsbac_request = R_GET_PERMISSIONS_DATA;
+			break;
+		case EXT3_IOC_SETFLAGS:
+		case EXT3_IOC_SETVERSION:
+		case EXT3_IOC_SETVERSION_OLD:
+		case EXT3_IOC_SETRSVSZ:
+		case EXT3_IOC_GROUP_EXTEND:
+		case EXT3_IOC_GROUP_ADD:
+			rsbac_request = R_MODIFY_PERMISSIONS_DATA;
+			break;
+		default:
+			rsbac_request = R_NONE;
+	}
+	if(S_ISSOCK(inode->i_mode)) {
+		if(SOCKET_I(inode)->ops
+				&& (SOCKET_I(inode)->ops->family == AF_UNIX)) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = filp->f_path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = filp->f_path.dentry;
+
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p
+				= SOCKET_I(inode);
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+	}
+	else {
+		if (S_ISDIR(inode->i_mode))
+			rsbac_target = T_DIR;
+		else if (S_ISFIFO(inode->i_mode))
+			rsbac_target = T_FIFO;
+		else if (S_ISLNK(inode->i_mode))
+			rsbac_target = T_SYMLINK;
+		else
+			rsbac_target = T_FILE;
+		rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+		rsbac_target_id.file.inode  = inode->i_ino;
+		rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	}
+	rsbac_attribute_value.ioctl_cmd = cmd;
+	if(   (rsbac_request != R_NONE)
+			&& !rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_ioctl_cmd,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);
 
 	switch (cmd) {
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 4264b9b..437baff 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -30,6 +30,8 @@
 #include "xattr.h"
 #include "acl.h"
 
+#include <rsbac/hooks.h>
+
 /*
  * define how far ahead to read directories while searching them.
  */
@@ -2189,6 +2191,19 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 
 	inode = d_inode(dentry);
 
+#ifdef CONFIG_RSBAC_SECDEL
+	if(inode->i_nlink == 1) {
+		ext3_journal_stop(handle);
+		rsbac_sec_del(dentry, TRUE);
+		handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
+		if (IS_ERR(handle))
+			return PTR_ERR(handle);
+
+		if (IS_DIRSYNC(dir))
+			handle->h_sync = 1;
+	}
+#endif
+
 	retval = -EIO;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
 		goto end_unlink;
@@ -2444,6 +2459,22 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
 		if (retval)
 			goto end_rename;
 	} else {
+
+#ifdef CONFIG_RSBAC_SECDEL
+	if (new_inode->i_nlink == 1) {
+			ext3_journal_stop(handle);
+			rsbac_sec_del(new_dentry, TRUE);
+			handle = ext3_journal_start(old_dir, 2 *
+					EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
+					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
+			if (IS_ERR(handle))
+				return PTR_ERR(handle);
+
+			if (IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir))
+				handle->h_sync = 1;
+	}
+#endif
+
 		BUFFER_TRACE(new_bh, "get write access");
 		retval = ext3_journal_get_write_access(handle, new_bh);
 		if (retval)
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index dbe1ff5..db113bf 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -206,6 +206,11 @@ static int uuid_is_zero(__u8 u[16])
 	return 1;
 }
 
+#ifdef CONFIG_RSBAC
+#include <net/sock.h>
+#endif
+#include <rsbac/hooks.h>
+
 long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct inode *inode = file_inode(filp);
@@ -213,6 +218,77 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	struct ext4_inode_info *ei = EXT4_I(inode);
 	unsigned int flags;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request;
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	switch (cmd) {
+		case EXT4_IOC_GETFLAGS:
+		case EXT4_IOC_GETVERSION:
+		case EXT4_IOC_GETVERSION_OLD:
+		case EXT4_IOC_GETRSVSZ:
+			rsbac_request = R_GET_PERMISSIONS_DATA;
+			break;
+		case EXT4_IOC_SETFLAGS:
+		case EXT4_IOC_SETVERSION:
+		case EXT4_IOC_SETVERSION_OLD:
+		case EXT4_IOC_SETRSVSZ:
+		case EXT4_IOC_GROUP_EXTEND:
+		case EXT4_IOC_GROUP_ADD:
+		case EXT4_IOC_MIGRATE:
+			rsbac_request = R_MODIFY_PERMISSIONS_DATA;
+			break;
+		default:
+			rsbac_request = R_NONE;
+	}
+	if(S_ISSOCK(inode->i_mode)) {
+		if(SOCKET_I(inode)->ops
+				&& (SOCKET_I(inode)->ops->family == AF_UNIX)) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = filp->f_path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = filp->f_path.dentry;
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p
+				= SOCKET_I(inode);
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+		}
+	else {
+		if (S_ISDIR(inode->i_mode))
+			rsbac_target = T_DIR;
+		else if (S_ISFIFO(inode->i_mode))
+			rsbac_target = T_FIFO;
+		else if (S_ISLNK(inode->i_mode))
+			rsbac_target = T_SYMLINK;
+		else
+			rsbac_target = T_FILE;
+		rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+		rsbac_target_id.file.inode  = inode->i_ino;
+		rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	}
+	rsbac_attribute_value.ioctl_cmd = cmd;
+	if(   (rsbac_request != R_NONE)
+		&& !rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_ioctl_cmd,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	ext4_debug("cmd = %u, arg = %lu\n", cmd, arg);
 
 	switch (cmd) {
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index aa33db8..f932d4a 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -40,6 +40,9 @@
 #include "acl.h"
 
 #include <trace/events/ext4.h>
+
+#include <rsbac/hooks.h>
+
 /*
  * define how far ahead to read directories while searching them.
  */
@@ -3018,6 +3021,12 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
 
 	inode = d_inode(dentry);
 
+#ifdef CONFIG_RSBAC_SECDEL
+        if(inode->i_nlink == 1) {
+                rsbac_sec_del(dentry, TRUE);
+        }
+#endif
+
 	retval = -EIO;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
 		goto end_rmdir;
@@ -3677,8 +3686,21 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 		if (retval)
 			goto end_rename;
 	} else {
+
+#ifdef CONFIG_RSBAC_SECDEL
+		if(new.inode->i_nlink == 1) {
+			ext4_journal_stop(handle);
+			rsbac_sec_del(new.dentry, TRUE);
+			handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits);
+			if (IS_ERR(handle))
+				return PTR_ERR(handle);
+			if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir))
+				ext4_handle_sync(handle);
+		}
+#endif
+
 		retval = ext4_setent(handle, &new,
-				     old.inode->i_ino, old_file_type);
+				old.inode->i_ino, old_file_type);
 		if (retval)
 			goto end_rename;
 	}
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index b7e2b33..dbd7c1a 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/module.h>
+#include <rsbac/hooks.h>
 #include "fat.h"
 
 /* Characters that are undesirable in an MS-DOS file name */
@@ -418,6 +419,9 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry)
 	clear_nlink(inode);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	fat_detach(inode);
+#ifdef CONFIG_RSBAC_SECDEL
+        rsbac_sec_del(dentry, TRUE);
+#endif
 out:
 	mutex_unlock(&MSDOS_SB(sb)->s_lock);
 	if (!err)
@@ -510,6 +514,11 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 	}
 	new_dir->i_version++;
 
+#ifdef CONFIG_RSBAC_SECDEL
+        if (new_inode && (new_inode->i_nlink == 1))
+		rsbac_sec_del(new_dentry, TRUE);
+#endif
+
 	fat_detach(old_inode);
 	fat_attach(old_inode, new_i_pos);
 	if (is_hid)
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 7092584..ffe4bc8 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -19,6 +19,7 @@
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/namei.h>
+#include <rsbac/hooks.h>
 #include "fat.h"
 
 /*
@@ -843,6 +844,10 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
 	if (err)
 		goto out;
 
+#ifdef CONFIG_RSBAC_SECDEL
+        rsbac_sec_del(dentry, TRUE);
+#endif
+
 	err = fat_remove_entries(dir, &sinfo);	/* and releases bh */
 	if (err)
 		goto out;
@@ -938,6 +943,11 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 			if (err)
 				goto out;
 		}
+#ifdef CONFIG_RSBAC_SECDEL
+		else
+			if(new_inode->i_nlink == 1)
+				rsbac_sec_del(new_dentry, TRUE);
+#endif
 		new_i_pos = MSDOS_I(new_inode)->i_pos;
 		fat_detach(new_inode);
 	} else {
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 5d01d26..de98eeb 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -18,6 +18,11 @@
 
 #include <asm/ioctls.h>
 
+#ifdef CONFIG_RSBAC_IOCTL
+#include <net/sock.h>
+#endif
+#include <rsbac/hooks.h>
+
 /* So that the fiemap access checks can't overflow on 32 bit machines. */
 #define FIEMAP_MAX_EXTENTS	(UINT_MAX / sizeof(struct fiemap_extent))
 
@@ -37,9 +42,78 @@ static long vfs_ioctl(struct file *filp, unsigned int cmd,
 {
 	int error = -ENOTTY;
 
+#ifdef CONFIG_RSBAC_IOCTL
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!filp->f_op->unlocked_ioctl)
 		goto out;
 
+#ifdef CONFIG_RSBAC_IOCTL
+	if (S_ISBLK(filp->f_path.dentry->d_inode->i_mode)) {
+		rsbac_target = T_DEV;
+		rsbac_target_id.dev.type = D_block;
+		rsbac_target_id.dev.major = RSBAC_MAJOR(filp->f_path.dentry->d_inode->i_rdev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(filp->f_path.dentry->d_inode->i_rdev);
+	}
+	else
+		if (S_ISCHR(filp->f_path.dentry->d_inode->i_mode)) {
+			rsbac_target = T_DEV;
+			rsbac_target_id.dev.type = D_char;
+			rsbac_target_id.dev.major = RSBAC_MAJOR(filp->f_path.dentry->d_inode->i_rdev);
+			rsbac_target_id.dev.minor = RSBAC_MINOR(filp->f_path.dentry->d_inode->i_rdev);
+		}
+		else
+			if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode)) {
+				if (   SOCKET_I(filp->f_path.dentry->d_inode)->ops
+						&& (SOCKET_I(filp->f_path.dentry->d_inode)->ops->family == AF_UNIX)
+				  ) {
+					if (filp->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+						rsbac_target = T_IPC;
+						rsbac_target_id.ipc.type = I_anonunix;
+						rsbac_target_id.ipc.id.id_nr = filp->f_path.dentry->d_inode->i_ino;
+					}
+					else {
+						rsbac_target = T_UNIXSOCK;
+						rsbac_target_id.unixsock.device = filp->f_path.dentry->d_sb->s_dev;
+						rsbac_target_id.unixsock.inode  = filp->f_path.dentry->d_inode->i_ino;
+						rsbac_target_id.unixsock.dentry_p = filp->f_path.dentry;
+					}
+				}
+				else {
+#ifdef CONFIG_RSBAC_NET_OBJ
+					rsbac_target = T_NETOBJ;
+					rsbac_target_id.netobj.sock_p
+						= SOCKET_I(filp->f_path.dentry->d_inode);
+					rsbac_target_id.netobj.local_addr = NULL;
+					rsbac_target_id.netobj.local_len = 0;
+					rsbac_target_id.netobj.remote_addr = NULL;
+					rsbac_target_id.netobj.remote_len = 0;
+#else
+					rsbac_target = T_NONE;
+#endif
+				}
+			}
+			else
+				rsbac_target = T_NONE;
+	if (rsbac_target != T_NONE) {
+		rsbac_pr_debug(aef, "[sys_ioctl()]: calling ADF\n");
+		rsbac_attribute_value.ioctl_cmd = cmd;
+		if (!rsbac_adf_request(R_IOCTL,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_ioctl_cmd,
+					rsbac_attribute_value))
+		{
+			error = -EPERM;
+			goto out;
+		}
+	}
+#endif
+
 	error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
 	if (error == -ENOIOCTLCMD)
 		error = -ENOTTY;
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 4ddcaf9..ded1308 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -2389,6 +2389,11 @@ int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode)
 		return -EROFS;
 	journal = transaction->t_journal;
 
+#ifdef CONFIG_RSBAC
+	if (!jinode)
+		return 0;
+#endif
+
 	jbd_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
 			transaction->t_tid);
 
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 66db7bc..a791b47 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -33,6 +33,8 @@
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
+#include <rsbac/hooks.h>
+
 /*
  * forward references
  */
@@ -489,6 +491,12 @@ static int jfs_unlink(struct inode *dip, struct dentry *dentry)
 	if ((rc = get_UCSname(&dname, dentry)))
 		goto out;
 
+	/* RSBAC jfs_unlink */
+#ifdef CONFIG_RSBAC_SECDEL
+	if(dentry->d_inode->i_nlink == 1)
+		rsbac_sec_del(dentry, TRUE);
+#endif
+
 	IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
 
 	tid = txBegin(dip->i_sb, 0);
@@ -1129,6 +1137,10 @@ static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			}
 		}
 	} else if (new_ip) {
+#ifdef CONFIG_RSBAC_SECDEL
+		if (new_ip->i_nlink == 1)
+			rsbac_sec_del(new_dentry, TRUE);
+#endif
 		IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL);
 		/* Init inode for quota operations. */
 		dquot_initialize(new_ip);
diff --git a/fs/locks.c b/fs/locks.c
index af6fcf6..46e8fc4 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -135,6 +135,8 @@
 
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 #define IS_POSIX(fl)	(fl->fl_flags & FL_POSIX)
 #define IS_FLOCK(fl)	(fl->fl_flags & FL_FLOCK)
 #define IS_LEASE(fl)	(fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
@@ -1900,6 +1902,12 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
 	int can_sleep, unlock;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = -EBADF;
 	if (!f.file)
 		goto out;
@@ -1925,6 +1933,38 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
 	if (error)
 		goto out_free;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target = T_FILE;
+        rsbac_target_id.file.device = f.file->f_path.dentry->d_sb->s_dev;
+        rsbac_target_id.file.inode  = f.file->f_path.dentry->d_inode->i_ino;
+        rsbac_target_id.file.dentry_p = f.file->f_path.dentry;
+	if (S_ISDIR(f.file->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(f.file->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(f.file->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+        else if (S_ISSOCK(f.file->f_path.dentry->d_inode->i_mode)) {
+          if(f.file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+            rsbac_target = T_IPC;
+            rsbac_target_id.ipc.type = I_anonunix;
+            rsbac_target_id.ipc.id.id_nr = f.file->f_path.dentry->d_inode->i_ino;
+          } else
+            rsbac_target = T_UNIXSOCK;
+        }
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_LOCK,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out_free;
+	}
+#endif
+
 	if (f.file->f_op->flock)
 		error = f.file->f_op->flock(f.file,
 					  (can_sleep) ? F_SETLKW : F_SETLK,
@@ -2000,6 +2040,12 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
 	struct flock flock;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = -EFAULT;
 	if (copy_from_user(&flock, l, sizeof(flock)))
 		goto out;
@@ -2021,6 +2067,32 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l)
 		file_lock.fl_owner = filp;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_fcntl()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = filp->f_path.dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out;
+	}
+#endif
+
 	error = vfs_test_lock(filp, &file_lock);
 	if (error)
 		goto out;
@@ -2134,6 +2206,12 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
 	struct file *f;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (file_lock == NULL)
 		return -ENOLCK;
 
@@ -2189,6 +2267,38 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
 		file_lock->fl_flags |= FL_SLEEP;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_fcntl()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode)) {
+		if(filp->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			rsbac_target_id.ipc.id.id_nr = filp->f_path.dentry->d_inode->i_ino;
+		} else
+			rsbac_target = T_UNIXSOCK;
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_LOCK,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out;
+	}
+#endif
+
 	error = do_lock_file_wait(filp, cmd, file_lock);
 
 	/*
@@ -2228,6 +2338,12 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
 	struct flock64 flock;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = -EFAULT;
 	if (copy_from_user(&flock, l, sizeof(flock)))
 		goto out;
@@ -2249,6 +2365,32 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l)
 		file_lock.fl_owner = filp;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_fcntl()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = filp->f_path.dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out;
+	}
+#endif
+
 	error = vfs_test_lock(filp, &file_lock);
 	if (error)
 		goto out;
@@ -2278,6 +2420,12 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
 	struct file *f;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (file_lock == NULL)
 		return -ENOLCK;
 
@@ -2333,6 +2481,38 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
 		file_lock->fl_flags |= FL_SLEEP;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_fcntl()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	rsbac_target_id.file.device = filp->f_path.dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode)) {
+		if(filp->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			rsbac_target_id.ipc.id.id_nr = filp->f_path.dentry->d_inode->i_ino;
+		} else
+			rsbac_target = T_UNIXSOCK;
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_LOCK,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto out;
+	}
+#endif
+
 	error = do_lock_file_wait(filp, cmd, file_lock);
 
 	/*
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index a795a11..da6bd58 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -6,6 +6,8 @@
 
 #include "minix.h"
 
+#include <rsbac/hooks.h>
+
 static int add_nondir(struct dentry *dentry, struct inode *inode)
 {
 	int err = minix_add_link(dentry, inode);
@@ -163,6 +165,11 @@ static int minix_unlink(struct inode * dir, struct dentry *dentry)
 	if (err)
 		goto end_unlink;
 
+#ifdef CONFIG_RSBAC_SECDEL
+	if (inode->i_nlink == 1)
+		rsbac_sec_del(dentry, TRUE);
+#endif
+
 	inode->i_ctime = dir->i_ctime;
 	inode_dec_link_count(inode);
 end_unlink:
@@ -218,6 +225,12 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
 		new_de = minix_find_entry(new_dentry, &new_page);
 		if (!new_de)
 			goto out_dir;
+
+#ifdef CONFIG_RSBAC_SECDEL
+		if (new_inode->i_nlink == 1)
+			rsbac_sec_del(new_dentry, TRUE);
+#endif
+
 		minix_set_link(new_de, new_page, old_inode);
 		new_inode->i_ctime = CURRENT_TIME_SEC;
 		if (dir_de)
diff --git a/fs/namei.c b/fs/namei.c
index 4d333d2..b1e35c0 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -36,6 +36,10 @@
 #include <linux/posix_acl.h>
 #include <linux/hash.h>
 #include <asm/uaccess.h>
+#ifdef CONFIG_RSBAC
+#include <rsbac/hooks.h>
+#include <linux/magic.h>
+#endif
 
 #include "internal.h"
 #include "mount.h"
@@ -404,6 +408,11 @@ int __inode_permission(struct inode *inode, int mask)
 {
 	int retval;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+	if (rsbac_dac_disable)
+	  return 0;
+#endif
+
 	if (unlikely(mask & MAY_WRITE)) {
 		/*
 		 * Nobody gets write access to an immutable file.
@@ -875,6 +884,11 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 	int error;
 	char *s;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	BUG_ON(nd->flags & LOOKUP_RCU);
 
 	if (link->mnt == nd->path.mnt)
@@ -894,6 +908,28 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 	if (error)
 		goto out_put_nd_path;
 
+#ifdef CONFIG_RSBAC
+	if (link->dentry->d_sb) {
+		rsbac_target_id.symlink.device = link->dentry->d_sb->s_dev;
+		rsbac_target_id.symlink.inode  = link->dentry->d_inode->i_ino;
+		rsbac_target_id.symlink.dentry_p = link->dentry;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_SEARCH,
+					task_pid(current),
+					T_SYMLINK,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+			error = -ENOENT;
+#else
+			error = -EPERM;
+#endif
+			goto out_put_nd_path;
+		}
+	}
+#endif
+
 	nd->last_type = LAST_BIND;
 	*p = dentry->d_inode->i_op->follow_link(dentry, nd);
 	error = PTR_ERR(*p);
@@ -917,6 +953,20 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
 			nd->flags |= LOOKUP_JUMPED;
 		}
 		nd->inode = nd->path.dentry->d_inode;
+
+#ifdef CONFIG_RSBAC_SYM_REDIR
+		if (S_ISLNK(dentry->d_inode->i_mode)) {
+			char * rsbac_name;
+
+			rsbac_name = rsbac_symlink_redirect(dentry->d_inode, s, PATH_MAX);
+			if (rsbac_name) {
+				error = link_path_walk(rsbac_name, nd);
+				kfree(rsbac_name);
+			} else {
+				error = link_path_walk(s, nd);
+			}
+		} else
+#endif
 		error = link_path_walk(s, nd);
 		if (unlikely(error))
 			put_link(nd, link, *p);
@@ -1434,6 +1484,11 @@ static int lookup_fast(struct nameidata *nd,
 	int status = 1;
 	int err;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/*
 	 * Rename seqlock is not required here because in the off chance
 	 * of a false negative due to a concurrent rename, we're going to
@@ -1512,6 +1567,31 @@ unlazy:
 	}
 	path->mnt = mnt;
 	path->dentry = dentry;
+
+#ifdef CONFIG_RSBAC
+	if (   dentry
+	    && dentry->d_inode
+	   ) {
+		rsbac_target_id.dir.device = dentry->d_inode->i_sb->s_dev;
+		rsbac_target_id.dir.inode  = dentry->d_inode->i_ino;
+		rsbac_target_id.dir.dentry_p = dentry;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_SEARCH,
+					task_pid(current),
+					T_DIR,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			path_put_conditional(path, nd);
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+			return -ENOENT;
+#else
+			return -EPERM;
+#endif
+		}
+	}
+#endif
+
 	err = follow_managed(path, nd->flags);
 	if (unlikely(err < 0)) {
 		path_put_conditional(path, nd);
@@ -1814,6 +1894,11 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 	struct path next;
 	int err;
 	
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	while (*name=='/')
 		name++;
 	if (!*name)
@@ -1824,9 +1909,39 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 		u64 hash_len;
 		int type;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+		if (rsbac_dac_part_disabled(nd->path.dentry))
+			err = 0;
+		else {
+#endif
 		err = may_lookup(nd);
  		if (err)
 			break;
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+		}
+#endif
+
+#ifdef CONFIG_RSBAC
+		if (nd->inode->i_sb) {
+			rsbac_target_id.dir.device = nd->inode->i_sb->s_dev;
+			rsbac_target_id.dir.inode  = nd->inode->i_ino;
+			rsbac_target_id.dir.dentry_p = nd->path.dentry;
+			rsbac_attribute_value.dummy = 0;
+			if (!rsbac_adf_request(R_SEARCH,
+						task_pid(current),
+						T_DIR,
+						rsbac_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+				err = -ENOENT;
+#else
+				err = -EPERM;
+#endif
+				break;
+			}
+		}
+#endif
 
 		hash_len = hash_name(name);
 
@@ -1885,6 +2000,24 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 			break;
 		}
 	}
+
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	if (!err && nd->inode->i_sb) {
+		rsbac_target_id.dir.device = nd->inode->i_sb->s_dev;
+		rsbac_target_id.dir.inode  = nd->inode->i_ino;
+		rsbac_target_id.dir.dentry_p = nd->path.dentry;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_SEARCH,
+					task_pid(current),
+					T_DIR,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			err = -ENOENT;
+		}
+	}
+#endif
+
 	terminate_walk(nd);
 	return err;
 }
@@ -2223,6 +2356,52 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
 }
 EXPORT_SYMBOL(lookup_one_len);
 
+/* RSBAC
+ * I hate to put new functions into this file, but even more I hate removing
+ * all statics from all the lookup helpers in here...
+ * Still, I need some form of RSBAC bypass for internal file access.
+ * Amon Ott <ao@rsbac.org>
+ */
+#ifdef CONFIG_RSBAC
+struct dentry *rsbac_lookup_one_len(const char *name, struct dentry *base, int len)
+{
+	struct qstr this;
+	unsigned int c;
+
+	WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex));
+
+	this.name = name;
+	this.len = len;
+	this.hash = full_name_hash(name, len);
+	if (!len)
+		return ERR_PTR(-EACCES);
+
+	if (unlikely(name[0] == '.')) {
+		if (len < 2 || (len == 2 && name[1] == '.'))
+			return ERR_PTR(-EACCES);
+	}
+
+	while (len--) {
+		c = *(const unsigned char *)name++;
+		if (c == '/' || c == '\0')
+			return ERR_PTR(-EACCES);
+	}
+	/*
+	 * See if the low-level filesystem might want
+	 * to use its own hash..
+	 */
+	if (base->d_flags & DCACHE_OP_HASH) {
+		int err = base->d_op->d_hash(base, &this);
+		if (err < 0)
+			return ERR_PTR(err);
+	}
+
+	return __lookup_hash(&this, base, 0);
+}
+
+EXPORT_SYMBOL(rsbac_lookup_one_len);
+#endif
+
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
 		 struct path *path, int *empty)
 {
@@ -2499,6 +2678,11 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir)
 	BUG_ON(victim->d_parent->d_inode != dir);
 	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(victim))
+		error = 0;
+	else
+#endif
 	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
 	if (error)
 		return error;
@@ -2537,6 +2721,12 @@ static inline int may_create(struct inode *dir, struct dentry *child)
 		return -EEXIST;
 	if (IS_DEADDIR(dir))
 		return -ENOENT;
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(child->d_parent))
+		return 0;
+	else
+#endif
 	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
 }
 
@@ -2588,6 +2778,15 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 		bool want_excl)
 {
 	int error = may_create(dir, dentry);
+
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	enum  rsbac_target_t rsbac_new_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (error)
 		return error;
 
@@ -2598,9 +2797,68 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 	error = security_inode_create(dir, dentry, mode);
 	if (error)
 		return error;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[open_namei() [filp_open() [do_open() [sys_open()]]]]: calling ADF\n");
+	rsbac_target = T_DIR;
+	rsbac_target_id.dir.device = dir->i_sb->s_dev;
+	rsbac_target_id.dir.inode  = dir->i_ino;
+	rsbac_target_id.dir.dentry_p = dentry->d_parent;
+	if (S_ISDIR(mode))
+		rsbac_attribute_value.create_data.target = T_DIR;
+	else if (S_ISSOCK(mode))
+		rsbac_attribute_value.create_data.target = T_UNIXSOCK;
+	else if (S_ISFIFO(mode))
+		rsbac_attribute_value.create_data.target = T_FIFO;
+	else
+		rsbac_attribute_value.create_data.target = T_FILE;
+	rsbac_attribute_value.create_data.dentry_p = dentry;
+	rsbac_attribute_value.create_data.mode = mode;
+	rsbac_attribute_value.create_data.device = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_create_data,
+				rsbac_attribute_value))
+		return -EPERM;
+#endif
+
 	error = dir->i_op->create(dir, dentry, mode, want_excl);
-	if (!error)
+	if (!error) {
+		/* RSBAC: notify ADF of new fs object */
+#ifdef CONFIG_RSBAC
+		if (dentry->d_inode) {
+			if (S_ISDIR(dentry->d_inode->i_mode))
+				rsbac_new_target = T_DIR;
+			else if (S_ISSOCK(dentry->d_inode->i_mode))
+				rsbac_new_target = T_UNIXSOCK;
+			else if (S_ISFIFO(dentry->d_inode->i_mode)) {
+				if (dentry->d_inode->i_sb->s_magic != PIPEFS_MAGIC)
+					rsbac_new_target = T_FIFO;
+				else
+					rsbac_new_target = T_NONE;
+			} else
+				rsbac_new_target = T_FILE;
+			rsbac_new_target_id.file.device = dentry->d_inode->i_sb->s_dev;
+			rsbac_new_target_id.file.inode  = dentry->d_inode->i_ino;
+			rsbac_new_target_id.file.dentry_p = dentry;
+			if (unlikely(rsbac_adf_set_attr(R_CREATE,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						rsbac_new_target,
+						rsbac_new_target_id,
+						A_create_data,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"vfs_create() [open_namei() [filp_open() [do_open() [sys_open()]]]]: rsbac_adf_set_attr() returned error");
+			}
+		}
+#endif
+
 		fsnotify_create(dir, dentry);
+	}
 	return error;
 }
 EXPORT_SYMBOL(vfs_create);
@@ -2636,6 +2894,12 @@ static int may_open(struct path *path, int acc_mode, int flag)
 		break;
 	}
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(dentry))
+		error = 0;
+	else
+#endif
+
 	error = inode_permission(inode, acc_mode);
 	if (error)
 		return error;
@@ -2727,6 +2991,14 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 	struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
 	bool excl;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	enum  rsbac_target_t rsbac_new_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	BUG_ON(dentry->d_inode);
 
 	/* Don't create child dentry for a dead directory. */
@@ -2779,6 +3051,31 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 				goto no_open;
 			open_flag &= ~O_CREAT;
 		}
+
+#ifdef CONFIG_RSBAC
+		else {
+			rsbac_pr_debug(aef, "atomic_open() [lookup_open() [do_last() [path_openat() [do_filp_open()]]]]: calling ADF\n");
+			rsbac_target = T_DIR;
+			rsbac_target_id.dir.device = dir->i_sb->s_dev;
+			rsbac_target_id.dir.inode  = dir->i_ino;
+			rsbac_target_id.dir.dentry_p = dentry->d_parent;
+			rsbac_attribute_value.create_data.target = T_FILE;
+			rsbac_attribute_value.create_data.dentry_p = dentry;
+			rsbac_attribute_value.create_data.mode = mode;
+			rsbac_attribute_value.create_data.device = 0;
+			if (!rsbac_adf_request(R_CREATE,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						A_create_data,
+						rsbac_attribute_value)) {
+				error = -EPERM;
+				create_error = -EPERM;
+				goto no_open;
+			}
+		}
+#endif
+
 	}
 
 	if (nd->flags & LOOKUP_DIRECTORY)
@@ -2834,6 +3131,27 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
 	if (error)
 		fput(file);
 
+	/* RSBAC: notify ADF of new file */
+#ifdef CONFIG_RSBAC
+	if (!error && (rsbac_target != T_NONE)) {
+		rsbac_new_target = T_FILE;
+		rsbac_new_target_id.file.device = dentry->d_sb->s_dev;
+		rsbac_new_target_id.file.inode  = dentry->d_inode->i_ino;
+		rsbac_new_target_id.file.dentry_p = dentry;
+		if (unlikely(rsbac_adf_set_attr(R_CREATE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_new_target,
+					rsbac_new_target_id,
+					A_create_data,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"atomic_open() [lookup_open() [do_last() [path_openat() [do_filp_open()]]]]: rsbac_adf_set_attr() returned error");
+		}
+	}
+#endif
+
 out:
 	dput(dentry);
 	return error;
@@ -2958,6 +3276,14 @@ static int do_last(struct nameidata *nd, struct path *path,
 	bool retried = false;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_adf_req = R_NONE;
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	nd->flags &= ~LOOKUP_PARENT;
 	nd->flags |= op->intent;
 
@@ -3122,6 +3448,67 @@ finish_open_created:
 	if (error)
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "do_last() [sys_open()]: calling ADF\n");
+	/* get target type and id clear */
+	if (S_ISBLK(nd->path.dentry->d_inode->i_mode) || S_ISCHR(nd->path.dentry->d_inode->i_mode)){
+		rsbac_target = T_DEV;
+		if (S_ISBLK(nd->path.dentry->d_inode->i_mode)) {
+			rsbac_target_id.dev.type = D_block;
+		}
+		else {
+			rsbac_target_id.dev.type = D_char;
+		}
+		rsbac_target_id.dev.major = RSBAC_MAJOR(nd->path.dentry->d_inode->i_rdev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(nd->path.dentry->d_inode->i_rdev);
+	}
+	else { /* must be file, dir or fifo */
+		if (S_ISDIR(nd->path.dentry->d_inode->i_mode))
+			rsbac_target = T_DIR;
+		else if (S_ISSOCK(nd->path.dentry->d_inode->i_mode))
+			rsbac_target = T_UNIXSOCK;
+		else if (S_ISFIFO(nd->path.dentry->d_inode->i_mode)) {
+			if (nd->path.dentry->d_inode->i_sb->s_magic != PIPEFS_MAGIC)
+				rsbac_target = T_FIFO;
+			else
+				rsbac_target = T_NONE;
+		}
+		else
+			rsbac_target = T_FILE;
+
+		rsbac_target_id.file.device = nd->path.dentry->d_inode->i_sb->s_dev;
+		rsbac_target_id.file.inode  = nd->path.dentry->d_inode->i_ino;
+		rsbac_target_id.file.dentry_p = nd->path.dentry;
+	}
+	/* determine request type */
+	rsbac_adf_req = R_NONE;
+	if (open_flag & O_APPEND)
+		rsbac_adf_req = R_APPEND_OPEN;
+	else
+		if ((open_flag & O_RDWR) || ((open_flag & O_WRONLY) && (open_flag & O_RDONLY)))
+			rsbac_adf_req = R_READ_WRITE_OPEN;
+		else
+			if (open_flag & O_WRONLY)
+				rsbac_adf_req = R_WRITE_OPEN;
+			else
+				if (rsbac_target == T_DIR)
+					rsbac_adf_req = R_READ;
+				else
+					rsbac_adf_req = R_READ_OPEN;
+	if ((rsbac_adf_req != R_NONE) && (rsbac_target != T_NONE)) {
+		rsbac_attribute_value.open_flag = open_flag;
+		if (!rsbac_adf_request(rsbac_adf_req,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_open_flag,
+					rsbac_attribute_value)) {
+			error = -EPERM;
+			goto out;
+		}
+	}
+#endif
+
 	BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
 	error = vfs_open(&nd->path, file, current_cred());
 	if (!error) {
@@ -3151,6 +3538,24 @@ out:
 	}
 	if (got_write)
 		mnt_drop_write(nd->path.mnt);
+
+#ifdef CONFIG_RSBAC
+	if (!error && (rsbac_adf_req != R_NONE) && (rsbac_target != T_NONE)) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(rsbac_adf_req,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_open_flag,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"do_last() [sys_open()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 	path_put(&save_parent);
 	terminate_walk(nd);
 	return error;
@@ -3251,6 +3656,11 @@ static struct file *path_openat(int dfd, struct filename *pathname,
 	int opened = 0;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	file = get_empty_filp();
 	if (IS_ERR(file))
 		return file;
@@ -3279,6 +3689,25 @@ static struct file *path_openat(int dfd, struct filename *pathname,
 		error = may_follow_link(&link, nd);
 		if (unlikely(error))
 			break;
+
+#ifdef CONFIG_RSBAC
+		if (link.dentry->d_sb) {
+			rsbac_target_id.symlink.device = link.dentry->d_sb->s_dev;
+			rsbac_target_id.symlink.inode  = link.dentry->d_inode->i_ino;
+			rsbac_target_id.symlink.dentry_p = link.dentry;
+			rsbac_attribute_value.dummy = 0;
+			if (!rsbac_adf_request(R_SEARCH,
+						task_pid(current),
+						T_SYMLINK,
+						rsbac_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				error = -EPERM;
+				break;
+			}
+		}
+#endif
+
 		nd->flags |= LOOKUP_PARENT;
 		nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
 		error = follow_link(&link, nd, &cookie);
@@ -3458,6 +3887,13 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
 	int error = may_create(dir, dentry);
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	enum  rsbac_target_t rsbac_new_target;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (error)
 		return error;
 
@@ -3475,9 +3911,57 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 	if (error)
 		return error;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_mknod()]: calling ADF\n");
+	rsbac_target_id.dir.device = dir->i_sb->s_dev;
+	rsbac_target_id.dir.inode  = dir->i_ino;
+	rsbac_target_id.dir.dentry_p = dentry->d_parent;
+	rsbac_attribute_value.create_data.target = T_FILE;
+	rsbac_attribute_value.create_data.dentry_p = dentry;
+	rsbac_attribute_value.create_data.mode = mode;
+	rsbac_attribute_value.create_data.device = dev;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_create_data,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	error = dir->i_op->mknod(dir, dentry, mode, dev);
-	if (!error)
+	if (!error) {
+#ifdef CONFIG_RSBAC
+		if (dentry->d_inode) {
+			if (S_ISFIFO(dentry->d_inode->i_mode))
+				rsbac_new_target = T_FIFO;
+			else
+				if (S_ISLNK(dentry->d_inode->i_mode))
+					rsbac_new_target = T_SYMLINK;
+				else
+					if (S_ISSOCK(dentry->d_inode->i_mode))
+						rsbac_new_target = T_UNIXSOCK;
+					else
+						rsbac_new_target = T_FILE;
+			rsbac_new_target_id.dir.device = dentry->d_sb->s_dev;
+			rsbac_new_target_id.dir.inode  = dentry->d_inode->i_ino;
+			rsbac_new_target_id.dir.dentry_p = dentry;
+			if (unlikely(rsbac_adf_set_attr(R_CREATE,
+						task_pid(current),
+						T_DIR,
+						rsbac_target_id,
+						rsbac_new_target,
+						rsbac_new_target_id,
+						A_create_data,
+						rsbac_attribute_value))) {
+				rsbac_pr_debug(aef, "[do_mknod(), sys_mknod()]: rsbac_adf_set_attr() returned error");
+			}
+		}
+#endif
+
 		fsnotify_create(dir, dentry);
+	}
 	return error;
 }
 EXPORT_SYMBOL(vfs_mknod);
@@ -3551,6 +4035,13 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	int error = may_create(dir, dentry);
 	unsigned max_links = dir->i_sb->s_max_links;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_new_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (error)
 		return error;
 
@@ -3565,9 +4056,53 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 	if (max_links && dir->i_nlink >= max_links)
 		return -EMLINK;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "vfs_mkdir(): calling ADF\n");
+	rsbac_target_id.dir.device = dir->i_sb->s_dev;
+	rsbac_target_id.dir.inode  = dir->i_ino;
+	rsbac_target_id.dir.dentry_p = dentry->d_parent;
+	rsbac_attribute_value.create_data.target = T_DIR;
+	rsbac_attribute_value.create_data.dentry_p = dentry;
+	rsbac_attribute_value.create_data.mode = mode;
+	rsbac_attribute_value.create_data.device = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_create_data,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	error = dir->i_op->mkdir(dir, dentry, mode);
-	if (!error)
+	if (!error) {
+#ifdef CONFIG_RSBAC
+		if (dentry->d_inode) {
+			rsbac_new_target = T_DIR;
+			if (dentry->d_sb)
+				rsbac_new_target_id.dir.device = dentry->d_sb->s_dev;
+			else
+				rsbac_new_target_id.dir.device = rsbac_target_id.dir.device;
+			rsbac_new_target_id.dir.inode  = dentry->d_inode->i_ino;
+			rsbac_new_target_id.dir.dentry_p = dentry;
+			if (unlikely(rsbac_adf_set_attr(R_CREATE,
+						task_pid(current),
+						T_DIR,
+						rsbac_target_id,
+						rsbac_new_target,
+						rsbac_new_target_id,
+						A_create_data,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"vfs_mkdir() [sys_mkdir()]: rsbac_adf_set_attr() returned error");
+			}
+		}
+#endif
+
 		fsnotify_mkdir(dir, dentry);
+	}
+
 	return error;
 }
 EXPORT_SYMBOL(vfs_mkdir);
@@ -3631,6 +4166,12 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error = may_delete(dir, dentry, 1);
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (error)
 		return error;
 
@@ -3638,6 +4179,24 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 		return -EPERM;
 
 	dget(dentry);
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_rmdir() [sys_rmdir()]]: calling ADF\n");
+	rsbac_target_id.dir.device = dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_DELETE,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		dput(dentry);
+		return -EPERM;
+	}
+#endif
+
 	mutex_lock(&dentry->d_inode->i_mutex);
 
 	error = -EBUSY;
@@ -3659,6 +4218,24 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 
 out:
 	mutex_unlock(&dentry->d_inode->i_mutex);
+
+#ifdef CONFIG_RSBAC
+	if (!error) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_DELETE,
+					task_pid(current),
+					T_DIR,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"vfs_rmdir() [do_rmdir() [sys_rmdir()]]: rsbac_adf_set_attr() returned error");
+		}
+	}
+#endif
+
 	dput(dentry);
 	if (!error)
 		d_delete(dentry);
@@ -3751,6 +4328,13 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate
 	struct inode *target = dentry->d_inode;
 	int error = may_delete(dir, dentry, 0);
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (error)
 		return error;
 
@@ -3763,6 +4347,36 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate
 	else {
 		error = security_inode_unlink(dir, dentry);
 		if (!error) {
+#ifdef CONFIG_RSBAC
+			rsbac_pr_debug(aef, "[do_unlink() [sys_unlink()]]: calling ADF\n");
+			if (S_ISDIR(dentry->d_inode->i_mode))
+				rsbac_target = T_DIR;
+			else
+				if (S_ISFIFO(dentry->d_inode->i_mode))
+					rsbac_target = T_FIFO;
+				else
+					if (S_ISLNK(dentry->d_inode->i_mode))
+						rsbac_target = T_SYMLINK;
+					else
+						if (S_ISSOCK(dentry->d_inode->i_mode))
+							rsbac_target = T_UNIXSOCK;
+					else
+						rsbac_target = T_FILE;
+			rsbac_target_id.file.device = dentry->d_sb->s_dev;
+			rsbac_target_id.file.inode  = dentry->d_inode->i_ino;
+			rsbac_target_id.file.dentry_p = dentry;
+			rsbac_attribute_value.nlink = dentry->d_inode->i_nlink;
+			if (!rsbac_adf_request(R_DELETE,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						A_nlink,
+						rsbac_attribute_value)) {
+				error = -EPERM;
+				goto out;
+			}
+#endif
+
 			error = try_break_deleg(target, delegated_inode);
 			if (error)
 				goto out;
@@ -3776,6 +4390,23 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate
 out:
 	mutex_unlock(&target->i_mutex);
 
+#ifdef CONFIG_RSBAC
+	if (!error) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_DELETE,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_nlink,
+						rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"vfs_unlink() [do_unlink() [sys_unlink()]]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 	/* We don't d_delete() NFS sillyrenamed files--they still exist. */
 	if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
 		fsnotify_link_count(target);
@@ -3883,6 +4514,12 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 {
 	int error = may_create(dir, dentry);
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (error)
 		return error;
 
@@ -3893,9 +4530,46 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
 	if (error)
 		return error;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_symlink(), sys_symlink()]: calling ADF\n");
+	rsbac_target_id.dir.device = dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = dir->i_ino;
+	rsbac_target_id.dir.dentry_p = dentry->d_parent;
+	rsbac_attribute_value.create_data.target = T_SYMLINK;
+	rsbac_attribute_value.create_data.dentry_p = dentry;
+	rsbac_attribute_value.create_data.mode = 0;
+	rsbac_attribute_value.create_data.device = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_create_data,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	error = dir->i_op->symlink(dir, dentry, oldname);
-	if (!error)
+	if (!error) {
+#ifdef CONFIG_RSBAC
+		rsbac_new_target_id.symlink.device = dentry->d_sb->s_dev;
+		rsbac_new_target_id.symlink.inode  = dentry->d_inode->i_ino;
+		rsbac_new_target_id.symlink.dentry_p = dentry;
+		if (unlikely(rsbac_adf_set_attr(R_CREATE,
+					task_pid(current),
+					T_DIR,
+					rsbac_target_id,
+					T_SYMLINK,
+					rsbac_new_target_id,
+					A_create_data,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"vfs_symlink() [do_symlink(), sys_symlink()]: rsbac_adf_set_attr() returned error");
+		}
+#endif
+
 		fsnotify_create(dir, dentry);
+	}
 	return error;
 }
 EXPORT_SYMBOL(vfs_symlink);
@@ -3961,6 +4635,12 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 	unsigned max_links = dir->i_sb->s_max_links;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!inode)
 		return -ENOENT;
 
@@ -3985,6 +4665,31 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 	if (error)
 		return error;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_link() [sys_link()]]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR (old_dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO (old_dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK (old_dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK (old_dentry->d_inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.dir.device = old_dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = old_dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = old_dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_LINK_HARD,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	mutex_lock(&inode->i_mutex);
 	/* Make sure we don't allow creating hardlink to an unlinked file */
 	if (inode->i_nlink == 0 && !(inode->i_state & I_LINKABLE))
@@ -4149,6 +4854,17 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	bool new_is_dir = false;
 	unsigned max_links = new_dir->i_sb->s_max_links;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	enum  rsbac_target_t rsbac_target2 = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_target_id2;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	union rsbac_attribute_value_t rsbac_attribute_value2;
+	rsbac_boolean_t target_exists = FALSE;
+#endif
+
 	if (source == target)
 		return 0;
 
@@ -4180,6 +4896,11 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	 * we'll need to flip '..'.
 	 */
 	if (new_dir != old_dir) {
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+		if (rsbac_dac_part_disabled(old_dentry))
+			error = 0;
+		else {
+#endif
 		if (is_dir) {
 			error = inode_permission(source, MAY_WRITE);
 			if (error)
@@ -4190,6 +4911,9 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			if (error)
 				return error;
 		}
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+		}
+#endif
 	}
 
 	error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry,
@@ -4199,6 +4923,91 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
 	dget(new_dentry);
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[vfs_rename_dir()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(old_dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO (old_dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK (old_dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK (old_dentry->d_inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = old_dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = old_dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = old_dentry;
+	rsbac_attribute_value.new_dir_dentry_p = new_dentry->d_parent;
+	if (!rsbac_adf_request(R_RENAME,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_new_dir_dentry_p,
+				rsbac_attribute_value)) {
+		dput(new_dentry);
+		fsnotify_oldname_free(old_name);
+		return -EPERM;
+	}
+	if (new_dir != old_dir) {
+#ifdef CONFIG_RSBAC_MOVETO
+		rsbac_pr_debug(aef, "[vfs_rename_dir()]: calling ADF for MOVETO on new_dir\n");
+#else
+		rsbac_pr_debug(aef, "[vfs_rename_dir()]: calling ADF for WRITE on new_dir\n");
+#endif
+		rsbac_target_id2.dir.device = new_dentry->d_sb->s_dev;
+		rsbac_target_id2.dir.inode  = new_dir->i_ino;
+		rsbac_target_id2.dir.dentry_p = new_dentry->d_parent;
+		rsbac_attribute_value2.dummy = 0;
+#ifdef CONFIG_RSBAC_MOVETO
+		if (!rsbac_adf_request(R_MOVETO,
+#else
+		if (!rsbac_adf_request(R_WRITE,
+#endif
+					task_pid(current),
+					T_DIR,
+					rsbac_target_id2,
+					A_none,
+					rsbac_attribute_value2)) {
+			dput(new_dentry);
+			fsnotify_oldname_free(old_name);
+#ifdef CONFIG_RSBAC_MOVETO_EXDEV
+			return -EXDEV;
+#else
+			return -EPERM;
+#endif
+		}
+	}
+	if(new_dentry->d_inode)
+	{
+		target_exists = TRUE;
+		rsbac_pr_debug(aef, "[vfs_rename_dir()]: calling ADF for DELETE on existing target\n");
+		rsbac_target2 = T_FILE;
+		if (S_ISDIR(new_dentry->d_inode->i_mode))
+			rsbac_target2 = T_DIR;
+		else if (S_ISFIFO (new_dentry->d_inode->i_mode))
+			rsbac_target2 = T_FIFO;
+		else if (S_ISLNK (new_dentry->d_inode->i_mode))
+			rsbac_target2 = T_SYMLINK;
+		else if (S_ISSOCK (new_dentry->d_inode->i_mode))
+			rsbac_target2 = T_UNIXSOCK;
+		rsbac_target_id2.file.device = new_dentry->d_sb->s_dev;
+		rsbac_target_id2.file.inode  = new_dentry->d_inode->i_ino;
+		rsbac_target_id2.file.dentry_p = new_dentry;
+		rsbac_attribute_value2.nlink = new_dentry->d_inode->i_nlink;
+		if (!rsbac_adf_request(R_DELETE,
+					task_pid(current),
+					rsbac_target2,
+					rsbac_target_id2,
+					A_nlink,
+					rsbac_attribute_value2)) {
+			dput(new_dentry);
+			fsnotify_oldname_free(old_name);
+			return -EPERM;
+		}
+	}
+#endif
+
 	if (!is_dir || (flags & RENAME_EXCHANGE))
 		lock_two_nondirectories(source, target);
 	else if (target)
@@ -4256,6 +5065,42 @@ out:
 		unlock_two_nondirectories(source, target);
 	else if (target)
 		mutex_unlock(&target->i_mutex);
+
+#ifdef CONFIG_RSBAC
+	if (!error && target_exists) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_DELETE,
+					task_pid(current),
+					rsbac_target2,
+					rsbac_target_id2,
+					T_NONE,
+					rsbac_new_target_id,
+					A_nlink,
+					rsbac_attribute_value2))) {
+			rsbac_printk(KERN_WARNING
+					"do_rename() [sys_rename()]: rsbac_adf_set_attr() for DELETE returned error\n");
+		}
+	}
+#endif
+
+#ifdef CONFIG_RSBAC
+	if (!error) {
+		rsbac_new_target_id.dummy = 0;
+		rsbac_attribute_value.old_dir_inode_p = old_dir;
+		if (unlikely(rsbac_adf_set_attr(R_RENAME,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_old_dir_inode_p,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+				"do_rename() [sys_rename()]: rsbac_adf_set_attr() for RENAME returned error\n");
+		}
+	}
+#endif
+
 	dput(new_dentry);
 	if (!error) {
 		fsnotify_move(old_dir, new_dir, old_name, is_dir,
@@ -4456,6 +5301,35 @@ out:
 }
 EXPORT_SYMBOL(readlink_copy);
 
+#ifdef CONFIG_RSBAC_SYM_REDIR
+int rsbac_readlink_copy(char __user *buffer, int buflen, const char *link, struct inode *inode)
+{
+	int len = PTR_ERR(link);
+	char * rsbac_name;
+
+	if (IS_ERR(link))
+		goto out;
+
+	len = strlen(link);
+	if (len > (unsigned) buflen)
+		len = buflen;
+
+	rsbac_name = rsbac_symlink_redirect(inode, link, buflen);
+	if (rsbac_name) {
+		len = strlen(rsbac_name);
+		if (copy_to_user(buffer, rsbac_name, len))
+			len = -EFAULT;
+		kfree(rsbac_name);
+	}
+	else
+	if (copy_to_user(buffer, link, len))
+		len = -EFAULT;
+out:
+	return len;
+}
+EXPORT_SYMBOL(rsbac_readlink_copy);
+#endif
+
 /*
  * A helper for ->readlink().  This should be used *ONLY* for symlinks that
  * have ->follow_link() touching nd only in nd_set_link().  Using (or not
@@ -4472,7 +5346,11 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 	if (IS_ERR(cookie))
 		return PTR_ERR(cookie);
 
+#ifdef CONFIG_RSBAC_SYM_REDIR
+	res = rsbac_readlink_copy(buffer, buflen, nd_get_link(&nd), dentry->d_inode);
+#else
 	res = readlink_copy(buffer, buflen, nd_get_link(&nd));
+#endif
 	if (dentry->d_inode->i_op->put_link)
 		dentry->d_inode->i_op->put_link(dentry, &nd, cookie);
 	return res;
@@ -4497,7 +5375,11 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
 int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
 	struct page *page = NULL;
+#ifdef CONFIG_RSBAC_SYM_REDIR
+	int res = rsbac_readlink_copy(buffer, buflen, page_getlink(dentry, &page), dentry->d_inode);
+#else
 	int res = readlink_copy(buffer, buflen, page_getlink(dentry, &page));
+#endif
 	if (page) {
 		kunmap(page);
 		page_cache_release(page);
diff --git a/fs/namespace.c b/fs/namespace.c
index 45fc042..ea09f4b 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -24,6 +24,9 @@
 #include <linux/magic.h>
 #include <linux/bootmem.h>
 #include <linux/task_work.h>
+
+#include <rsbac/hooks.h>
+
 #include "pnode.h"
 #include "internal.h"
 
@@ -277,6 +280,13 @@ out_free_cache:
  */
 int __mnt_is_readonly(struct vfsmount *mnt)
 {
+#ifdef CONFIG_RSBAC
+	/* HACK - Remove me when switching to full 2.6, pass over the vfsmount
+	 * in init_private_file() instead
+	 */
+	if(!mnt)
+		return 0;
+#endif
 	if (mnt->mnt_flags & MNT_READONLY)
 		return 1;
 	if (mnt->mnt_sb->s_flags & MS_RDONLY)
@@ -349,6 +359,14 @@ int __mnt_want_write(struct vfsmount *m)
 	struct mount *mnt = real_mount(m);
 	int ret = 0;
 
+#ifdef CONFIG_RSBAC
+	/* HACK - Remove me when switching to full 2.6, pass over the vfsmount
+	 * in init_private_file() instead
+	 */
+	if(!mnt)
+		return 0;
+#endif
+
 	preempt_disable();
 	mnt_inc_writers(mnt);
 	/*
@@ -463,6 +481,13 @@ EXPORT_SYMBOL_GPL(mnt_want_write_file);
  */
 void __mnt_drop_write(struct vfsmount *mnt)
 {
+#ifdef CONFIG_RSBAC
+	/* HACK - Remove me when switching to full 2.6, pass over the vfsmount
+	 * in init_private_file() instead
+	 */
+	if(!mnt)
+		return;
+#endif
 	preempt_disable();
 	mnt_dec_writers(real_mount(mnt));
 	preempt_enable();
@@ -981,6 +1006,11 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
 	lock_mount_hash();
 	list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
 	unlock_mount_hash();
+
+#ifdef CONFIG_RSBAC
+	rsbac_mount(&mnt->mnt);
+#endif
+
 	return &mnt->mnt;
 }
 EXPORT_SYMBOL_GPL(vfs_kern_mount);
@@ -1040,6 +1070,10 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
 	list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
 	unlock_mount_hash();
 
+#ifdef CONFIG_RSBAC
+	rsbac_mount(&mnt->mnt);
+#endif
+
 	if ((flag & CL_SLAVE) ||
 	    ((flag & CL_SHARED_TO_SLAVE) && IS_MNT_SHARED(old))) {
 		list_add(&mnt->mnt_slave, &old->mnt_slave_list);
@@ -1480,6 +1514,11 @@ static int do_umount(struct mount *mnt, int flags)
 	struct super_block *sb = mnt->mnt.mnt_sb;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	retval = security_sb_umount(&mnt->mnt, flags);
 	if (retval)
 		return retval;
@@ -1510,6 +1549,44 @@ static int do_umount(struct mount *mnt, int flags)
 			return -EAGAIN;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF for DIR\n");
+	rsbac_target_id.dir.device = sb->s_root->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = sb->s_root->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = sb->s_root;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_UMOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+	rsbac_pr_debug(aef, "calling ADF for dev\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(sb->s_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(sb->s_dev);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_UMOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
+        /* RSBAC: removing data structures for this fs from memory (not /) */
+#ifdef CONFIG_RSBAC
+	if ((&mnt->mnt != current->fs->root.mnt) || (flags & MNT_DETACH)) {
+		rsbac_pr_debug(ds, "[sys_umount()]: calling rsbac_umount for Device %02u:%02u\n",
+				MAJOR(sb->s_dev), MINOR(sb->s_dev));
+		rsbac_umount(&mnt->mnt);
+	}
+#endif
+
 	/*
 	 * If we may have to abort operations to get out of this
 	 * mount, and they will themselves hold resources we must
@@ -1565,6 +1642,17 @@ static int do_umount(struct mount *mnt, int flags)
 		}
 	}
 	unlock_mount_hash();
+
+#ifdef CONFIG_RSBAC
+	/* RSBAC: umount failed, so reread data structures for this fs from disk */
+	if(retval) {
+		rsbac_printk(KERN_WARNING
+				"do_umount() [sys_umount()]: umount failed -> calling rsbac_mount for Device %02u:%02u\n",
+				MAJOR(mnt->mnt.mnt_sb->s_dev),MINOR(mnt->mnt.mnt_sb->s_dev));
+		rsbac_mount(&mnt->mnt);
+	}
+#endif
+
 	namespace_unlock();
 	return retval;
 }
@@ -2145,6 +2233,13 @@ static int do_loopback(struct path *path, const char *old_name,
 	struct mount *mnt = NULL, *old, *parent;
 	struct mountpoint *mp;
 	int err;
+
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!old_name || !*old_name)
 		return -EINVAL;
 	err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
@@ -2163,6 +2258,57 @@ static int do_loopback(struct path *path, const char *old_name,
 	old = real_mount(old_path.mnt);
 	parent = real_mount(path->mnt);
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_loopback() [sys_mount()]]: calling ADF for DIR\n");
+	rsbac_target_id.dir.device = old_path.dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = old_path.dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = old_path.dentry;
+	rsbac_attribute_value.mode = recurse;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_mode,
+				rsbac_attribute_value))
+	{
+		err = -EPERM;
+		goto out2;
+	}
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for DEV\n");
+	if(S_ISBLK(old_path.dentry->d_inode->i_mode))
+	{
+		rsbac_target = T_DEV;
+		rsbac_target_id.dev.type = D_block;
+		rsbac_target_id.dev.major = RSBAC_MAJOR(old_path.dentry->d_sb->s_dev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(old_path.dentry->d_sb->s_dev);
+	}
+	else
+		if(S_ISDIR(old_path.dentry->d_inode->i_mode))
+		{
+			rsbac_target = T_DIR;
+			rsbac_target_id.dir.device = old_path.dentry->d_sb->s_dev;
+			rsbac_target_id.dir.inode  = old_path.dentry->d_inode->i_ino;
+			rsbac_target_id.dir.dentry_p = old_path.dentry;
+		}
+		else
+		{
+			rsbac_target = T_FILE;
+			rsbac_target_id.file.device = old_path.dentry->d_sb->s_dev;
+			rsbac_target_id.file.inode  = old_path.dentry->d_inode->i_ino;
+			rsbac_target_id.file.dentry_p = old_path.dentry;
+		}
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_mode,
+				rsbac_attribute_value))
+	{
+		err = -EPERM;
+		goto out2;
+	}
+#endif
+
 	err = -EINVAL;
 	if (IS_MNT_UNBINDABLE(old))
 		goto out2;
@@ -2198,6 +2344,12 @@ out2:
 	unlock_mount(mp);
 out:
 	path_put(&old_path);
+
+#ifdef CONFIG_RSBAC
+	if (!err)
+		rsbac_mount(&mnt->mnt);
+#endif
+
 	return err;
 }
 
@@ -2230,6 +2382,11 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
 	struct super_block *sb = path->mnt->mnt_sb;
 	struct mount *mnt = real_mount(path->mnt);
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!check_mnt(mnt))
 		return -EINVAL;
 
@@ -2273,6 +2430,34 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
 	if (err)
 		return err;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for DIR\n");
+	rsbac_target_id.dir.device = path->dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = path->dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = path->dentry;
+	rsbac_attribute_value.mode = flags;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_mode,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for DEV\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(sb->s_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(sb->s_dev);
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_mode,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	down_write(&sb->s_umount);
 	if (flags & MS_BIND)
 		err = change_mount_flags(path->mnt, flags);
@@ -2308,6 +2493,12 @@ static int do_move_mount(struct path *path, const char *old_name)
 	struct mount *old;
 	struct mountpoint *mp;
 	int err;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!old_name || !*old_name)
 		return -EINVAL;
 	err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
@@ -2322,6 +2513,61 @@ static int do_move_mount(struct path *path, const char *old_name)
 	old = real_mount(old_path.mnt);
 	p = real_mount(path->mnt);
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for UMOUNT on old DIR\n");
+	rsbac_target_id.dir.device = old_path.dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = old_path.dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = old_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_UMOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))	{
+		err = -EPERM;
+		goto out1;
+	}
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for MOUNT on new DIR\n");
+	rsbac_target_id.dir.device = path->dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = path->dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = path->dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto out1;
+	}
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for UMOUNT on DEV\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(old_path.dentry->d_sb->s_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(old_path.dentry->d_sb->s_dev);
+	if (!rsbac_adf_request(R_UMOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto out1;
+	}
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for MOUNT on DEV\n");
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto out1;
+	}
+#endif
+
+
 	err = -EINVAL;
 	if (!check_mnt(p) || !check_mnt(old))
 		goto out1;
@@ -2355,9 +2601,24 @@ static int do_move_mount(struct path *path, const char *old_name)
 		if (p == old)
 			goto out1;
 
+#ifdef CONFIG_RSBAC
+	rsbac_umount(old_path.mnt);
+#endif
+
 	err = attach_recursive_mnt(old, real_mount(path->mnt), mp, &parent_path);
-	if (err)
+	if (err) {
+#ifdef CONFIG_RSBAC
+		rsbac_printk(KERN_WARNING
+				"do_move_mount() [sys_mount()]: attach_recursive_mnt() failed -> calling rsbac_mount() for old Device %02u:%02u\n",
+				MAJOR(old_path.mnt->mnt_sb->s_dev),MINOR(old_path.mnt->mnt_sb->s_dev));
+		rsbac_mount(old_path.mnt);
+#endif
 		goto out1;
+        }
+
+#ifdef CONFIG_RSBAC
+	rsbac_mount(old_path.mnt);
+#endif
 
 	/* if the mount is moved, it should no longer be expire
 	 * automatically */
@@ -2403,6 +2664,11 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 	struct mount *parent;
 	int err;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	mnt_flags &= ~MNT_INTERNAL_FLAGS;
 
 	mp = lock_mount(path);
@@ -2430,6 +2696,37 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
 	if (d_is_symlink(newmnt->mnt.mnt_root))
 		goto unlock;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[do_add_mount() [sys_mount()]]: calling ADF for DIR\n");
+	rsbac_target_id.dir.device = path->dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = path->dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = path->dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto unlock;
+	}
+	rsbac_pr_debug(aef, "[do_mount() [sys_mount()]]: calling ADF for DEV\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(newmnt->mnt.mnt_sb->s_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(newmnt->mnt.mnt_sb->s_dev);
+	rsbac_attribute_value.mode = mnt_flags;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_mode,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto unlock;
+	}
+#endif
+
 	newmnt->mnt.mnt_flags = mnt_flags;
 	err = graft_tree(newmnt, parent, mp);
 
@@ -3059,6 +3356,11 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	struct mountpoint *old_mp, *root_mp;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!may_mount())
 		return -EPERM;
 
@@ -3080,6 +3382,42 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	if (IS_ERR(old_mp))
 		goto out3;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF for MOUNT on put_old\n");
+	rsbac_target_id.dir.device = old.dentry->d_sb->s_dev;
+	rsbac_target_id.dir.inode  = old.dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = old.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		error = -EPERM;
+		goto out4;
+	}
+	rsbac_pr_debug(aef, "calling ADF for MOUNT on root DIR\n");
+	rsbac_target_id.dir.device = current->fs->root.mnt->mnt_sb->s_dev;
+	rsbac_target_id.dir.inode  = current->fs->root.dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = current->fs->root.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MOUNT,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		error = -EPERM;
+		goto out4;
+	}
+
+	/* Make the new root's cached rsbac.dat dentry be put to free the old root's dcache */
+	rsbac_free_dat_dentries();
+#endif
+
 	error = -EINVAL;
 	new_mnt = real_mount(new.mnt);
 	root_mnt = real_mount(root.mnt);
diff --git a/fs/open.c b/fs/open.c
index d0169e5..e86d7f2 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -34,16 +34,51 @@
 
 #include "internal.h"
 
+#ifdef CONFIG_RSBAC
+#include <net/sock.h>
+#endif
+#include <rsbac/hooks.h>
+
 int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 	struct file *filp)
 {
 	int ret;
 	struct iattr newattrs;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#ifdef CONFIG_RSBAC_SECDEL
+	loff_t old_len = dentry->d_inode->i_size;
+#endif
+#endif
+
 	/* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
 	if (length < 0)
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[open_namei(), do_sys_truncate() [sys_truncate()]]: calling ADF\n");
+	rsbac_target_id.file.device = dentry->d_inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_TRUNCATE,
+				task_pid(current),
+				T_FILE,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
+	/* RSBAC: Overwrite truncated part, if asked by flag */
+#ifdef CONFIG_RSBAC_SECDEL
+	rsbac_sec_trunc(dentry, length, old_len);
+#endif
+
 	newattrs.ia_size = length;
 	newattrs.ia_valid = ATTR_SIZE | time_attrs;
 	if (filp) {
@@ -60,6 +95,25 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 	/* Note any delegations or leases have already been broken: */
 	ret = notify_change(dentry, &newattrs, NULL);
 	mutex_unlock(&dentry->d_inode->i_mutex);
+
+#ifdef CONFIG_RSBAC
+	if (!ret) {
+		rsbac_pr_debug(aef, "[open_namei(), do_sys_truncate() [sys_truncate()]]: notifying ADF\n");
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_TRUNCATE,
+					task_pid(current),
+					T_FILE,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"do_truncate() [open_namei(), do_sys_truncate() [sys_truncate()]]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 	return ret;
 }
 
@@ -80,6 +134,11 @@ long vfs_truncate(struct path *path, loff_t length)
 	if (error)
 		goto out;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+        if (rsbac_dac_part_disabled(path->dentry))
+		error = 0;
+	else
+#endif
 	error = inode_permission(inode, MAY_WRITE);
 	if (error)
 		goto mnt_drop_write_and_out;
@@ -226,6 +285,10 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 {
 	struct inode *inode = file_inode(file);
 	long ret;
+#ifdef CONFIG_RSBAC_RW
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	if (offset < 0 || len <= 0)
 		return -EINVAL;
@@ -283,6 +346,21 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 	if (S_ISFIFO(inode->i_mode))
 		return -ESPIPE;
 
+#ifdef CONFIG_RSBAC_RW
+	rsbac_pr_debug(aef, "sys_fallocate(): calling ADF\n");
+	rsbac_target_id.file.device = inode->i_sb->s_dev;
+	rsbac_target_id.file.inode = inode->i_ino;
+	rsbac_target_id.file.dentry_p = file->f_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_WRITE,
+			task_pid(current),
+			T_FILE,
+			rsbac_target_id,
+			A_none,
+			rsbac_attribute_value))
+		return -EPERM;
+#endif
+
 	/*
 	 * Let individual file system decide if it supports preallocation
 	 * for directories or not.
@@ -341,6 +419,12 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
 	int res;
 	unsigned int lookup_flags = LOOKUP_FOLLOW;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (mode & ~S_IRWXO)	/* where's F_OK, X_OK, W_OK, R_OK? */
 		return -EINVAL;
 
@@ -354,7 +438,11 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		/* Clear the capabilities if we switch to a non-root user */
 		kuid_t root_uid = make_kuid(override_cred->user_ns, 0);
-		if (!uid_eq(override_cred->uid, root_uid))
+		if (!uid_eq(override_cred->uid, root_uid)
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+			&& !rsbac_uid_faked()
+#endif
+		)
 			cap_clear(override_cred->cap_effective);
 		else
 			override_cred->cap_effective =
@@ -367,6 +455,32 @@ retry:
 	if (res)
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(path.dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(path.dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(path.dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(path.dentry->d_inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = path.dentry->d_inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = path.dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_PERMISSIONS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		res = -EPERM;
+		goto out_path_release;
+	}
+#endif
+
 	inode = path.dentry->d_inode;
 
 	if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
@@ -418,15 +532,43 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename)
 	struct path path;
 	int error;
 	unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 retry:
 	error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
 	if (error)
 		goto out;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(path.dentry))
+		error = 0;
+	else
+#endif
 	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
 	if (error)
 		goto dput_and_out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dir.device = path.dentry->d_inode->i_sb->s_dev;
+	rsbac_target_id.dir.inode  = path.dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CHDIR,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto dput_and_out;
+	}
+#endif
+
 	set_fs_pwd(current->fs, &path);
 
 dput_and_out:
@@ -445,6 +587,11 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
 	struct inode *inode;
 	int error = -EBADF;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = -EBADF;
 	if (!f.file)
 		goto out;
@@ -455,7 +602,32 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
 	if (!S_ISDIR(inode->i_mode))
 		goto out_putf;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(f.file->f_path.dentry))
+		error = 0;
+	else
+#endif
+
 	error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
+
+#ifdef CONFIG_RSBAC
+	if (!error) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.dir.device = inode->i_sb->s_dev;
+		rsbac_target_id.dir.inode  = inode->i_ino;
+		rsbac_target_id.dir.dentry_p = f.file->f_path.dentry;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_CHDIR,
+					task_pid(current),
+					T_DIR,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			error = -EPERM;
+		}
+	}
+#endif
+
 	if (!error)
 		set_fs_pwd(current->fs, &f.file->f_path);
 out_putf:
@@ -469,11 +641,22 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 	struct path path;
 	int error;
 	unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 retry:
 	error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
 	if (error)
 		goto out;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+	if (rsbac_dac_part_disabled(path.dentry))
+		error = 0;
+	else
+#endif
 	error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
 	if (error)
 		goto dput_and_out;
@@ -485,6 +668,23 @@ retry:
 	if (error)
 		goto dput_and_out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dir.device = path.dentry->d_inode->i_sb->s_dev;
+	rsbac_target_id.dir.inode  = path.dentry->d_inode->i_ino;
+	rsbac_target_id.dir.dentry_p = path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CHDIR,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto dput_and_out;
+	}
+#endif
+
 	set_fs_root(current->fs, &path);
 	error = 0;
 dput_and_out:
@@ -504,9 +704,50 @@ static int chmod_common(struct path *path, umode_t mode)
 	struct iattr newattrs;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = mnt_want_write(path->mnt);
 	if (error)
 		return error;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target = T_FILE;
+	rsbac_target_id.file.device = inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = path->dentry;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(inode->i_mode)) {
+		if(inode->i_sb->s_magic == SOCKFS_MAGIC) {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			rsbac_target_id.ipc.id.id_nr = inode->i_ino;
+		} else {
+			rsbac_target = T_UNIXSOCK;
+		}
+	}
+	rsbac_attribute_value.mode = mode;
+	if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_mode,
+				rsbac_attribute_value))
+	{
+		mnt_drop_write(path->mnt);
+		return -EPERM;
+	}
+#endif
+
 retry_deleg:
 	mutex_lock(&inode->i_mutex);
 	error = security_path_chmod(path, mode);
@@ -571,9 +812,40 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
 	kuid_t uid;
 	kgid_t gid;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	uid = make_kuid(current_user_ns(), user);
 	gid = make_kgid(current_user_ns(), group);
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_*chown]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = path->dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CHANGE_OWNER,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 retry_deleg:
 	newattrs.ia_valid =  ATTR_CTIME;
 	if (user != (uid_t) -1) {
@@ -1069,11 +1341,92 @@ int filp_close(struct file *filp, fl_owner_t id)
 {
 	int retval = 0;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t       rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!file_count(filp)) {
 		printk(KERN_ERR "VFS: Close: file count is 0\n");
 		return 0;
 	}
 
+#ifdef CONFIG_RSBAC
+	if (current->files && filp && filp->f_path.dentry && filp->f_path.dentry->d_inode) {
+		rsbac_pr_debug(aef, "[sys_close]: calling ADF\n");
+		rsbac_target = T_NONE;
+		if (S_ISBLK(filp->f_path.dentry->d_inode->i_mode)
+			|| S_ISCHR(filp->f_path.dentry->d_inode->i_mode)) {
+			rsbac_target = T_DEV;
+			if (S_ISBLK(filp->f_path.dentry->d_inode->i_mode)) {
+				rsbac_target_id.dev.type = D_block;
+			}
+			else {
+				rsbac_target_id.dev.type = D_char;
+			}
+			rsbac_target_id.dev.major = RSBAC_MAJOR(filp->f_path.dentry->d_inode->i_sb->s_dev);
+			rsbac_target_id.dev.minor = RSBAC_MINOR(filp->f_path.dentry->d_inode->i_sb->s_dev);
+			rsbac_attribute = A_f_mode;
+			rsbac_attribute_value.f_mode = filp->f_mode;
+		} else
+			if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode)) {
+				if (SOCKET_I(filp->f_path.dentry->d_inode)->ops
+					&& (SOCKET_I(filp->f_path.dentry->d_inode)->ops->family == AF_UNIX)) {
+					if (filp->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+						rsbac_target = T_IPC;
+						rsbac_target_id.ipc.type = I_anonunix;
+						rsbac_target_id.ipc.id.id_nr = filp->f_path.dentry->d_inode->i_ino;
+						rsbac_attribute = A_nlink;
+						rsbac_attribute_value.nlink = filp->f_path.dentry->d_inode->i_nlink;
+					} else {
+						rsbac_target = T_UNIXSOCK;
+						rsbac_target_id.unixsock.device = filp->f_path.dentry->d_sb->s_dev;
+						rsbac_target_id.unixsock.inode  = filp->f_path.dentry->d_inode->i_ino;
+						rsbac_target_id.unixsock.dentry_p = filp->f_path.dentry;
+						rsbac_attribute = A_f_mode;
+						rsbac_attribute_value.f_mode = filp->f_mode;
+					}
+				} else {
+					rsbac_target = T_NETOBJ;
+					rsbac_target_id.netobj.sock_p
+						= SOCKET_I(filp->f_path.dentry->d_inode);
+					rsbac_target_id.netobj.local_addr = NULL;
+					rsbac_target_id.netobj.local_len = 0;
+					rsbac_target_id.netobj.remote_addr = NULL;
+					rsbac_target_id.netobj.remote_len = 0;
+					rsbac_attribute = A_f_mode;
+					rsbac_attribute_value.f_mode = filp->f_mode;
+				}
+			} else { /* must be file, fifo or dir */
+				if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode))
+					rsbac_target = T_DIR;
+				else if (S_ISFIFO(filp->f_path.dentry->d_inode->i_mode))
+					rsbac_target = T_FIFO;
+				else
+					rsbac_target = T_FILE;
+				rsbac_target_id.file.device = filp->f_path.dentry->d_inode->i_sb->s_dev;
+				rsbac_target_id.file.inode  = filp->f_path.dentry->d_inode->i_ino;
+				rsbac_target_id.file.dentry_p = filp->f_path.dentry;
+				rsbac_attribute = A_f_mode;
+				rsbac_attribute_value.f_mode = filp->f_mode;
+			}
+		if ((rsbac_target != T_NONE) && !rsbac_adf_request(R_CLOSE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))
+		{
+#ifdef CONFIG_RSBAC_ENFORCE_CLOSE
+			return -EPERM;
+#endif
+		}
+	}
+#endif
+
 	if (filp->f_op->flush)
 		retval = filp->f_op->flush(filp, id);
 
@@ -1081,6 +1434,26 @@ int filp_close(struct file *filp, fl_owner_t id)
 		dnotify_flush(filp, id);
 		locks_remove_posix(filp, id);
 	}
+
+#ifdef CONFIG_RSBAC
+	if (rsbac_target != T_NONE) {
+		rsbac_pr_debug(aef, "[sys_close]: notifying ADF\n");
+		rsbac_new_target_id.dummy = 0;
+		rsbac_attribute_value.f_mode = filp->f_mode;
+		if (unlikely(rsbac_adf_set_attr(R_CLOSE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"filp_close() [sys_close]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 	fput(filp);
 	return retval;
 }
diff --git a/fs/pipe.c b/fs/pipe.c
index dbea65d..c7f279c 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -27,6 +27,8 @@
 
 #include "internal.h"
 
+#include <rsbac/hooks.h>
+
 /*
  * The max size that a non-root user is allowed to grow the pipe. Can
  * be set by root in /proc/sys/fs/pipe-max-size
@@ -240,10 +242,32 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 	int do_wakeup;
 	ssize_t ret;
 
+#ifdef CONFIG_RSBAC_RW
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* Null read succeeds. */
 	if (unlikely(total_len == 0))
 		return 0;
 
+#ifdef CONFIG_RSBAC_RW
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.ipc.type = I_anonpipe;
+	rsbac_target_id.ipc.id.id_nr = filp->f_inode->i_ino;
+	rsbac_attribute_value.dummy = 0;
+
+	if (!rsbac_adf_request(R_READ,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	do_wakeup = 0;
 	ret = 0;
 	__pipe_lock(pipe);
@@ -330,8 +354,26 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 		wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM);
 		kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 	}
-	if (ret > 0)
+	if (ret > 0) {
 		file_accessed(filp);
+
+#ifdef CONFIG_RSBAC_RW
+		rsbac_new_target_id.dummy = 0;
+
+		if (unlikely(rsbac_adf_set_attr(R_READ,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"pipe_readv(): rsbac_adf_set_attr() returned error\n");
+		}
+#endif
+
+	}
 	return ret;
 }
 
@@ -350,10 +392,32 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
 	size_t total_len = iov_iter_count(from);
 	ssize_t chars;
 
+#ifdef CONFIG_RSBAC_RW
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* Null write succeeds. */
 	if (unlikely(total_len == 0))
 		return 0;
 
+#ifdef CONFIG_RSBAC_RW
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.ipc.type = I_anonpipe;
+	rsbac_target_id.ipc.id.id_nr = filp->f_inode->i_ino;
+	rsbac_attribute_value.dummy = 0;
+
+	if (!rsbac_adf_request(R_WRITE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	__pipe_lock(pipe);
 
 	if (!pipe->readers) {
@@ -475,6 +539,23 @@ out:
 		if (err)
 			ret = err;
 		sb_end_write(file_inode(filp)->i_sb);
+
+#ifdef CONFIG_RSBAC_RW
+		rsbac_new_target_id.dummy = 0;
+
+		if (unlikely(rsbac_adf_set_attr(R_WRITE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"pipe_writev(): rsbac_adf_set_attr() returned error\n");
+		}
+#endif
+
 	}
 	return ret;
 }
@@ -538,6 +619,10 @@ static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
 {
 	int kill = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+#endif
+
 	spin_lock(&inode->i_lock);
 	if (!--pipe->files) {
 		inode->i_pipe = NULL;
@@ -545,8 +630,16 @@ static void put_pipe_info(struct inode *inode, struct pipe_inode_info *pipe)
 	}
 	spin_unlock(&inode->i_lock);
 
-	if (kill)
+	if (kill) {
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "calling ACI remove_target()\n");
+		rsbac_target_id.ipc.type = I_anonpipe;
+		rsbac_target_id.ipc.id.id_nr  = inode->i_ino;
+		rsbac_remove_target(T_IPC, rsbac_target_id);
+#endif
+
 		free_pipe_info(pipe);
+	}
 }
 
 static int
@@ -577,14 +670,87 @@ pipe_fasync(int fd, struct file *filp, int on)
 	struct pipe_inode_info *pipe = filp->private_data;
 	int retval = 0;
 
+#ifdef CONFIG_RSBAC_RW
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	__pipe_lock(pipe);
-	if (filp->f_mode & FMODE_READ)
+	if (filp->f_mode & FMODE_READ) {
+#ifdef CONFIG_RSBAC_RW
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.ipc.type = I_anonpipe;
+		rsbac_target_id.ipc.id.id_nr = filp->f_inode->i_ino;
+		rsbac_attribute_value.dummy = 0;
+
+		if (!rsbac_adf_request(R_READ,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			__pipe_unlock(pipe);
+			return -EPERM;
+		}
+#endif
+
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_readers);
+
+#ifdef CONFIG_RSBAC_RW
+		rsbac_new_target_id.dummy = 0;
+
+		if (unlikely((retval >= 0) && rsbac_adf_set_attr(R_READ,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING "pipe_fasync(): rsbac_adf_set_attr() for READ returned error\n");
+		}
+#endif
+
+	}
 	if ((filp->f_mode & FMODE_WRITE) && retval >= 0) {
+#ifdef CONFIG_RSBAC_RW
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.ipc.type = I_anonpipe;
+		rsbac_target_id.ipc.id.id_nr = filp->f_inode->i_ino;
+		rsbac_attribute_value.dummy = 0;
+
+		if (!rsbac_adf_request(R_WRITE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			__pipe_unlock(pipe);
+			return -EPERM;
+		}
+#endif
+
 		retval = fasync_helper(fd, filp, on, &pipe->fasync_writers);
 		if (retval < 0 && (filp->f_mode & FMODE_READ))
 			/* this can happen only if on == T */
 			fasync_helper(-1, filp, 0, &pipe->fasync_readers);
+
+#ifdef CONFIG_RSBAC_RW
+		rsbac_new_target_id.dummy = 0;
+
+		if (unlikely((retval >= 0) && rsbac_adf_set_attr(R_WRITE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING "pipe_fasync(): rsbac_adf_set_attr() for WRITE returned error\n");
+		}
+#endif
+
 	}
 	__pipe_unlock(pipe);
 	return retval;
@@ -714,11 +880,33 @@ fail_inode:
 int create_pipe_files(struct file **res, int flags)
 {
 	int err;
-	struct inode *inode = get_pipe_inode();
+	struct inode *inode;
 	struct file *f;
 	struct path path;
 	static struct qstr name = { .name = "" };
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "create_pipe_files() [sys_pipe()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_anonpipe;
+	rsbac_target_id.ipc.id.id_nr = 0;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
+	inode = get_pipe_inode();
 	if (!inode)
 		return -ENFILE;
 
@@ -742,6 +930,24 @@ int create_pipe_files(struct file **res, int flags)
 	if (IS_ERR(res[0]))
 		goto err_file;
 
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.ipc.type = I_anonpipe;
+	rsbac_target_id.ipc.id.id_nr = inode->i_ino;
+	rsbac_new_target_id.dummy = 0;
+	rsbac_attribute_value.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_none,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"do_pipe() [sys_pipe()]: rsbac_adf_set_attr() returned error");
+	}
+#endif
+
 	path_get(&path);
 	res[0]->private_data = inode->i_pipe;
 	res[0]->f_flags = O_RDONLY | (flags & O_NONBLOCK);
@@ -861,8 +1067,47 @@ static int fifo_open(struct inode *inode, struct file *filp)
 	bool is_pipe = inode->i_sb->s_magic == PIPEFS_MAGIC;
 	int ret;
 
+#ifdef CONFIG_RSBAC
+	enum rsbac_adf_request_t rsbac_request = R_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	filp->f_version = 0;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	switch (filp->f_mode & (FMODE_READ | FMODE_WRITE)) {
+		case FMODE_READ:
+			rsbac_request = R_READ_OPEN;
+			break;
+
+		case FMODE_WRITE:
+			rsbac_request = R_WRITE_OPEN;
+			break;
+
+		case FMODE_READ | FMODE_WRITE:
+			rsbac_request = R_READ_WRITE_OPEN;
+			break;
+
+		default:
+			return -EINVAL;
+	}
+	rsbac_target_id.ipc.type = I_anonpipe;
+	rsbac_target_id.ipc.id.id_nr = inode->i_ino;
+	rsbac_attribute_value.dummy = 0;
+
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	spin_lock(&inode->i_lock);
 	if (inode->i_pipe) {
 		pipe = inode->i_pipe;
@@ -957,6 +1202,21 @@ static int fifo_open(struct inode *inode, struct file *filp)
 		goto err;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_new_target_id.dummy = 0;
+
+	if (unlikely(!ret && rsbac_adf_set_attr(rsbac_request,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_none,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING "pipe_read_open(): rsbac_adf_set_attr() returned error\n");
+	}
+#endif
+
 	/* Ok! */
 	__pipe_unlock(pipe);
 	return 0;
diff --git a/fs/proc/array.c b/fs/proc/array.c
index dca04ed..115ec8c 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -87,6 +87,7 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include "internal.h"
+#include <rsbac/hooks.h>
 
 static inline void task_name(struct seq_file *m, struct task_struct *p)
 {
@@ -343,7 +344,30 @@ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task)
 int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
 			struct pid *pid, struct task_struct *task)
 {
-	struct mm_struct *mm = get_task_mm(task);
+	struct mm_struct *mm;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
+	mm = get_task_mm(task);
 
 	task_name(m, task);
 	task_state(m, ns, pid, task);
@@ -382,6 +406,27 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
 	char tcomm[sizeof(task->comm)];
 	unsigned long flags;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))	{
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	state = *get_task_state(task);
 	vsize = eip = esp = 0;
 	permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT);
@@ -557,8 +602,30 @@ int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
 			struct pid *pid, struct task_struct *task)
 {
 	unsigned long size = 0, resident = 0, shared = 0, text = 0, data = 0;
-	struct mm_struct *mm = get_task_mm(task);
+	struct mm_struct *mm;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
+	mm = get_task_mm(task);
 	if (mm) {
 		size = task_statm(mm, &shared, &text, &data, &resident);
 		mmput(mm);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index d566549..74bfc20 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -94,6 +94,8 @@
 #include "internal.h"
 #include "fd.h"
 
+#include <rsbac/hooks.h>
+
 /* NOTE:
  *	Implementing inode permission operations in /proc is almost
  *	certainly an error.  Permission checks need to happen during
@@ -172,6 +174,28 @@ static int proc_cwd_link(struct dentry *dentry, struct path *path)
 	struct task_struct *task = get_proc_task(d_inode(dentry));
 	int result = -ENOENT;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if(!task)
+		return result;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	if (task) {
 		task_lock(task);
 		if (task->fs) {
@@ -189,6 +213,30 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
 	struct task_struct *task = get_proc_task(d_inode(dentry));
 	int result = -ENOENT;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	if(!task)
+		return result;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	if (task) {
 		result = get_task_root(task, path);
 		put_task_struct(task);
@@ -199,11 +247,33 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
 static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
 			    struct pid *pid, struct task_struct *task)
 {
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/*
 	 * Rely on struct seq_operations::show() being called once
 	 * per internal buffer allocation. See single_open(), traverse().
 	 */
 	BUG_ON(m->size < PAGE_SIZE);
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	m->count += get_cmdline(task, m->buf, PAGE_SIZE);
 	return 0;
 }
@@ -212,6 +282,30 @@ static int proc_pid_auxv(struct seq_file *m, struct pid_namespace *ns,
 			 struct pid *pid, struct task_struct *task)
 {
 	struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		if (mm && !IS_ERR(mm))
+			mmput(mm);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	if (mm && !IS_ERR(mm)) {
 		unsigned int nwords = 0;
 		do {
@@ -236,6 +330,27 @@ static int proc_pid_wchan(struct seq_file *m, struct pid_namespace *ns,
 	unsigned long wchan;
 	char symname[KSYM_NAME_LEN];
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	wchan = get_wchan(task);
 
 	if (wchan && ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)
@@ -277,6 +392,27 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
 	int err;
 	int i;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
 	if (!entries)
 		return -ENOMEM;
@@ -309,6 +445,27 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
 static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns,
 			      struct pid *pid, struct task_struct *task)
 {
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	seq_printf(m, "%llu %llu %lu\n",
 		   (unsigned long long)task->se.sum_exec_runtime,
 		   (unsigned long long)task->sched_info.run_delay,
@@ -325,8 +482,31 @@ static int lstats_show_proc(struct seq_file *m, void *v)
 	struct inode *inode = m->private;
 	struct task_struct *task = get_proc_task(inode);
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!task)
 		return -ESRCH;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	seq_puts(m, "Latency Top version : v0.1\n");
 	for (i = 0; i < 32; i++) {
 		struct latency_record *lr = &task->latency_record[i];
@@ -384,6 +564,25 @@ static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns,
 	unsigned long totalpages = totalram_pages + total_swap_pages;
 	unsigned long points = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if(!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	read_lock(&tasklist_lock);
 	if (pid_alive(task))
 		points = oom_badness(task, NULL, NULL, totalpages) *
@@ -614,7 +813,34 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
 	struct task_struct *task = get_proc_task(inode);
 	struct mm_struct *mm = ERR_PTR(-ESRCH);
 
+#ifdef CONFIG_RSBAC
+        enum  rsbac_adf_request_t rsbac_adf_req;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (task) {
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "calling ADF\n");
+		if (mode & PTRACE_MODE_ATTACH)
+		        rsbac_adf_req = R_TRACE;
+	        else
+		        rsbac_adf_req = R_GET_STATUS_DATA;
+		rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(rsbac_adf_req,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			put_pid(rsbac_target_id.process);
+			put_task_struct(task);
+			return ERR_PTR(-EPERM);
+		}
+		put_pid(rsbac_target_id.process);
+#endif
+
 		mm = mm_access(task, mode | PTRACE_MODE_FSCREDS);
 		put_task_struct(task);
 
@@ -658,9 +884,33 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
 	ssize_t copied;
 	char *page;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_adf_req = R_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!mm)
 		return 0;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (write)
+		rsbac_adf_req = R_MODIFY_SYSTEM_DATA;
+	else
+		rsbac_adf_req = R_GET_STATUS_DATA;
+	rsbac_target_id.process = proc_pid(file->f_path.dentry->d_inode);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_adf_req,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	page = (char *)__get_free_page(GFP_TEMPORARY);
 	if (!page)
 		return -ENOMEM;
@@ -759,10 +1009,37 @@ static ssize_t environ_read(struct file *file, char __user *buf,
 	int ret = 0;
 	struct mm_struct *mm = file->private_data;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	struct task_struct *rsbac_task;
+#endif
+
 	/* Ensure the process spawned far enough to have an environment. */
 	if (!mm || !mm->env_end)
 		return 0;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_task = get_proc_task(file->f_path.dentry->d_inode);
+	if (!rsbac_task)
+		return -ESRCH;
+	rsbac_target_id.process = get_task_pid(rsbac_task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(rsbac_task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+	put_task_struct(rsbac_task);
+#endif
+
 	page = (char *)__get_free_page(GFP_TEMPORARY);
 	if (!page)
 		return -ENOMEM;
@@ -824,8 +1101,31 @@ static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
 	size_t len;
 	unsigned long flags;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!task)
 		return -ESRCH;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	if (lock_task_sighand(task, &flags)) {
 		if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
 			oom_adj = OOM_ADJUST_MAX;
@@ -848,6 +1148,11 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf,
 	unsigned long flags;
 	int err;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	memset(buffer, 0, sizeof(buffer));
 	if (count > sizeof(buffer) - 1)
 		count = sizeof(buffer) - 1;
@@ -871,6 +1176,24 @@ static ssize_t oom_adj_write(struct file *file, const char __user *buf,
 		goto out;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		err = -EPERM;
+		goto out;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	task_lock(task);
 	if (!task->mm) {
 		err = -EINVAL;
@@ -1021,8 +1344,31 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
 	ssize_t length;
 	char tmpbuf[TMPBUFLEN];
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!task)
 		return -ESRCH;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
 			   from_kuid(file->f_cred->user_ns,
 				     audit_get_loginuid(task)));
@@ -1039,6 +1385,11 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
 	uid_t loginuid;
 	kuid_t kloginuid;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	rcu_read_lock();
 	if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) {
 		rcu_read_unlock();
@@ -1053,6 +1404,21 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf,
 		/* No partial writes. */
 		return -EINVAL;
 	}
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = proc_pid(inode);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	page = (char*)__get_free_page(GFP_TEMPORARY);
 	if (!page)
 		return -ENOMEM;
@@ -1361,9 +1727,32 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
 	struct mm_struct *mm;
 	struct file *exe_file;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	task = get_proc_task(d_inode(dentry));
 	if (!task)
 		return -ENOENT;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		return -EPERM;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	mm = get_task_mm(task);
 	put_task_struct(task);
 	if (!mm)
@@ -1501,6 +1890,11 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 	const struct cred *cred;
 	struct pid_namespace *pid = dentry->d_sb->s_fs_info;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	generic_fillattr(inode, stat);
 
 	rcu_read_lock();
@@ -1508,6 +1902,22 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 	stat->gid = GLOBAL_ROOT_GID;
 	task = pid_task(proc_pid(inode), PIDTYPE_PID);
 	if (task) {
+
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = proc_pid(inode);
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			rcu_read_unlock();
+			return -EPERM;
+		}
+#endif
+
 		if (!has_pid_permissions(pid, task, 2)) {
 			rcu_read_unlock();
 			/*
@@ -1665,6 +2075,11 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
 	struct inode *inode;
 	int status = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (flags & LOOKUP_RCU)
 		return -ECHILD;
 
@@ -1678,6 +2093,23 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
 	if (!task)
 		goto out_notask;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		status = -EPERM;
+		goto out;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
 	if (IS_ERR_OR_NULL(mm))
 		goto out;
@@ -2787,6 +3219,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsign
 	unsigned tgid;
 	struct pid_namespace *ns;
 
+#ifdef CONFIG_RSBAC_PROC_HIDE
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	tgid = name_to_int(&dentry->d_name);
 	if (tgid == ~0U)
 		goto out;
@@ -2800,6 +3237,23 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsign
 	if (!task)
 		goto out;
 
+#ifdef CONFIG_RSBAC_PROC_HIDE
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		result = -ENOENT;
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		goto out;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	result = proc_pid_instantiate(dir, dentry, task, NULL);
 	put_task_struct(task);
 out:
@@ -2858,6 +3312,11 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
 	struct pid_namespace *ns = file_inode(file)->i_sb->s_fs_info;
 	loff_t pos = ctx->pos;
 
+#ifdef CONFIG_RSBAC_PROC_HIDE
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (pos >= PID_MAX_LIMIT + TGID_OFFSET)
 		return 0;
 
@@ -2885,6 +3344,21 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
 		if (!has_pid_permissions(ns, iter.task, 2))
 			continue;
 
+#ifdef CONFIG_RSBAC_PROC_HIDE
+		rsbac_target_id.process = get_task_pid(iter.task, PIDTYPE_PID);
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			put_pid(rsbac_target_id.process);
+			continue;
+		}
+		put_pid(rsbac_target_id.process);
+#endif
+
 		len = snprintf(name, sizeof(name), "%d", iter.tgid);
 		ctx->pos = iter.tgid + TGID_OFFSET;
 		if (!proc_fill_cache(file, ctx, name, len,
@@ -3043,6 +3517,11 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
 	unsigned tid;
 	struct pid_namespace *ns;
 
+#ifdef CONFIG_RSBAC_PROC_HIDE
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!leader)
 		goto out_no_task;
 
@@ -3061,6 +3540,21 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry
 	if (!same_thread_group(leader, task))
 		goto out_drop_task;
 
+#ifdef CONFIG_RSBAC_PROC_HIDE
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		goto out_drop_task;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	result = proc_task_instantiate(dir, dentry, task, NULL);
 out_drop_task:
 	put_task_struct(task);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 91a4e64..a1b3349 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -31,6 +31,8 @@
 #include <asm/sections.h>
 #include "internal.h"
 
+#include <rsbac/hooks.h>
+
 #define CORE_STR "CORE"
 
 #ifndef ELF_CORE_EFLAGS
@@ -547,8 +549,27 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
 
 static int open_kcore(struct inode *inode, struct file *filp)
 {
+#ifdef CONFIG_RSBAC
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
+
+#ifdef CONFIG_RSBAC
+        rsbac_target_id.scd = ST_kmem;
+        rsbac_attribute_value.dummy = 0;
+        rsbac_pr_debug(aef, "calling ADF\n");
+        if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                              task_pid(current),
+                              T_SCD,
+                              rsbac_target_id,
+                              A_none,
+                              rsbac_attribute_value))
+          return -EPERM;
+#endif
+
 	if (kcore_need_update)
 		kcore_update_ram();
 	if (i_size_read(inode) != proc_root_kcore->size) {
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index d385412..3995ba9 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -11,6 +11,9 @@
 #include <linux/namei.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+
+#include <rsbac/hooks.h>
+
 #include "internal.h"
 
 static const struct dentry_operations proc_sys_dentry_operations;
@@ -419,11 +422,32 @@ static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, i
 	struct ctl_table_root *root = head->root;
 	int mode;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (root->permissions)
 		mode = root->permissions(head, table);
 	else
 		mode = table->mode;
 
+#ifdef CONFIG_RSBAC
+	if (op & 002) { /* write access */
+		rsbac_target_id.scd = ST_sysctl;
+		rsbac_attribute_value.mode = mode;
+		rsbac_pr_debug(aef, "[sysctl() etc.]: calling ADF\n");
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_mode,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+	}
+#endif
+
 	return test_perm(mode, op);
 }
 
diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c
index a5644c4..8893537 100644
--- a/fs/proc_namespace.c
+++ b/fs/proc_namespace.c
@@ -10,6 +10,9 @@
 #include <linux/nsproxy.h>
 #include <linux/security.h>
 #include <linux/fs_struct.h>
+
+#include <rsbac/hooks.h>
+
 #include "proc/internal.h" /* only for get_proc_task() in ->open() */
 
 #include "pnode.h"
@@ -240,9 +243,32 @@ static int mounts_open_common(struct inode *inode, struct file *file,
 	struct proc_mounts *p;
 	int ret = -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!task)
 		goto err;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = get_task_pid(task, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		put_pid(rsbac_target_id.process);
+		put_task_struct(task);
+		ret = -EPERM;
+		goto err;
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	task_lock(task);
 	nsp = task->nsproxy;
 	if (!nsp || !nsp->mnt_ns) {
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 86ded73..d2674bc 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -15,12 +15,18 @@
 #include <linux/syscalls.h>
 #include <linux/capability.h>
 #include <linux/quotaops.h>
+#include <rsbac/hooks.h>
 #include <linux/types.h>
 #include <linux/writeback.h>
 
 static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 				     qid_t id)
 {
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	switch (cmd) {
 	/* these commands do not require any special privilegues */
 	case Q_GETFMT:
@@ -29,17 +35,59 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 	case Q_XGETQSTAT:
 	case Q_XGETQSTATV:
 	case Q_XQUOTASYNC:
+#ifdef CONFIG_RSBAC
+		rsbac_target_id.scd = ST_quota;
+		rsbac_attribute_value.dummy = 0;
+		rsbac_pr_debug(aef, "[sys_quotactl()]: calling ADF\n");
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+#endif
 		break;
 	/* allow to query information for dquots we "own" */
 	case Q_GETQUOTA:
 	case Q_XGETQUOTA:
 		if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) ||
-		    (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))))
+		    (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id)))) {
+#ifdef CONFIG_RSBAC
+			rsbac_target_id.scd = ST_quota;
+			rsbac_attribute_value.dummy = 0;
+			rsbac_pr_debug(aef, "[sys_quotactl()]: calling ADF\n");
+			if (!rsbac_adf_request(R_GET_STATUS_DATA,
+						task_pid(current),
+						T_SCD,
+						rsbac_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				return -EPERM;
+			}
+#endif
 			break;
+		}
 		/*FALLTHROUGH*/
 	default:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
+
+#ifdef CONFIG_RSBAC
+		rsbac_target_id.scd = ST_quota;
+		rsbac_attribute_value.dummy = 0;
+		rsbac_pr_debug(aef, "[sys_quotactl()]: calling ADF\n");
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value))
+		{
+			return -EPERM;
+		}
+#endif
 	}
 
 	return security_quotactl(cmd, type, id, sb);
diff --git a/fs/read_write.c b/fs/read_write.c
index bfd1a5d..761c6b0 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -18,6 +18,12 @@
 #include <linux/compat.h>
 #include "internal.h"
 
+#ifdef CONFIG_RSBAC_RW
+#include <net/sock.h>
+#include <net/af_unix.h>
+#endif
+#include <rsbac/hooks.h>
+
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
@@ -441,6 +447,10 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
 {
 	ssize_t ret;
 
+#ifdef CONFIG_RSBAC_RW
+	struct rsbac_rw_req rsbac_rw_req_obj;
+#endif
+
 	if (!(file->f_mode & FMODE_READ))
 		return -EBADF;
 	if (!(file->f_mode & FMODE_CAN_READ))
@@ -451,8 +461,20 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
 	ret = rw_verify_area(READ, file, pos, count);
 	if (ret >= 0) {
 		count = ret;
+
+#ifdef CONFIG_RSBAC_RW
+		rsbac_rw_req_obj.rsbac_target = T_NONE;
+		rsbac_rw_req_obj.rsbac_request = R_READ;
+		if (!rsbac_handle_rw_req(file, &rsbac_rw_req_obj))
+			return -EPERM;
+#endif
+
 		ret = __vfs_read(file, buf, count, pos);
 		if (ret > 0) {
+#ifdef CONFIG_RSBAC_RW
+			rsbac_handle_rw_up(&rsbac_rw_req_obj);
+#endif
+
 			fsnotify_access(file);
 			add_rchar(current, ret);
 		}
@@ -524,6 +546,10 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
 {
 	ssize_t ret;
 
+#ifdef CONFIG_RSBAC_RW
+	struct rsbac_rw_req rsbac_rw_req_obj;
+#endif
+
 	if (!(file->f_mode & FMODE_WRITE))
 		return -EBADF;
 	if (!(file->f_mode & FMODE_CAN_WRITE))
@@ -534,9 +560,21 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
 	ret = rw_verify_area(WRITE, file, pos, count);
 	if (ret >= 0) {
 		count = ret;
+
+#ifdef CONFIG_RSBAC_RW
+		rsbac_rw_req_obj.rsbac_target = T_NONE;
+		rsbac_rw_req_obj.rsbac_request = R_WRITE;
+		if (!rsbac_handle_rw_req(file, &rsbac_rw_req_obj))
+			return -EPERM;
+#endif
+
 		file_start_write(file);
 		ret = __vfs_write(file, buf, count, pos);
 		if (ret > 0) {
+#ifdef CONFIG_RSBAC_RW
+			rsbac_handle_rw_up(&rsbac_rw_req_obj);
+#endif
+
 			fsnotify_modify(file);
 			add_wchar(current, ret);
 		}
@@ -783,6 +821,11 @@ static ssize_t do_readv_writev(int type, struct file *file,
 	io_fn_t fn;
 	iter_fn_t iter_fn;
 
+#ifdef CONFIG_RSBAC_RW
+	struct rsbac_rw_req rsbac_rw_req_obj;
+	rsbac_rw_req_obj.rsbac_target = T_NONE;
+#endif
+
 	ret = import_iovec(type, uvector, nr_segs,
 			   ARRAY_SIZE(iovstack), &iov, &iter);
 	if (ret < 0)
@@ -795,6 +838,19 @@ static ssize_t do_readv_writev(int type, struct file *file,
 	if (ret < 0)
 		goto out;
 
+#ifdef CONFIG_RSBAC_RW
+	if (type == READ)
+		rsbac_rw_req_obj.rsbac_request = R_READ;
+	else
+/* if type wouldn't be WRITE here it's going to be funny ;)
+   kernel itself does NOT check on it. */
+		rsbac_rw_req_obj.rsbac_request = R_WRITE;
+        if(!rsbac_handle_rw_req(file, &rsbac_rw_req_obj)) {
+		ret = -EPERM;
+		goto out;
+	}
+#endif
+
 	if (type == READ) {
 		fn = file->f_op->read;
 		iter_fn = file->f_op->read_iter;
@@ -814,6 +870,12 @@ static ssize_t do_readv_writev(int type, struct file *file,
 
 out:
 	kfree(iov);
+
+#ifdef CONFIG_RSBAC_RW
+	if (ret > 0)
+		rsbac_handle_rw_up(&rsbac_rw_req_obj);
+#endif
+
 	if ((ret + (type == READ)) > 0) {
 		if (type == READ)
 			fsnotify_access(file);
@@ -1162,6 +1224,15 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
 	ssize_t retval;
 	int fl;
 
+#ifdef CONFIG_RSBAC_RW
+	struct rsbac_rw_req rsbac_rw_req_obj1;
+	struct rsbac_rw_req rsbac_rw_req_obj2;
+	struct socket * sock1;
+	struct socket * sock2;
+	rsbac_rw_req_obj1.rsbac_target = T_NONE;
+	rsbac_rw_req_obj2.rsbac_target = T_NONE;
+#endif
+
 	/*
 	 * Get input file, and verify that it is ok..
 	 */
@@ -1184,6 +1255,29 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
 		goto fput_in;
 	count = retval;
 
+#ifdef CONFIG_RSBAC_RW
+/* i could have done it in few lines of code, but that's way it is MUCH faster and sendfile is mostly beeing used with network sockets */
+	if (S_ISSOCK(in.file->f_path.dentry->d_inode->i_mode)) {
+		sock1 = SOCKET_I(in.file->f_path.dentry->d_inode);
+		if ((sock1->ops) && (sock1->ops->family != AF_UNIX)) {
+			rsbac_rw_req_obj1.rsbac_target = T_NETOBJ;
+                        rsbac_rw_req_obj1.rsbac_target_id.netobj.sock_p = sock1;
+                        rsbac_rw_req_obj1.rsbac_target_id.netobj.local_addr = NULL;
+                        rsbac_rw_req_obj1.rsbac_target_id.netobj.local_len = 0;
+                        rsbac_rw_req_obj1.rsbac_target_id.netobj.remote_addr = NULL;
+                        rsbac_rw_req_obj1.rsbac_target_id.netobj.remote_len = 0;
+                        rsbac_rw_req_obj1.rsbac_attribute = A_sock_type;
+                        rsbac_rw_req_obj1.rsbac_attribute_value.sock_type = sock1->type;
+                }
+	}
+	rsbac_rw_req_obj1.rsbac_request = R_READ;
+	if(!rsbac_handle_rw_req(in.file, &rsbac_rw_req_obj1))
+	{
+		retval = -EPERM;
+		goto fput_in;
+	}
+#endif
+
 	/*
 	 * Get output file, and verify that it is ok..
 	 */
@@ -1202,6 +1296,28 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
 		goto fput_out;
 	count = retval;
 
+#ifdef CONFIG_RSBAC_RW
+	if (S_ISSOCK(out.file->f_path.dentry->d_inode->i_mode)) {
+		sock2 = SOCKET_I(out.file->f_path.dentry->d_inode);
+		if ((sock2->ops) && (sock2->ops->family != AF_UNIX)) {
+                        rsbac_rw_req_obj2.rsbac_target = T_NETOBJ;
+                        rsbac_rw_req_obj2.rsbac_target_id.netobj.sock_p = sock2;
+                        rsbac_rw_req_obj2.rsbac_target_id.netobj.local_addr = NULL;
+                        rsbac_rw_req_obj2.rsbac_target_id.netobj.local_len = 0;
+                        rsbac_rw_req_obj2.rsbac_target_id.netobj.remote_addr = NULL;
+                        rsbac_rw_req_obj2.rsbac_target_id.netobj.remote_len = 0;
+                        rsbac_rw_req_obj2.rsbac_attribute = A_sock_type;
+                        rsbac_rw_req_obj2.rsbac_attribute_value.sock_type = sock2->type;
+                }
+	}
+	rsbac_rw_req_obj2.rsbac_request = R_WRITE;
+	if(!rsbac_handle_rw_req(out.file, &rsbac_rw_req_obj2))
+	{
+		retval = -EPERM;
+		goto fput_out;
+	}
+#endif
+
 	if (!max)
 		max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
 
@@ -1244,6 +1360,11 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
 	if (pos > max)
 		retval = -EOVERFLOW;
 
+#ifdef CONFIG_RSBAC_RW
+	rsbac_handle_rw_up(&rsbac_rw_req_obj1);
+	rsbac_handle_rw_up(&rsbac_rw_req_obj2);
+#endif
+
 fput_out:
 	fdput(out);
 fput_in:
diff --git a/fs/readdir.c b/fs/readdir.c
index ced6791..a4c43ed 100644
--- a/fs/readdir.c
+++ b/fs/readdir.c
@@ -21,10 +21,27 @@
 
 #include <asm/uaccess.h>
 
+#ifdef CONFIG_RSBAC
+#include <net/sock.h>
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+#include "hfsplus/hfsplus_fs.h"
+#include "hfsplus/hfsplus_raw.h"
+#endif
+#endif
+
+#include <rsbac/hooks.h>
+#include <linux/namei.h>
+
 int iterate_dir(struct file *file, struct dir_context *ctx)
 {
 	struct inode *inode = file_inode(file);
 	int res = -ENOTDIR;
+
+#ifdef CONFIG_RSBAC
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!file->f_op->iterate)
 		goto out;
 
@@ -32,6 +49,23 @@ int iterate_dir(struct file *file, struct dir_context *ctx)
 	if (res)
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[old_readdir(), sys_getdents()]: calling ADF\n");
+	rsbac_target_id.dir.device = inode->i_sb->s_dev;
+	rsbac_target_id.dir.inode = inode->i_ino;
+	rsbac_target_id.dir.dentry_p = file->f_path.dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_READ,
+				task_pid(current),
+				T_DIR,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))	{
+		res = -EPERM;
+		goto out;
+	}
+#endif
+
 	res = mutex_lock_killable(&inode->i_mutex);
 	if (res)
 		goto out;
@@ -71,6 +105,9 @@ struct old_linux_dirent {
 struct readdir_callback {
 	struct dir_context ctx;
 	struct old_linux_dirent __user * dirent;
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	struct file * file;
+#endif
 	int result;
 };
 
@@ -84,6 +121,11 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen,
 
 	if (buf->result)
 		return -EINVAL;
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	if (!rsbac_handle_filldir(buf->file, name, namlen, ino))
+		return 0;
+#endif
+
 	d_ino = ino;
 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
 		buf->result = -EOVERFLOW;
@@ -120,6 +162,10 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
 	if (!f.file)
 		return -EBADF;
 
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	buf.file = f.file;
+#endif
+
 	error = iterate_dir(f.file, &buf.ctx);
 	if (buf.result)
 		error = buf.result;
@@ -145,6 +191,9 @@ struct getdents_callback {
 	struct dir_context ctx;
 	struct linux_dirent __user * current_dir;
 	struct linux_dirent __user * previous;
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	struct file * file;
+#endif
 	int count;
 	int error;
 };
@@ -162,6 +211,10 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
 	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
 		return -EINVAL;
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	if (!rsbac_handle_filldir(buf->file, name, namlen, ino))
+		return 0;
+#endif
 	d_ino = ino;
 	if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
 		buf->error = -EOVERFLOW;
@@ -212,6 +265,10 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
 	if (!f.file)
 		return -EBADF;
 
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	buf.file = f.file;
+#endif
+
 	error = iterate_dir(f.file, &buf.ctx);
 	if (error >= 0)
 		error = buf.error;
@@ -232,6 +289,9 @@ struct getdents_callback64 {
 	struct linux_dirent64 __user * previous;
 	int count;
 	int error;
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	struct file * file;
+#endif
 };
 
 static int filldir64(struct dir_context *ctx, const char *name, int namlen,
@@ -246,6 +306,12 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
 	buf->error = -EINVAL;	/* only used if we fail.. */
 	if (reclen > buf->count)
 		return -EINVAL;
+
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	if (!rsbac_handle_filldir(buf->file, name, namlen, ino))
+		return 0;
+#endif
+
 	dirent = buf->previous;
 	if (dirent) {
 		if (__put_user(offset, &dirent->d_off))
@@ -293,6 +359,10 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
 	if (!f.file)
 		return -EBADF;
 
+#ifdef CONFIG_RSBAC_FSOBJ_HIDE
+	buf.file = f.file;
+#endif
+
 	error = iterate_dir(f.file, &buf.ctx);
 	if (error >= 0)
 		error = buf.error;
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index b55a074..9492955 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -18,6 +18,7 @@
 #include "acl.h"
 #include "xattr.h"
 #include <linux/quotaops.h>
+#include <rsbac/hooks.h>
 
 #define INC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) { inc_nlink(i); if (i->i_nlink >= REISERFS_LINK_MAX) set_nlink(i, 1); }
 #define DEC_DIR_INODE_NLINK(i) if (i->i_nlink != 1) drop_nlink(i);
@@ -1042,6 +1043,11 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
 	 */
 	savelink = inode->i_nlink;
 
+#ifdef CONFIG_RSBAC_SECDEL
+	if (inode->i_nlink == 1)
+		rsbac_sec_del(dentry, TRUE);
+#endif
+
 	retval =
 	    reiserfs_cut_from_item(&th, &path, &de.de_entry_key, dir, NULL,
 				   0);
@@ -1416,6 +1422,11 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			journal_end(&th);
 			reiserfs_write_unlock(old_dir->i_sb);
 			return -EIO;
+#ifdef CONFIG_RSBAC_SECDEL
+		} else {
+			if (new_dentry_inode && (new_dentry_inode->i_nlink == 1))
+				rsbac_sec_del(new_dentry, TRUE);
+#endif
 		}
 
 		copy_item_head(&old_entry_ih, tp_item_head(&old_entry_path));
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index e87f9b5..c5002ce 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -991,6 +991,10 @@ static const struct dentry_operations xattr_lookup_poison_ops = {
 	.d_revalidate = xattr_hide_revalidate,
 };
 
+#ifdef CONFIG_RSBAC
+struct dentry * rsbac_lookup_one_len(const char * name, struct dentry * base, int len);
+#endif
+
 int reiserfs_lookup_privroot(struct super_block *s)
 {
 	struct dentry *dentry;
@@ -1038,8 +1042,13 @@ int reiserfs_xattr_init(struct super_block *s, int mount_flags)
 		if (!REISERFS_SB(s)->xattr_root) {
 			struct dentry *dentry;
 
+#ifdef CONFIG_RSBAC
+			dentry = rsbac_lookup_one_len(XAROOT_NAME, s->s_root,
+						strlen(XAROOT_NAME));
+#else
 			dentry = lookup_one_len(XAROOT_NAME, privroot,
 						strlen(XAROOT_NAME));
+#endif
 			if (!IS_ERR(dentry))
 				REISERFS_SB(s)->xattr_root = dentry;
 			else
diff --git a/fs/stat.c b/fs/stat.c
index cccc1aa..26d2941 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -18,8 +18,19 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
+#ifdef CONFIG_RSBAC
+#include <net/sock.h>
+#include <rsbac/hooks.h>
+#endif
+
 void generic_fillattr(struct inode *inode, struct kstat *stat)
 {
+
+#ifdef CONFIG_RSBAC_SYM_REDIR
+	char *rsbac_name;
+	int len = 0;
+#endif
+
 	stat->dev = inode->i_sb->s_dev;
 	stat->ino = inode->i_ino;
 	stat->mode = inode->i_mode;
@@ -27,6 +38,19 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
 	stat->uid = inode->i_uid;
 	stat->gid = inode->i_gid;
 	stat->rdev = inode->i_rdev;
+
+#ifdef CONFIG_RSBAC_SYM_REDIR
+	if (S_ISLNK(inode->i_mode)) {
+		rsbac_name = rsbac_symlink_redirect(inode, "", 0);
+		if (rsbac_name) {
+			len = strlen(rsbac_name);
+			kfree(rsbac_name);
+		}
+		stat->size = i_size_read(inode) + len;
+	}
+	else
+#endif
+
 	stat->size = i_size_read(inode);
 	stat->atime = inode->i_atime;
 	stat->mtime = inode->i_mtime;
@@ -66,9 +90,51 @@ int vfs_getattr(struct path *path, struct kstat *stat)
 {
 	int retval;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	retval = security_inode_getattr(path);
 	if (retval)
 		return retval;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_stat() etc.]: calling ADF\n");
+	rsbac_target_id.file.device = path->dentry->d_inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = path->dentry->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = path->dentry;
+	if (S_ISDIR(path->dentry->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(path->dentry->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(path->dentry->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(path->dentry->d_inode->i_mode)) {
+		if (path->dentry->d_inode->i_sb->s_magic == SOCKFS_MAGIC) {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			rsbac_target_id.ipc.id.id_nr = path->dentry->d_inode->i_ino;
+		} else {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = path->dentry->d_inode->i_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = path->dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = path->dentry;
+		}
+	} else
+		rsbac_target = T_FILE;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	return vfs_getattr_nosec(path, stat);
 }
 
@@ -320,6 +386,11 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
 	int empty = 0;
 	unsigned int lookup_flags = LOOKUP_EMPTY;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (bufsiz <= 0)
 		return -EINVAL;
 
@@ -332,6 +403,24 @@ retry:
 		if (inode->i_op->readlink) {
 			error = security_inode_readlink(path.dentry);
 			if (!error) {
+
+#ifdef CONFIG_RSBAC
+				rsbac_pr_debug(aef, "calling ADF\n");
+				rsbac_target_id.file.device = path.dentry->d_sb->s_dev;
+				rsbac_target_id.file.inode  = inode->i_ino;
+				rsbac_target_id.file.dentry_p = path.dentry;
+				rsbac_attribute_value.dummy = 0;
+				if (!rsbac_adf_request(R_GET_STATUS_DATA,
+							task_pid(current),
+							T_SYMLINK,
+							rsbac_target_id,
+							A_none,
+							rsbac_attribute_value)) {
+					path_put(&path);
+					return -EPERM;
+				}
+#endif
+
 				touch_atime(&path);
 				error = inode->i_op->readlink(path.dentry,
 							      buf, bufsiz);
diff --git a/fs/statfs.c b/fs/statfs.c
index 083dc0a..8f31aab 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -9,6 +9,8 @@
 #include <linux/uaccess.h>
 #include "internal.h"
 
+#include <rsbac/hooks.h>
+
 static int flags_by_mnt(int mnt_flags)
 {
 	int flags = 0;
@@ -50,9 +52,30 @@ static int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
 {
 	int retval;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!dentry->d_sb->s_op->statfs)
 		return -ENOSYS;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dev.type = D_block;
+	rsbac_target_id.dev.major = RSBAC_MAJOR(dentry->d_sb->s_dev);
+	rsbac_target_id.dev.minor = RSBAC_MINOR(dentry->d_sb->s_dev);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_DEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	memset(buf, 0, sizeof(*buf));
 	retval = security_sb_statfs(dentry);
 	if (retval)
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 5bccdf6..0ef7d8a 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -21,6 +21,8 @@
 #include "sysfs.h"
 #include "../kernfs/kernfs-internal.h"
 
+#include <rsbac/hooks.h>
+
 /*
  * Determine ktype->sysfs_ops for the given kernfs_node.  This function
  * must be called while holding an active reference.
@@ -47,6 +49,25 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
 	ssize_t count;
 	char *buf;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sysfs_kf_seq_show()]: calling ADF\n");
+	rsbac_target_id.scd = ST_sysfs;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_owner,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	/* acquire buffer and ensure that it's >= PAGE_SIZE and clear */
 	count = seq_get_buf(sf, &buf);
 	if (count < PAGE_SIZE) {
@@ -86,6 +107,11 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
 	struct kobject *kobj = of->kn->parent->priv;
 	loff_t size = file_inode(of->file)->i_size;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!count)
 		return 0;
 
@@ -99,6 +125,20 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
 	if (!battr->read)
 		return -EIO;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sysfs_kf_bin_read()]: calling ADF\n");
+	rsbac_target_id.scd = ST_sysfs;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_owner,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	return battr->read(of->file, kobj, battr, buf, pos, count);
 }
 
@@ -135,9 +175,28 @@ static ssize_t sysfs_kf_write(struct kernfs_open_file *of, char *buf,
 	const struct sysfs_ops *ops = sysfs_file_ops(of->kn);
 	struct kobject *kobj = of->kn->parent->priv;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!count)
 		return 0;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sysfs_kf_write()]: calling ADF\n");
+	rsbac_target_id.scd = ST_sysfs;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	return ops->store(kobj, of->kn->priv, buf, count);
 }
 
@@ -149,6 +208,11 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
 	struct kobject *kobj = of->kn->parent->priv;
 	loff_t size = file_inode(of->file)->i_size;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (size) {
 		if (size <= pos)
 			return -EFBIG;
@@ -160,6 +224,20 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
 	if (!battr->write)
 		return -EIO;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sysfs_kf_bin_write()]: calling ADF\n");
+	rsbac_target_id.scd = ST_sysfs;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	return battr->write(of->file, kobj, battr, buf, pos, count);
 }
 
@@ -169,6 +247,25 @@ static int sysfs_kf_bin_mmap(struct kernfs_open_file *of,
 	struct bin_attribute *battr = of->kn->priv;
 	struct kobject *kobj = of->kn->parent->priv;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sysfs_kf_bin_write()]: calling ADF\n");
+	rsbac_target_id.scd = ST_sysfs;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	return battr->mmap(of->file, kobj, battr, vma);
 }
 
diff --git a/fs/utimes.c b/fs/utimes.c
index 61abc30..a0f7a4e 100644
--- a/fs/utimes.c
+++ b/fs/utimes.c
@@ -10,6 +10,7 @@
 #include <linux/syscalls.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <rsbac/hooks.h>
 
 #ifdef __ARCH_WANT_SYS_UTIME
 
@@ -55,6 +56,12 @@ static int utimes_common(struct path *path, struct timespec *times)
 	struct inode *inode = path->dentry->d_inode;
 	struct inode *delegated_inode = NULL;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = mnt_want_write(path->mnt);
 	if (error)
 		goto out;
@@ -96,12 +103,42 @@ static int utimes_common(struct path *path, struct timespec *times)
                 if (IS_IMMUTABLE(inode))
 			goto mnt_drop_write_and_out;
 
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+		if (!rsbac_dac_part_disabled(path->dentry))
+#endif
 		if (!inode_owner_or_capable(inode)) {
 			error = inode_permission(inode, MAY_WRITE);
 			if (error)
 				goto mnt_drop_write_and_out;
 		}
 	}
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = inode->i_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = path->dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_ACCESS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		error = -EPERM;
+		goto mnt_drop_write_and_out;
+	}
+#endif
+
 retry_deleg:
 	mutex_lock(&inode->i_mutex);
 	error = notify_change(path->dentry, &newattrs, &delegated_inode);
diff --git a/fs/xattr.c b/fs/xattr.c
index c721960..4779575 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -24,6 +24,8 @@
 
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 /*
  * Check permissions for extended attribute access.  This is a bit complicated
  * because different namespaces have very different rules.
@@ -124,11 +126,41 @@ vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 {
 	struct inode *inode = dentry->d_inode;
 	int error;
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	error = xattr_permission(inode, name, MAY_WRITE);
 	if (error)
 		return error;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_*setxattr()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	mutex_lock(&inode->i_mutex);
 	error = security_inode_setxattr(dentry, name, value, size, flags);
 	if (error)
@@ -233,6 +265,12 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
 	struct inode *inode = dentry->d_inode;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = xattr_permission(inode, name, MAY_READ);
 	if (error)
 		return error;
@@ -241,6 +279,31 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
 	if (error)
 		return error;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_*getxattr()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_PERMISSIONS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN)) {
 		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
@@ -267,10 +330,41 @@ ssize_t
 vfs_listxattr(struct dentry *d, char *list, size_t size)
 {
 	ssize_t error;
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	error = security_inode_listxattr(d);
 	if (error)
 		return error;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_*listxattr()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(d->d_inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(d->d_inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(d->d_inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(d->d_inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = d->d_sb->s_dev;
+	rsbac_target_id.file.inode  = d->d_inode->i_ino;
+	rsbac_target_id.file.dentry_p = d;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_PERMISSIONS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))	{
+		return -EPERM;
+	}
+#endif
+
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op->listxattr) {
 		error = d->d_inode->i_op->listxattr(d, list, size);
@@ -289,6 +383,12 @@ vfs_removexattr(struct dentry *dentry, const char *name)
 	struct inode *inode = dentry->d_inode;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!inode->i_op->removexattr)
 		return -EOPNOTSUPP;
 
@@ -296,6 +396,31 @@ vfs_removexattr(struct dentry *dentry, const char *name)
 	if (error)
 		return error;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_*removexattr()]: calling ADF\n");
+	rsbac_target = T_FILE;
+	if (S_ISDIR(inode->i_mode))
+		rsbac_target = T_DIR;
+	else if (S_ISFIFO(inode->i_mode))
+		rsbac_target = T_FIFO;
+	else if (S_ISLNK(inode->i_mode))
+		rsbac_target = T_SYMLINK;
+	else if (S_ISSOCK(inode->i_mode))
+		rsbac_target = T_UNIXSOCK;
+	rsbac_target_id.file.device = dentry->d_sb->s_dev;
+	rsbac_target_id.file.inode  = inode->i_ino;
+	rsbac_target_id.file.dentry_p = dentry;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	mutex_lock(&inode->i_mutex);
 	error = security_inode_removexattr(dentry, name);
 	if (error) {
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 3b79859..01dbaf0 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -306,7 +306,11 @@ xfs_readlink_by_handle(
 	error = xfs_readlink(XFS_I(d_inode(dentry)), link);
 	if (error)
 		goto out_kfree;
+#ifdef CONFIG_RSBAC_SYM_REDIR
+	error = rsbac_readlink_copy(hreq->ohandle, olen, link, dentry->d_inode);
+#else
 	error = readlink_copy(hreq->ohandle, olen, link);
+#endif
 	if (error)
 		goto out_kfree;
 
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 4e4d651..ed27067 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -78,6 +78,8 @@ xfs_initxattrs(
 	return error;
 }
 
+#include <rsbac/hooks.h>
+
 /*
  * Hook in SELinux.  This is not quite correct yet, what we really need
  * here (as we do for default ACLs) is a mechanism by which creation of
@@ -327,6 +329,11 @@ xfs_vn_unlink(
 	struct xfs_name	name;
 	int		error;
 
+#ifdef CONFIG_RSBAC_SECDEL
+	if (dentry->d_inode->i_nlink == 1)
+		rsbac_sec_del(dentry, FALSE);
+#endif
+
 	xfs_dentry_to_name(&name, dentry, 0);
 
 	error = xfs_remove(XFS_I(dir), &name, XFS_I(d_inode(dentry)));
@@ -394,6 +401,10 @@ xfs_vn_rename(
 	struct xfs_name	oname;
 	struct xfs_name	nname;
 
+#ifdef CONFIG_RSBAC_SECDEL
+	struct xfs_inode *cip;
+#endif
+
 	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
 		return -EINVAL;
 
@@ -404,6 +415,27 @@ xfs_vn_rename(
 	xfs_dentry_to_name(&oname, odentry, omode);
 	xfs_dentry_to_name(&nname, ndentry, d_inode(odentry)->i_mode);
 
+#ifdef CONFIG_RSBAC_SECDEL
+	/* RSBAC secure delete code. in the event of overwritting existing
+	 * file with sec_del flag set, its blocks will be deallocated so we
+	 * have to overwrite their content. since XFS does all the necessary
+	 * checks on the layer below linux VFS, operating on vnodes
+	 * i decided to implement my own set of checks here, so we can see
+	 * if the existing file is being overwritten.
+	 * inspired by ext2/3/4 and jfs code. michal@rsbac.org
+	 */
+
+	if (new_inode) {
+		if (new_inode->i_nlink == 1) {
+			if (!xfs_lookup(XFS_I(ndir), &nname, &cip, NULL)) {
+				IRELE(cip);
+				if(!S_ISDIR(new_inode->i_mode))
+					rsbac_sec_del(ndentry, TRUE);
+			}
+		}
+	}
+#endif
+
 	return xfs_rename(XFS_I(odir), &oname, XFS_I(d_inode(odentry)),
 			  XFS_I(ndir), &nname,
 			  new_inode ? XFS_I(new_inode) : NULL, flags);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 31c3d81..01e648f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2713,6 +2713,9 @@ extern const struct file_operations generic_ro_fops;
 #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
 
 extern int readlink_copy(char __user *, int, const char *);
+#ifdef CONFIG_RSBAC_SYM_REDIR
+extern int rsbac_readlink_copy(char __user *, int, const char *, struct inode *);
+#endif
 extern int page_readlink(struct dentry *, char __user *, int);
 extern void *page_follow_link_light(struct dentry *, struct nameidata *);
 extern void page_put_link(struct dentry *, struct nameidata *, void *);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b6c0334..f231233 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -62,6 +62,10 @@ struct sched_param {
 
 #include <asm/processor.h>
 
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_JAIL_LOG_MISSING)
+#include <rsbac/log_cap.h>
+#endif
+
 #define SCHED_ATTR_SIZE_VER0	48	/* sizeof first published struct */
 
 /*
@@ -2523,7 +2527,11 @@ extern int do_execveat(int, struct filename *,
 		       const char __user * const __user *,
 		       const char __user * const __user *,
 		       int);
+#ifdef CONFIG_RSBAC
+extern long do_fork(unsigned long long, unsigned long, unsigned long, int __user *, int __user *);
+#else
 extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *);
+#endif
 struct task_struct *fork_idle(int);
 extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
diff --git a/include/rsbac/aci.h b/include/rsbac/aci.h
new file mode 100644
index 0000000..0f01595
--- /dev/null
+++ b/include/rsbac/aci.h
@@ -0,0 +1,153 @@
+/******************************* */
+/* Rule Set Based Access Control */
+/* Author and (c) 1999-2015:     */
+/*   Amon Ott <ao@rsbac.org>     */
+/* API: Data structures          */
+/* and functions for Access      */
+/* Control Information           */
+/* Last modified: 04/Jan/2016    */
+/******************************* */
+
+#ifndef __RSBAC_ACI_H
+#define __RSBAC_ACI_H
+
+#include <rsbac/types.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+
+/***************************************************/
+/*                   Prototypes                    */
+/***************************************************/
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+/****************************************************************************/
+/* Initialization, including ACI restoration for all mounted devices from   */
+/* disk. After this call, all ACI is kept in memory for performance reasons,*/
+/* but user and file/dir object ACI are written to disk on every change.    */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern int rsbac_init(kdev_t root_dev);
+#else
+extern int rsbac_init(kdev_t root_dev) __init;
+#endif
+
+/* Notify RSBAC of new kernel thread */
+int rsbac_kthread_notify(rsbac_pid_t pid);
+
+/* To turn RSBAC off on umount of root device */
+void rsbac_off(void);
+
+/* For other kernel parts to check, whether RSBAC was initialized correctly */
+extern rsbac_boolean_t rsbac_initialized;
+
+static inline rsbac_boolean_t rsbac_is_initialized(void)
+{
+  return rsbac_initialized;
+}
+
+/* Check if the device exists */
+int rsbac_check_device(kdev_t kdev);
+
+/* Is device writable? */
+rsbac_boolean_t rsbac_writable(struct super_block * sb_p);
+
+/* When mounting a device, its ACI must be read and added to the ACI lists. */
+int rsbac_mount(struct vfsmount * vfsmount_p);
+
+/* When umounting a device, its ACI must be removed from the ACI lists. */
+int rsbac_umount(struct vfsmount * vfsmount_p);
+
+/* On pivot_root, we must unblock the dentry tree of the old root */
+/* by putting all cached rsbac.dat dentries */
+int rsbac_free_dat_dentries(void);
+
+/* Some information about the current status is also available */
+int rsbac_stats(void);
+
+/* Trigger internal consistency check (int: if != 0: correct errors) */
+int rsbac_check(int correct, int check_inode);
+
+/* RSBAC attribute saving to disk can be triggered from outside
+ * param: call lock_kernel() before disk access?
+ */
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+int rsbac_write(void);
+#endif
+
+/* get the parent of a target
+ * returns -RSBAC_EINVALIDTARGET for non-fs targets
+ * and -RSBAC_ENOTFOUND, if no parent available
+ * In kernels >= 2.4.0, device_p->d_covers is used and the item is properly
+ * locked for reading, so never call with a write lock held on device_p!
+ */
+int rsbac_get_parent(enum rsbac_target_t target,
+                     union rsbac_target_id_t tid,
+                     enum rsbac_target_t * parent_target_p,
+                     union rsbac_target_id_t * parent_tid_p);
+
+/* Invalidate cached attribute values for one or all filesystem objects */
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+int rsbac_fd_cache_invalidate(struct rsbac_fs_file_t * file_p);
+
+int rsbac_fd_cache_invalidate_device(kdev_t kdev);
+
+int rsbac_fd_cache_invalidate_all(void);
+#endif
+
+/****************************************************************************/
+/* For objects, users and processes all manipulation is encapsulated by the */
+/* function calls rsbac_set_attr, rsbac_get_attr and rsbac_remove_target.   */
+                          
+int rsbac_ta_get_attr(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_switch_target_t module,
+  enum rsbac_target_t target,
+  union rsbac_target_id_t tid,
+  enum rsbac_attribute_t attr,
+  union rsbac_attribute_value_t * value,
+  rsbac_boolean_t inherit);
+
+#define rsbac_get_attr(module, target, tid, attr, value, inherit) \
+  rsbac_ta_get_attr(0, module, target, tid, attr, value, inherit)
+
+int rsbac_ta_set_attr(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_switch_target_t module,
+  enum rsbac_target_t target,
+  union rsbac_target_id_t tid,
+  enum rsbac_attribute_t attr,
+  union rsbac_attribute_value_t value);
+
+#define rsbac_set_attr(module, target, tid, attr, value) \
+  rsbac_ta_set_attr(0, module, target, tid, attr, value)
+
+/* All RSBAC targets should be removed, if no longer needed, to prevent     */
+/* memory wasting.                                                          */
+
+int rsbac_ta_remove_target(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_target_t target,
+  union rsbac_target_id_t tid);
+
+#define rsbac_remove_target(target, tid) \
+  rsbac_ta_remove_target(0, target, tid)
+
+int rsbac_ta_list_all_dev(rsbac_list_ta_number_t ta_number,
+                          struct rsbac_dev_desc_t ** id_pp);
+
+int rsbac_ta_list_all_user(rsbac_list_ta_number_t ta_number,
+                           rsbac_uid_t ** id_pp);
+
+int rsbac_ta_list_all_ipc(rsbac_list_ta_number_t ta_number,
+			  struct rsbac_ipc_t ** id_pp);
+	
+int rsbac_ta_list_all_group(rsbac_list_ta_number_t ta_number,
+                            rsbac_gid_t ** id_pp);
+
+int rsbac_mark_kthread(rsbac_pid_t pid);
+int rsbac_kthreads_init(void);
+#endif
diff --git a/include/rsbac/aci_data_structures.h b/include/rsbac/aci_data_structures.h
new file mode 100644
index 0000000..ff0ced2
--- /dev/null
+++ b/include/rsbac/aci_data_structures.h
@@ -0,0 +1,1736 @@
+/**************************************/
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016: Amon Ott */
+/* Data structures                    */
+/* Last modified: 07/Jan/2016         */
+/**************************************/
+
+#ifndef __RSBAC_DATA_STRUC_H
+#define __RSBAC_DATA_STRUC_H
+
+#ifdef __KERNEL__		/* only include in kernel code */
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/semaphore.h>
+#include <linux/sched.h>
+#include <rsbac/types.h>
+#include <linux/spinlock.h>
+#include <rsbac/rc_types.h>
+#include <rsbac/aci.h>
+#include <rsbac/debug.h>
+#include <rsbac/lists.h>
+#endif				/* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+/* List to keep mounts before init, so that we can rsbac_mount them at init */
+
+struct rsbac_mount_list_t {
+	struct vfsmount * vfsmount_p;
+	struct rsbac_mount_list_t * next;
+};
+
+/* First of all we define dirname and filenames for saving the ACIs to disk. */
+/* The path must be a valid single dir name! Each mounted device gets its    */
+/* own file set, residing in 'DEVICE_ROOT/RSBAC_ACI_PATH/'.                  */
+/* The dynamic data structures for RC and ACL are kept in their own files.   */
+/* All user access to these files will be denied.                            */
+/* Backups are kept in FILENAMEb.                                            */
+
+#define RSBAC_LOG_BUF_LEN (16384)
+
+#define RSBAC_ACI_PATH          "rsbac.dat"
+
+#define RSBAC_GEN_FD_NAME       "fd_gen"
+#define RSBAC_GEN_OLD_FD_NAME   "fd_gen."
+#define RSBAC_MAC_FD_NAME       "fd_mac"
+#define RSBAC_MAC_OLD_FD_NAME   "fd_mac."
+#define RSBAC_DAZ_FD_NAME       "fd_dazt"
+#define RSBAC_DAZ_OLD_FD_NAME   "fd_dazt."
+#define RSBAC_DAZ_SCANNED_FD_NAME "fd_dazs"
+#define RSBAC_DAZ_SCANNED_OLD_FD_NAME "fd_dazs."
+#define RSBAC_FF_FD_NAME        "fd_ff"
+#define RSBAC_FF_OLD_FD_NAME    "fd_ff."
+#define RSBAC_RC_FD_NAME        "fd_rc"
+#define RSBAC_RC_OLD_FD_NAME    "fd_rc."
+#define RSBAC_AUTH_FD_NAME      "fd_auth"
+#define RSBAC_AUTH_OLD_FD_NAME  "fd_auth."
+#define RSBAC_CAP_FD_NAME       "fd_cap"
+#define RSBAC_CAP_OLD_FD_NAME   "fd_cap."
+#define RSBAC_PAX_FD_NAME       "fd_pax"
+#define RSBAC_PAX_OLD_FD_NAME   "fd_pax."
+#define RSBAC_RES_FD_NAME       "fd_res"
+#define RSBAC_RES_OLD_FD_NAME   "fd_res."
+#define RSBAC_UDF_FD_NAME       "fd_udft"
+#define RSBAC_UDF_CHECKED_FD_NAME "fd_udfc"
+
+#define RSBAC_ACI_USER_NAME     "useraci"
+/* dir creation mode for discretionary access control: no rights*/
+#define RSBAC_ACI_DIR_MODE       (S_IFDIR)
+/* file creation mode for discretionary access control: rw for user only*/
+#define RSBAC_ACI_FILE_MODE      (S_IFREG | S_IRUSR | S_IWUSR)
+/* minimal mem chunk size available to try write_partial_fd_list, else defer */
+#define RSBAC_MIN_WRITE_FD_BUF_LEN 32768
+/* max size for write_chunks */
+#define RSBAC_MAX_WRITE_CHUNK ((1 << 15) - 1)
+
+#define RSBAC_GEN_NR_FD_LIST_HASH_BITS  1
+#define RSBAC_MAC_NR_FD_LIST_HASH_BITS  2
+#define RSBAC_DAZ_NR_FD_LIST_HASH_BITS   1
+#define RSBAC_DAZ_SCANNED_NR_FD_LIST_HASH_BITS 2
+#define RSBAC_FF_NR_FD_LIST_HASH_BITS   2
+#define RSBAC_RC_NR_FD_LIST_HASH_BITS   2
+#define RSBAC_AUTH_NR_FD_LIST_HASH_BITS 1
+#define RSBAC_CAP_NR_FD_LIST_HASH_BITS  1
+#define RSBAC_PAX_NR_FD_LIST_HASH_BITS  1
+#define RSBAC_RES_NR_FD_LIST_HASH_BITS  1
+#define RSBAC_UDF_NR_FD_LIST_HASH_BITS   1
+#define RSBAC_UDF_CHECKED_NR_FD_LIST_HASH_BITS 2
+
+#define RSBAC_P_LIST_HASH_BITS 4
+
+#ifdef CONFIG_RSBAC_INIT_THREAD
+/* Check and set init timeout */
+#if CONFIG_RSBAC_MAX_INIT_TIME >= 5
+#define RSBAC_MAX_INIT_TIME CONFIG_RSBAC_MAX_INIT_TIME
+#else
+#define RSBAC_MAX_INIT_TIME 5
+#endif
+#endif				/* INIT_THREAD */
+
+#endif				/* __KERNEL__ */
+
+/* The following structures privide attributes for all possible targets.  */
+/* The data structures are kept in double linked lists, and are optimized */
+/* by hash functions.                                                     */
+
+/* Only ATTRIBUTES are saved in those structures, that are saved to disk, */
+/* because saving sublists means breaking up the structures for every     */
+/* single list.                                                           */
+/* If a list of policy dependant items is to be stored, this is done in   */
+/* the policy dependant data structures. Here only an ID as a handle is   */
+/* supported.                                                             */
+
+/* OK, first we define the file/dir ACI, holding all file/dir information */
+/* the ADF needs for decisions.                                           */
+
+/* Caution: whenever ACI changes, version and old_version should be increased!            */
+
+// #define CONFIG_RSBAC_FD_CACHE 1
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+#define RSBAC_FD_CACHE_NAME       "fd_cache."
+#define RSBAC_FD_CACHE_VERSION 1
+#define RSBAC_FD_CACHE_KEY 3626114
+#endif
+
+#define RSBAC_GEN_FD_ACI_VERSION 8
+#define RSBAC_GEN_FD_ACI_KEY 1001
+struct rsbac_gen_fd_aci_t {
+	rsbac_log_array_t log_array_low;	/* file/dir based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+	rsbac_request_vector_t log_program_based;	/* Program based logging */
+	rsbac_enum_t symlink_add_remote_ip;
+	rsbac_enum_t symlink_add_uid;
+	rsbac_enum_t symlink_add_mac_level;
+	rsbac_enum_t symlink_add_rc_role;
+	rsbac_enum_t linux_dac_disable;
+	rsbac_fake_root_uid_int_t fake_root_uid;
+	rsbac_uid_t auid_exempt;
+	rsbac_um_set_t vset;
+};
+#define DEFAULT_GEN_FD_ACI \
+    { \
+      .log_array_low = -1, \
+      .log_array_high = -1, \
+      .log_program_based = 0, \
+      .symlink_add_uid = FALSE, \
+      .symlink_add_mac_level = FALSE, \
+      .symlink_add_rc_role = FALSE, \
+      .linux_dac_disable = LDD_inherit, \
+      .fake_root_uid = FR_off, \
+      .auid_exempt = RSBAC_NO_USER, \
+      .vset = RSBAC_UM_VIRTUAL_KEEP, \
+    }
+
+#define DEFAULT_GEN_ROOT_DIR_ACI \
+    { \
+      .log_array_low = -1, \
+      .log_array_high = -1, \
+      .log_program_based = 0, \
+      .symlink_add_uid = FALSE, \
+      .symlink_add_mac_level = FALSE, \
+      .symlink_add_rc_role = FALSE, \
+      .linux_dac_disable = LDD_false, \
+      .fake_root_uid = FR_off, \
+      .auid_exempt = RSBAC_NO_USER, \
+      .vset = RSBAC_UM_VIRTUAL_KEEP, \
+    }
+
+#define RSBAC_GEN_FD_OLD_ACI_VERSION 7
+struct rsbac_gen_fd_old_aci_t {
+	rsbac_log_array_t log_array_low;	/* file/dir based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+	rsbac_request_vector_t log_program_based;	/* Program based logging */
+	rsbac_enum_t symlink_add_remote_ip;
+	rsbac_enum_t symlink_add_uid;
+	rsbac_enum_t symlink_add_mac_level;
+	rsbac_enum_t symlink_add_rc_role;
+	rsbac_enum_t linux_dac_disable;
+	rsbac_fake_root_uid_int_t fake_root_uid;
+	rsbac_old_uid_t auid_exempt;
+};
+#define RSBAC_GEN_FD_OLD_OLD_ACI_VERSION 6
+struct rsbac_gen_fd_old_old_aci_t {
+	rsbac_log_array_t log_array_low;	/* file/dir based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+	rsbac_request_vector_t log_program_based;	/* Program based logging */
+	rsbac_enum_t symlink_add_uid;
+	rsbac_enum_t symlink_add_mac_level;
+	rsbac_enum_t symlink_add_rc_role;
+	rsbac_enum_t linux_dac_disable;
+	rsbac_fake_root_uid_int_t fake_root_uid;
+	rsbac_old_uid_t auid_exempt;
+};
+
+#define RSBAC_GEN_FD_OLD_OLD_OLD_ACI_VERSION 5
+struct rsbac_gen_fd_old_old_old_aci_t {
+	rsbac_log_array_t log_array_low;	/* file/dir based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+	rsbac_request_vector_t log_program_based;	/* Program based logging */
+	rsbac_enum_t symlink_add_uid;
+	rsbac_enum_t symlink_add_mac_level;
+	rsbac_enum_t symlink_add_rc_role;
+	rsbac_enum_t linux_dac_disable;
+	rsbac_fake_root_uid_int_t fake_root_uid;
+};
+
+#if defined(CONFIG_RSBAC_MAC)
+#define RSBAC_MAC_FD_ACI_VERSION 5
+#define RSBAC_MAC_FD_ACI_KEY 1001
+struct rsbac_mac_fd_aci_t {
+	rsbac_security_level_t sec_level;	/* MAC */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+	rsbac_mac_auto_int_t mac_auto;	/* auto-adjust current level */
+	rsbac_boolean_int_t mac_prop_trusted;	/* Keep trusted flag when executing this file */
+	rsbac_mac_file_flags_t mac_file_flags;	/* allow write_up, read_up etc. to it */
+};
+
+#define RSBAC_MAC_FD_OLD_ACI_VERSION 4
+struct rsbac_mac_fd_old_aci_t {
+	rsbac_security_level_t sec_level;	/* MAC */
+	rsbac_uid_t mac_trusted_for_user;	/* MAC (for FILE only) */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+	rsbac_mac_auto_int_t mac_auto;	/* auto-adjust current level */
+	rsbac_boolean_int_t mac_prop_trusted;	/* Keep trusted flag when executing this file */
+	rsbac_mac_file_flags_t mac_file_flags;	/* allow write_up, read_up etc. to it */
+};
+
+#define RSBAC_MAC_FD_OLD_OLD_ACI_VERSION 3
+struct rsbac_mac_fd_old_old_aci_t {
+	rsbac_security_level_t sec_level;	/* MAC */
+	rsbac_uid_t mac_trusted_for_user;	/* MAC (for FILE only) */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+	rsbac_mac_auto_int_t mac_auto;	/* auto-adjust current level */
+	rsbac_boolean_int_t mac_prop_trusted;	/* Keep trusted flag when executing this file */
+	rsbac_boolean_int_t mac_shared;	/* Shared dir, i.e., allow write_up to it */
+};
+
+#define RSBAC_MAC_FD_OLD_OLD_OLD_ACI_VERSION 2
+struct rsbac_mac_fd_old_old_old_aci_t {
+	rsbac_security_level_t sec_level;	/* MAC */
+	rsbac_uid_t mac_trusted_for_user;	/* MAC (for FILE only) */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+	rsbac_mac_auto_int_t mac_auto;	/* auto-adjust current level */
+};
+
+#define DEFAULT_MAC_FD_ACI_INH \
+    { \
+      .sec_level = SL_inherit, \
+      .mac_categories = RSBAC_MAC_INHERIT_CAT_VECTOR, \
+      .mac_auto = MA_inherit, \
+      .mac_prop_trusted = FALSE, \
+      .mac_file_flags = 0, \
+    }
+#define DEFAULT_MAC_FD_ACI_NO_INH \
+    { \
+      .sec_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_auto = MA_yes, \
+      .mac_prop_trusted = FALSE, \
+      .mac_file_flags = 0, \
+    }
+
+#ifdef CONFIG_RSBAC_MAC_DEF_INHERIT
+#define DEFAULT_MAC_FD_ACI DEFAULT_MAC_FD_ACI_INH
+#else
+#define DEFAULT_MAC_FD_ACI DEFAULT_MAC_FD_ACI_NO_INH
+#endif				/* MAC_DEF_INHERIT */
+
+#define DEFAULT_MAC_ROOT_DIR_ACI \
+    { \
+      .sec_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_auto = MA_yes, \
+      .mac_prop_trusted = FALSE, \
+      .mac_file_flags = 0, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+#define RSBAC_DAZ_FD_ACI_VERSION 2
+#define RSBAC_DAZ_FD_OLD_ACI_VERSION 1
+#define RSBAC_DAZ_FD_ACI_KEY 10535
+#define RSBAC_DAZ_CACHE_CLEANUP_INTERVAL 86400
+#define RSBAC_DAZ_SCANNED_FD_ACI_VERSION 1
+struct rsbac_daz_fd_aci_t            
+  {
+    rsbac_daz_scanner_t daz_scanner;       /* DAZ (for FILE only) */
+    rsbac_daz_do_scan_t daz_do_scan;
+  };
+
+struct rsbac_daz_fd_old_aci_t            
+  {
+    rsbac_daz_scanner_t   daz_scanner;       /* DAZ (for FILE only) (boolean) */
+  };
+
+#define DEFAULT_DAZ_FD_ACI \
+    { \
+      .daz_scanner = FALSE, \
+      .daz_do_scan = DEFAULT_DAZ_FD_DO_SCAN \
+    }
+
+#define DEFAULT_DAZ_ROOT_DIR_ACI \
+    { \
+      .daz_scanner = FALSE, \
+      .daz_do_scan = DEFAULT_DAZ_FD_ROOT_DO_SCAN \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+#define RSBAC_FF_FD_ACI_VERSION 1
+#define RSBAC_FF_FD_ACI_KEY 1001
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+#define RSBAC_RC_FD_ACI_VERSION 1
+#define RSBAC_RC_FD_ACI_KEY 1001
+struct rsbac_rc_fd_aci_t {
+	rsbac_rc_type_id_t rc_type_fd;	/* RC */
+	rsbac_rc_role_id_t rc_force_role;	/* RC */
+	rsbac_rc_role_id_t rc_initial_role;	/* RC */
+};
+
+#define DEFAULT_RC_FD_ACI \
+    { \
+      .rc_type_fd = RC_type_inherit_parent, \
+      .rc_force_role = RC_default_force_role, \
+      .rc_initial_role = RC_default_initial_role, \
+    }
+#define DEFAULT_RC_ROOT_DIR_ACI \
+    { \
+      .rc_type_fd = RSBAC_RC_GENERAL_TYPE, \
+      .rc_force_role = RC_default_root_dir_force_role, \
+      .rc_initial_role = RC_default_root_dir_initial_role, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+#define RSBAC_AUTH_FD_ACI_VERSION 2
+#define RSBAC_AUTH_FD_OLD_ACI_VERSION 1
+#define RSBAC_AUTH_FD_ACI_KEY 1001
+struct rsbac_auth_fd_aci_t {
+	__u8 auth_may_setuid;	/* AUTH (enum) */
+	__u8 auth_may_set_cap;	/* AUTH (boolean) */
+	__u8 auth_learn;	/* AUTH (boolean) */
+};
+
+struct rsbac_auth_fd_old_aci_t {
+	__u8 auth_may_setuid;	/* AUTH (boolean) */
+	__u8 auth_may_set_cap;	/* AUTH (boolean) */
+};
+
+#define DEFAULT_AUTH_FD_ACI \
+    { \
+      .auth_may_setuid = FALSE, \
+      .auth_may_set_cap = FALSE, \
+      .auth_learn = FALSE, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+#define RSBAC_CAP_FD_ACI_VERSION 3
+#define RSBAC_CAP_FD_OLD_ACI_VERSION 2
+#define RSBAC_CAP_FD_OLD_OLD_ACI_VERSION 1
+#define RSBAC_CAP_FD_ACI_KEY 1001
+struct rsbac_cap_fd_aci_t {
+	rsbac_cap_vector_t min_caps;	/* Program forced minimum Linux capabilities */
+	rsbac_cap_vector_t max_caps;	/* Program max Linux capabilities */
+	rsbac_cap_ld_env_int_t cap_ld_env;
+};
+
+struct rsbac_cap_fd_old_aci_t {
+        rsbac_cap_old_vector_t min_caps;    /* Program forced minimum Linux capabilities */
+        rsbac_cap_old_vector_t max_caps;    /* Program max Linux capabilities */
+        rsbac_cap_ld_env_int_t cap_ld_env;
+};
+
+struct rsbac_cap_fd_old_old_aci_t {
+	rsbac_cap_old_vector_t min_caps;
+	rsbac_cap_old_vector_t max_caps;
+};
+
+#define DEFAULT_CAP_FD_ACI \
+    { \
+      .min_caps.cap[0] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .min_caps.cap[1] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .cap_ld_env = LD_keep, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+#define RSBAC_PAX_FD_ACI_VERSION 1
+#define RSBAC_PAX_FD_ACI_KEY 100112
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+#define RSBAC_RES_FD_ACI_VERSION 1
+#define RSBAC_RES_FD_ACI_KEY 1002
+struct rsbac_res_fd_aci_t {
+	rsbac_res_array_t res_min;
+	rsbac_res_array_t res_max;
+};
+#define DEFAULT_RES_FD_ACI \
+    { \
+      .res_min = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      }, \
+      .res_max = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      } \
+    }
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+#define RSBAC_UDF_FD_ACI_VERSION 1
+#define RSBAC_UDF_FD_ACI_KEY 764209
+#define RSBAC_UDF_CACHE_CLEANUP_INTERVAL 86400
+#define RSBAC_UDF_CHECKED_FD_ACI_VERSION 1
+struct rsbac_udf_fd_aci_t
+  {
+    rsbac_udf_checker_t  udf_checker;       /* UDF (for FILE only) */
+    rsbac_udf_do_check_t udf_do_check;
+  };
+
+#define DEFAULT_UDF_FD_ACI \
+    { \
+      .udf_checker = FALSE, \
+      .udf_do_check = DEFAULT_UDF_FD_DO_CHECK \
+    }
+
+#define DEFAULT_UDF_ROOT_DIR_ACI \
+    { \
+      .udf_checker = FALSE, \
+      .udf_do_check = DEFAULT_UDF_FD_ROOT_DO_CHECK \
+    }
+#endif
+
+
+#define RSBAC_FD_NR_ATTRIBUTES 33
+#define RSBAC_FD_ATTR_LIST { \
+      A_security_level, \
+      A_mac_categories, \
+      A_mac_auto, \
+      A_mac_prop_trusted, \
+      A_mac_file_flags, \
+      A_daz_scanner, \
+      A_ff_flags, \
+      A_rc_type_fd, \
+      A_rc_force_role, \
+      A_rc_initial_role, \
+      A_auth_may_setuid, \
+      A_auth_may_set_cap, \
+      A_auth_learn, \
+      A_log_array_low, \
+      A_log_array_high, \
+      A_log_program_based, \
+      A_symlink_add_remote_ip, \
+      A_symlink_add_uid, \
+      A_symlink_add_mac_level, \
+      A_symlink_add_rc_role, \
+      A_linux_dac_disable, \
+      A_min_caps, \
+      A_max_caps, \
+      A_cap_ld_env, \
+      A_res_min, \
+      A_res_max, \
+      A_pax_flags, \
+      A_fake_root_uid, \
+      A_auid_exempt, \
+      A_daz_do_scan, \
+      A_vset, \
+      A_udf_checker, \
+      A_udf_do_check \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_fd_list_handles_t {
+	rsbac_list_handle_t gen;
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	rsbac_list_handle_t daz;
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	rsbac_list_handle_t dazs;
+#endif
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	rsbac_list_handle_t ff;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_list_handle_t rc;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_list_handle_t auth;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	rsbac_list_handle_t cap;
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	rsbac_list_handle_t pax;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	rsbac_list_handle_t res;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	rsbac_list_handle_t udf;
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	rsbac_list_handle_t udfc;
+#endif
+#endif
+};
+
+/* The list of devices is also a double linked list, so we define list    */
+/* items and a list head.                                                 */
+
+/* Hash size. Must be power of 2. */
+
+#define RSBAC_NR_DEVICE_LISTS 8
+
+struct rsbac_device_list_item_t {
+	kdev_t id;
+	u_int mount_count;
+	struct rsbac_fd_list_handles_t handles;
+	struct dentry *rsbac_dir_dentry_p;
+	struct vfsmount *vfsmount_p;
+	rsbac_inode_nr_t rsbac_dir_inode;
+	struct rsbac_device_list_item_t *prev;
+	struct rsbac_device_list_item_t *next;
+#ifdef CONFIG_RSBAC_FD_CACHE
+	rsbac_list_handle_t fd_cache_handle[SW_NONE];
+#ifdef CONFIG_RSBAC_XSTATS
+	__u64 fd_cache_hits[SW_NONE];
+	__u64 fd_cache_misses[SW_NONE];
+	u_int fd_cache_invalidates;
+	u_int fd_cache_invalidate_alls;
+#endif
+#endif
+	rsbac_boolean_t persist;
+};
+
+/* To provide consistency we use spinlocks for all list accesses. The     */
+/* 'curr' entry is used to avoid repeated lookups for the same item.       */
+
+struct rsbac_device_list_head_t {
+	struct rsbac_device_list_item_t *head;
+	struct rsbac_device_list_item_t *tail;
+	struct rsbac_device_list_item_t *curr;
+	u_int count;
+};
+
+#endif				/* __KERNEL__ */
+
+/******************************/
+/* OK, now we define the block/char device ACI, holding all dev information */
+/* the ADF needs for decisions.                                           */
+
+#define RSBAC_GEN_ACI_DEV_NAME       "dev_gen"
+#define RSBAC_MAC_ACI_DEV_NAME       "dev_mac"
+#define RSBAC_RC_ACI_DEV_MAJOR_NAME  "devm_rc"
+#define RSBAC_RC_ACI_DEV_NAME        "dev_rc"
+
+/* Caution: whenever ACI changes, version should be increased!            */
+
+#define RSBAC_GEN_DEV_ACI_VERSION 2
+#define RSBAC_GEN_DEV_OLD_ACI_VERSION 1
+#define RSBAC_GEN_DEV_ACI_KEY 1001
+
+struct rsbac_gen_dev_aci_t {
+	rsbac_log_array_t log_array_low;	/* dev based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+};
+#define DEFAULT_GEN_DEV_ACI \
+    { \
+      .log_array_low = -1, \
+      .log_array_high = -1, \
+    }
+
+#if defined(CONFIG_RSBAC_MAC)
+#define RSBAC_MAC_DEV_ACI_VERSION 2
+#define RSBAC_MAC_DEV_OLD_ACI_VERSION 1
+#define RSBAC_MAC_DEV_ACI_KEY 1001
+struct rsbac_mac_dev_aci_t {
+	rsbac_security_level_t sec_level;	/* MAC */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+	__u8 mac_check;		/* MAC (boolean) */
+};
+#define DEFAULT_MAC_DEV_ACI \
+    { \
+      .sec_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_check = FALSE, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+#define RSBAC_RC_DEV_ACI_VERSION 2
+#define RSBAC_RC_DEV_OLD_ACI_VERSION 1
+#define RSBAC_RC_DEV_ACI_KEY 1001
+#endif
+
+#define RSBAC_DEV_NR_ATTRIBUTES 6
+#define RSBAC_DEV_ATTR_LIST { \
+      A_security_level, \
+      A_mac_categories, \
+      A_mac_check, \
+      A_rc_type, \
+      A_log_array_low, \
+      A_log_array_high \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_dev_handles_t {
+	rsbac_list_handle_t gen;
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_list_handle_t rc;
+#endif
+};
+#endif				/* __KERNEL__ */
+
+/**************************************************************************/
+/* Next we define the ipc ACI, holding all ipc information                */
+/* the ADF needs for decisions.                                           */
+
+#define RSBAC_MAC_ACI_IPC_NAME   "ipc_mac"
+#define RSBAC_RC_ACI_IPC_NAME    "ipc_rc"
+#define RSBAC_JAIL_ACI_IPC_NAME  "ipc_jai"
+
+#if defined(CONFIG_RSBAC_MAC)
+#define RSBAC_MAC_IPC_ACI_VERSION 1
+#define RSBAC_MAC_IPC_ACI_KEY 1001
+struct rsbac_mac_ipc_aci_t {
+	rsbac_security_level_t sec_level;	/* enum old_rsbac_security_level_t / __u8 */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+};
+#define DEFAULT_MAC_IPC_ACI \
+    { \
+      .sec_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+#define RSBAC_RC_IPC_ACI_VERSION 1
+#define RSBAC_RC_IPC_ACI_KEY 1001
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+#define RSBAC_JAIL_IPC_ACI_VERSION 1
+#define RSBAC_JAIL_IPC_ACI_KEY 1001
+#endif
+
+#define RSBAC_IPC_NR_ATTRIBUTES 4
+#define RSBAC_IPC_ATTR_LIST { \
+      A_security_level, \
+      A_mac_categories, \
+      A_rc_type, \
+      A_jail_id \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_ipc_handles_t {
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_list_handle_t rc;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	rsbac_list_handle_t jail;
+#endif
+};
+#endif				/* __KERNEL__ */
+
+/*************************************/
+/* The user ACI holds all user information the ADF needs. */
+
+#define RSBAC_GEN_ACI_USER_NAME   "u_gen"
+#define RSBAC_MAC_ACI_USER_NAME   "u_mac"
+#define RSBAC_DAZ_ACI_USER_NAME    "u_daz"
+#define RSBAC_FF_ACI_USER_NAME    "u_ff"
+#define RSBAC_RC_ACI_USER_NAME    "u_rc"
+#define RSBAC_AUTH_ACI_USER_NAME  "u_auth"
+#define RSBAC_CAP_ACI_USER_NAME   "u_cap"
+#define RSBAC_JAIL_ACI_USER_NAME  "u_jail"
+#define RSBAC_PAX_ACI_USER_NAME   "u_pax"
+#define RSBAC_RES_ACI_USER_NAME   "u_res"
+#define RSBAC_UDF_ACI_USER_NAME    "u_udf"
+
+#define RSBAC_GEN_USER_ACI_VERSION 2
+#define RSBAC_GEN_USER_OLD_ACI_VERSION 1
+#define RSBAC_GEN_USER_ACI_KEY 1001
+struct rsbac_gen_user_aci_t {
+	rsbac_pseudo_t pseudo;
+	rsbac_request_vector_t log_user_based;	/* User based logging */
+};
+#define DEFAULT_GEN_U_ACI \
+    { \
+      .pseudo = (rsbac_pseudo_t) 0, \
+      .log_user_based = 0, \
+    }
+
+#if defined(CONFIG_RSBAC_MAC)
+#define RSBAC_MAC_USER_ACI_VERSION 5
+#define RSBAC_MAC_USER_OLD_ACI_VERSION 4
+#define RSBAC_MAC_USER_OLD_OLD_ACI_VERSION 3
+#define RSBAC_MAC_USER_OLD_OLD_OLD_ACI_VERSION 2
+#define RSBAC_MAC_USER_OLD_OLD_OLD_OLD_ACI_VERSION 1
+#define RSBAC_MAC_USER_ACI_KEY 1001
+struct rsbac_mac_user_aci_t {
+	rsbac_security_level_t security_level;	/* maximum level */
+	rsbac_security_level_t initial_security_level;	/* maximum level */
+	rsbac_security_level_t min_security_level;	/* minimum level / __u8 */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC max category set */
+	rsbac_mac_category_vector_t mac_initial_categories;	/* MAC max category set */
+	rsbac_mac_category_vector_t mac_min_categories;	/* MAC min category set */
+	rsbac_system_role_int_t system_role;	/* enum rsbac_system_role_t */
+	rsbac_mac_user_flags_t mac_user_flags;	/* flags (override, trusted, allow_auto etc.) */
+};
+struct rsbac_mac_user_old_aci_t {
+	rsbac_security_level_t access_appr;	/* maximum level */
+	rsbac_security_level_t min_access_appr;	/* minimum level / __u8 */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC max category set */
+	rsbac_mac_category_vector_t mac_min_categories;	/* MAC min category set */
+	rsbac_system_role_int_t system_role;	/* enum rsbac_system_role_t */
+	rsbac_boolean_int_t mac_allow_auto;	/* allow to auto-adjust current level */
+};
+struct rsbac_mac_user_old_old_aci_t {
+	rsbac_security_level_t access_appr;	/* maximum level */
+	rsbac_security_level_t min_access_appr;	/* minimum level / __u8 */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC max category set */
+	rsbac_mac_category_vector_t mac_min_categories;	/* MAC min category set */
+	rsbac_system_role_int_t system_role;	/* enum rsbac_system_role_t */
+};
+struct rsbac_mac_user_old_old_old_aci_t {
+	rsbac_security_level_t access_appr;	/* enum old_rsbac_security_level_t / __u8 */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+	rsbac_system_role_int_t system_role;	/* enum rsbac_system_role_t */
+};
+#define DEFAULT_MAC_U_ACI \
+    { \
+      .security_level = SL_unclassified, \
+      .initial_security_level = SL_unclassified, \
+      .min_security_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_initial_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_min_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .system_role = SR_user, \
+      .mac_user_flags = RSBAC_MAC_DEF_U_FLAGS, \
+    }
+#define DEFAULT_MAC_U_SYSADM_ACI \
+    { \
+      .security_level = SL_unclassified, \
+      .initial_security_level = SL_unclassified, \
+      .min_security_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_initial_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_min_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .system_role = SR_administrator, \
+      .mac_user_flags = RSBAC_MAC_DEF_SYSADM_U_FLAGS, \
+    }
+#define DEFAULT_MAC_U_SECOFF_ACI \
+    { \
+      .security_level = SL_unclassified, \
+      .initial_security_level = SL_unclassified, \
+      .min_security_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_initial_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_min_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .system_role = SR_security_officer, \
+      .mac_user_flags = RSBAC_MAC_DEF_SECOFF_U_FLAGS, \
+    }
+#define DEFAULT_MAC_U_AUDITOR_ACI \
+    { \
+      .security_level = SL_unclassified, \
+      .initial_security_level = SL_unclassified, \
+      .min_security_level = SL_unclassified, \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_initial_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_min_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .system_role = SR_auditor, \
+      .mac_user_flags = RSBAC_MAC_DEF_U_FLAGS, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+#define RSBAC_DAZ_USER_ACI_VERSION 2
+#define RSBAC_DAZ_USER_OLD_ACI_VERSION 1
+#define RSBAC_DAZ_USER_ACI_KEY 1001
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+#define RSBAC_FF_USER_ACI_VERSION 2
+#define RSBAC_FF_USER_OLD_ACI_VERSION 1
+#define RSBAC_FF_USER_ACI_KEY 1001
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+#define RSBAC_RC_USER_ACI_VERSION 3
+#define RSBAC_RC_USER_OLD_ACI_VERSION 2
+#define RSBAC_RC_USER_OLD_OLD_ACI_VERSION 1
+#define RSBAC_RC_USER_ACI_KEY 1001
+struct rsbac_rc_user_aci_t {
+	rsbac_rc_role_id_t rc_role;
+	rsbac_rc_type_id_t rc_type;
+};
+#define DEFAULT_RC_U_ACI \
+    { \
+      .rc_role = RSBAC_RC_GENERAL_ROLE, \
+      .rc_type = RSBAC_RC_GENERAL_TYPE, \
+    }
+#define DEFAULT_RC_U_SYSADM_ACI \
+    { \
+      .rc_role = RSBAC_RC_SYSTEM_ADMIN_ROLE, /* rc_role (RC) */ \
+      .rc_type = RSBAC_RC_SYS_TYPE, \
+    }
+#define DEFAULT_RC_U_SECOFF_ACI \
+    { \
+      .rc_role = RSBAC_RC_ROLE_ADMIN_ROLE, /* rc_role (RC) */ \
+      .rc_type = RSBAC_RC_SEC_TYPE, \
+    }
+#define DEFAULT_RC_U_AUDITOR_ACI \
+    { \
+      .rc_role = RSBAC_RC_AUDITOR_ROLE, /* rc_role (RC) */ \
+      .rc_type = RSBAC_RC_SEC_TYPE, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+#define RSBAC_AUTH_USER_ACI_VERSION 2
+#define RSBAC_AUTH_USER_OLD_ACI_VERSION 1
+#define RSBAC_AUTH_USER_ACI_KEY 1001
+
+#endif				/* AUTH */
+
+#if defined(CONFIG_RSBAC_CAP)
+#define RSBAC_CAP_USER_ACI_VERSION 4
+#define RSBAC_CAP_USER_OLD_ACI_VERSION 3
+#define RSBAC_CAP_USER_OLD_OLD_ACI_VERSION 2
+#define RSBAC_CAP_USER_OLD_OLD_OLD_ACI_VERSION 1
+#define RSBAC_CAP_USER_ACI_KEY 1001
+struct rsbac_cap_user_aci_t {
+	rsbac_system_role_int_t cap_role;	/* System role for CAP administration */
+	rsbac_cap_vector_t min_caps;	        /* User forced minimum Linux capabilities */
+	rsbac_cap_vector_t max_caps;	        /* User max Linux capabilities */
+        rsbac_cap_ld_env_int_t cap_ld_env;
+};
+
+struct rsbac_cap_user_old_aci_t {
+	rsbac_system_role_int_t cap_role;       /* System role for CAP administration */
+	rsbac_cap_old_vector_t min_caps;            /* User forced minimum Linux capabilities */
+	rsbac_cap_old_vector_t max_caps;            /* User max Linux capabilities */
+	rsbac_cap_ld_env_int_t cap_ld_env;
+};
+
+struct rsbac_cap_user_old_old_aci_t {
+	rsbac_system_role_int_t cap_role;	/* System role for CAP administration */
+	rsbac_cap_old_vector_t min_caps;	        /* User forced minimum Linux capabilities */
+	rsbac_cap_old_vector_t max_caps;	        /* User max Linux capabilities */
+        rsbac_cap_ld_env_int_t cap_ld_env;
+};
+
+struct rsbac_cap_user_old_old_old_aci_t {
+	rsbac_system_role_int_t cap_role;       /* System role for CAP administration */
+	rsbac_cap_old_vector_t min_caps;        /* User forced minimum Linux capabilities */
+	rsbac_cap_old_vector_t max_caps;        /* User max Linux capabilities */
+};
+
+#define DEFAULT_CAP_U_ACI \
+    { \
+      .cap_role = SR_user, \
+      .min_caps.cap[0] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .min_caps.cap[1] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .cap_ld_env = LD_keep, \
+    }
+#define DEFAULT_CAP_U_SYSADM_ACI \
+    { \
+      .cap_role = SR_administrator, \
+      .min_caps.cap[0] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .min_caps.cap[1] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .cap_ld_env = LD_keep, \
+    }
+#define DEFAULT_CAP_U_SECOFF_ACI \
+    { \
+      .cap_role = SR_security_officer, \
+      .min_caps.cap[0] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .min_caps.cap[1] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .cap_ld_env = LD_keep, \
+    }
+#define DEFAULT_CAP_U_AUDITOR_ACI \
+    { \
+      .cap_role = SR_auditor, \
+      .min_caps.cap[0] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .min_caps.cap[1] = RSBAC_CAP_DEFAULT_MIN, \
+      .max_caps.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .cap_ld_env = LD_keep, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+#define RSBAC_JAIL_USER_ACI_VERSION 2
+#define RSBAC_JAIL_USER_OLD_ACI_VERSION 1
+#define RSBAC_JAIL_USER_ACI_KEY 1001
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+#define RSBAC_PAX_USER_ACI_VERSION 2
+#define RSBAC_PAX_USER_OLD_ACI_VERSION 1
+#define RSBAC_PAX_USER_ACI_KEY 1001221
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+#define RSBAC_RES_USER_ACI_VERSION 2
+#define RSBAC_RES_USER_OLD_ACI_VERSION 1
+#define RSBAC_RES_USER_ACI_KEY 1002
+struct rsbac_res_user_aci_t {
+	rsbac_system_role_int_t res_role;	/* System role for RES administration */
+	rsbac_res_array_t res_min;
+	rsbac_res_array_t res_max;
+};
+#define DEFAULT_RES_U_ACI \
+    { \
+      .res_role = SR_user, \
+      .res_min = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      }, \
+      .res_max = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      }, \
+    }
+#define DEFAULT_RES_U_SYSADM_ACI \
+    { \
+      .res_role = SR_administrator, \
+      .res_min = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      }, \
+      .res_max = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      } \
+    }
+#define DEFAULT_RES_U_SECOFF_ACI \
+    { \
+      .res_role = SR_security_officer, \
+      .res_min = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      }, \
+      .res_max = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      } \
+    }
+#define DEFAULT_RES_U_AUDITOR_ACI \
+    { \
+      .res_role = SR_auditor, \
+      .res_min = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      }, \
+      .res_max = { \
+        RSBAC_RES_UNSET,           /* cpu time */ \
+        RSBAC_RES_UNSET,           /* file size */ \
+        RSBAC_RES_UNSET,           /* process data segment size */ \
+        RSBAC_RES_UNSET,           /* stack size */ \
+        RSBAC_RES_UNSET,           /* core dump size */ \
+        RSBAC_RES_UNSET,           /* resident memory set size */ \
+        RSBAC_RES_UNSET,           /* number of processes for this user */ \
+        RSBAC_RES_UNSET,           /* number of files */ \
+        RSBAC_RES_UNSET,           /* locked-in-memory address space */ \
+        RSBAC_RES_UNSET,           /* address space (virtual memory) limit */ \
+        RSBAC_RES_UNSET            /* maximum file locks */ \
+      } \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+#define RSBAC_UDF_USER_ACI_VERSION 1
+#define RSBAC_UDF_USER_ACI_KEY 429822
+#endif
+
+#define RSBAC_USER_NR_ATTRIBUTES 23
+#define RSBAC_USER_ATTR_LIST { \
+      A_pseudo, \
+      A_log_user_based, \
+      A_security_level, \
+      A_initial_security_level, \
+      A_min_security_level, \
+      A_mac_categories, \
+      A_mac_initial_categories, \
+      A_mac_min_categories, \
+      A_mac_role, \
+      A_mac_user_flags, \
+      A_daz_role, \
+      A_ff_role, \
+      A_auth_role, \
+      A_rc_def_role, \
+      A_rc_type, \
+      A_min_caps, \
+      A_max_caps, \
+      A_cap_role, \
+      A_cap_ld_env, \
+      A_jail_role, \
+      A_res_role, \
+      A_pax_role, \
+      A_udf_role \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_user_handles_t {
+	rsbac_list_handle_t gen;
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	rsbac_list_handle_t daz;
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	rsbac_list_handle_t ff;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_list_handle_t rc;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_list_handle_t auth;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	rsbac_list_handle_t cap;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	rsbac_list_handle_t jail;
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	rsbac_list_handle_t pax;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	rsbac_list_handle_t res;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	rsbac_list_handle_t udf;
+#endif
+};
+#endif
+
+/********************************/
+/* Process ACI. */
+
+#define RSBAC_GEN_ACI_PROCESS_NAME   "process_gen"
+#define RSBAC_MAC_ACI_PROCESS_NAME   "process_mac"
+#define RSBAC_DAZ_ACI_PROCESS_NAME    "process_daz"
+#define RSBAC_RC_ACI_PROCESS_NAME    "process_rc"
+#define RSBAC_AUTH_ACI_PROCESS_NAME    "process_auth"
+#define RSBAC_CAP_ACI_PROCESS_NAME    "process_cap"
+#define RSBAC_JAIL_ACI_PROCESS_NAME    "process_jail"
+#define RSBAC_UDF_ACI_PROCESS_NAME    "process_udf"
+
+#define RSBAC_GEN_PROCESS_ACI_VERSION 3
+#define RSBAC_GEN_PROCESS_ACI_KEY 1001
+struct rsbac_gen_process_aci_t {
+	rsbac_request_vector_t log_program_based;
+	rsbac_fake_root_uid_int_t fake_root_uid;
+	rsbac_uid_t audit_uid;
+	rsbac_uid_t auid_exempt;
+	__u32 remote_ip;
+	rsbac_boolean_t kernel_thread;
+	rsbac_um_set_t vset;
+#if defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+	struct rsbac_fs_file_t program_file;
+#endif
+};
+#if defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+#define DEFAULT_GEN_P_ACI \
+    { \
+      .log_program_based = 0, \
+      .fake_root_uid = FR_off, \
+      .audit_uid = RSBAC_NO_USER, \
+      .auid_exempt = RSBAC_NO_USER, \
+      .remote_ip = 0, \
+      .kernel_thread = 0, \
+      .vset = 0, \
+      .program_file = { RSBAC_ZERO_DEV, 0, NULL }, \
+    }
+#else
+#define DEFAULT_GEN_P_ACI \
+    { \
+      .log_program_based = 0, \
+      .fake_root_uid = FR_off, \
+      .audit_uid = RSBAC_NO_USER, \
+      .auid_exempt = RSBAC_NO_USER, \
+      .remote_ip = 0, \
+      .kernel_thread = 0, \
+      .vset = 0, \
+    }
+#endif
+
+
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_MAC_MAINT)
+#define RSBAC_MAC_PROCESS_ACI_VERSION 1
+#define RSBAC_MAC_PROCESS_ACI_KEY 1001
+struct rsbac_mac_process_aci_t {
+	rsbac_security_level_t owner_sec_level;	/* enum old_rsbac_security_level_t */
+	rsbac_security_level_t owner_initial_sec_level;	/* enum old_rsbac_security_level_t */
+	rsbac_security_level_t owner_min_sec_level;	/* enum old_rsbac_security_level_t */
+	rsbac_mac_category_vector_t mac_owner_categories;	/* MAC category set */
+	rsbac_mac_category_vector_t mac_owner_initial_categories;	/* MAC category set */
+	rsbac_mac_category_vector_t mac_owner_min_categories;	/* MAC category set */
+	rsbac_security_level_t current_sec_level;	/* enum rsbac_security_level_t */
+	rsbac_mac_category_vector_t mac_curr_categories;	/* MAC current category set */
+	rsbac_security_level_t min_write_open;	/* for *-property, enum rsbac_security_level_t */
+	rsbac_mac_category_vector_t min_write_categories;	/* MAC, for *-property */
+	rsbac_security_level_t max_read_open;	/* for *-property, enum rsbac_security_level_t */
+	rsbac_mac_category_vector_t max_read_categories;	/* MAC, for *-property */
+	rsbac_mac_process_flags_t mac_process_flags;	/* flags (override, trusted, auto etc.) */
+};
+#define DEFAULT_MAC_P_ACI \
+    { \
+      .owner_sec_level = SL_unclassified, \
+      .owner_initial_sec_level = SL_unclassified, \
+      .owner_min_sec_level = SL_unclassified, \
+      .mac_owner_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_owner_initial_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_owner_min_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .current_sec_level = SL_unclassified, \
+      .mac_curr_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .min_write_open = SL_max, \
+      .min_write_categories = RSBAC_MAC_MAX_CAT_VECTOR, \
+      .max_read_open = SL_unclassified, \
+      .max_read_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .mac_process_flags = RSBAC_MAC_DEF_P_FLAGS, \
+    }
+#define DEFAULT_MAC_P_INIT_ACI \
+    { \
+      .owner_sec_level = SL_unclassified, \
+      .owner_initial_sec_level = SL_unclassified, \
+      .owner_min_sec_level = SL_unclassified, \
+      .mac_owner_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_owner_initial_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .mac_owner_min_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .current_sec_level = SL_unclassified, \
+      .mac_curr_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+      .min_write_open = SL_max, \
+      .min_write_categories = RSBAC_MAC_MAX_CAT_VECTOR, \
+      .max_read_open = SL_unclassified, \
+      .max_read_categories = RSBAC_MAC_MIN_CAT_VECTOR, \
+      .mac_process_flags = RSBAC_MAC_DEF_INIT_P_FLAGS, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+#define RSBAC_DAZ_PROCESS_ACI_VERSION 1
+#define RSBAC_DAZ_PROCESS_ACI_KEY 1001
+struct rsbac_daz_process_aci_t {
+	rsbac_boolean_int_t daz_scanner;	/* DAZ, boolean */
+};
+#define DEFAULT_DAZ_P_ACI \
+    { \
+      .daz_scanner = FALSE, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+#define RSBAC_RC_PROCESS_ACI_VERSION 1
+#define RSBAC_RC_PROCESS_ACI_KEY 1001
+struct rsbac_rc_process_aci_t {
+	rsbac_rc_role_id_t rc_role;	/* RC */
+	rsbac_rc_type_id_t rc_type;	/* RC */
+	rsbac_rc_role_id_t rc_force_role;	/* RC */
+	rsbac_rc_type_id_t rc_select_type; /* RC */
+};
+#define DEFAULT_RC_P_ACI \
+    { \
+      .rc_role = RSBAC_RC_GENERAL_ROLE, \
+      .rc_type = RSBAC_RC_GENERAL_TYPE, \
+      .rc_force_role = RC_default_force_role, \
+      .rc_select_type = RC_type_use_fd, \
+    }
+#define DEFAULT_RC_P_INIT_ACI \
+    { \
+      .rc_role = RSBAC_RC_SYSTEM_ADMIN_ROLE, \
+      .rc_type = RSBAC_RC_GENERAL_TYPE, \
+      .rc_force_role = RC_default_force_role, \
+      .rc_select_type = RC_type_use_fd, \
+    }
+#define DEFAULT_RC_P_KERNEL_ACI \
+    { \
+      .rc_role = RSBAC_RC_SYSTEM_ADMIN_ROLE, \
+      .rc_type = CONFIG_RSBAC_RC_KERNEL_PROCESS_TYPE, \
+      .rc_force_role = RC_default_force_role, \
+      .rc_select_type = RC_type_use_fd, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+#define RSBAC_AUTH_PROCESS_ACI_VERSION 1
+#define RSBAC_AUTH_PROCESS_ACI_KEY 1001
+struct rsbac_auth_process_aci_t {
+	__u8 auth_may_setuid;	/* AUTH (boolean) */
+	__u8 auth_may_set_cap;	/* AUTH (boolean) */
+	rsbac_uid_t auth_last_auth;
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+	rsbac_uid_t auth_start_uid;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	rsbac_uid_t auth_start_euid;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	rsbac_gid_t auth_start_gid;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	rsbac_gid_t auth_start_egid;
+#endif
+#endif
+	__u8 auth_learn;	/* AUTH (boolean) */
+#endif
+};
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+#define DEFAULT_AUTH_P_ACI \
+    { \
+      .auth_may_setuid = FALSE, \
+      .auth_may_set_cap = FALSE, \
+      .auth_last_auth = RSBAC_NO_USER, \
+      .auth_start_uid = 0, \
+      .auth_learn = 0, \
+    }
+#else
+#define DEFAULT_AUTH_P_ACI \
+    { \
+      .auth_may_setuid = FALSE, \
+      .auth_may_set_cap = FALSE, \
+      .auth_last_auth = RSBAC_NO_USER, \
+    }
+#endif
+#endif
+
+
+#if defined(CONFIG_RSBAC_CAP)
+#define RSBAC_CAP_PROCESS_ACI_VERSION 2
+#define RSBAC_CAP_PROCESS_ACI_KEY 10013283
+struct rsbac_cap_process_aci_t {
+	rsbac_cap_process_hiding_int_t cap_process_hiding;
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_CAP_LEARN)
+	rsbac_cap_vector_t max_caps_user;
+	rsbac_cap_vector_t max_caps_program;
+#endif
+	rsbac_cap_ld_env_int_t cap_ld_env;
+};
+
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+#define DEFAULT_CAP_P_ACI \
+    { \
+      .cap_process_hiding = PH_off, \
+      .max_caps_user.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .max_caps_user.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .max_caps_program.cap[0] = RSBAC_CAP_DEFAULT_MAX, \
+      .max_caps_program.cap[1] = RSBAC_CAP_DEFAULT_MAX, \
+      .cap_ld_env = LD_allow, \
+    }
+#else
+#define DEFAULT_CAP_P_ACI \
+    { \
+      .cap_process_hiding = PH_off, \
+      .cap_ld_env = LD_allow, \
+    }
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+#define RSBAC_JAIL_PROCESS_ACI_VERSION 1
+#define RSBAC_JAIL_PROCESS_ACI_KEY 1001
+struct rsbac_jail_process_aci_t {
+	rsbac_jail_id_t id;
+	rsbac_jail_id_t parent;
+	rsbac_jail_ip_t ip;
+	rsbac_jail_flags_t flags;
+	rsbac_cap_vector_t max_caps;	/* Program max Linux capabilities */
+	rsbac_jail_scd_vector_t scd_get;	/* SCD targets GET_STATUS_DATA */
+	rsbac_jail_scd_vector_t scd_modify;	/* SCD targets MODIFY_SYSTEM_DATA */
+};
+#define DEFAULT_JAIL_P_ACI \
+    { \
+      .id = 0, \
+      .parent = 0, \
+      .ip = 0, \
+      .flags = 0, \
+      .max_caps.cap[0] = -1, \
+      .max_caps.cap[1] = -1, \
+      .scd_get = 0, \
+      .scd_modify = 0, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+#define RSBAC_UDF_PROCESS_ACI_VERSION 1
+#define RSBAC_UDF_PROCESS_ACI_KEY 98428
+struct rsbac_udf_process_aci_t {
+	rsbac_boolean_int_t udf_checker;	/* UDF, boolean */
+};
+#define DEFAULT_UDF_P_ACI \
+    { \
+      .udf_checker = FALSE, \
+    }
+#endif
+
+#define RSBAC_PROCESS_NR_ATTRIBUTES 37
+#define RSBAC_PROCESS_ATTR_LIST { \
+      A_security_level, \
+      A_min_security_level, \
+      A_mac_categories, \
+      A_mac_min_categories, \
+      A_current_sec_level, \
+      A_mac_curr_categories, \
+      A_min_write_open, \
+      A_min_write_categories, \
+      A_max_read_open, \
+      A_max_read_categories, \
+      A_mac_process_flags, \
+      A_daz_scanner, \
+      A_rc_role, \
+      A_rc_type, \
+      A_rc_force_role, \
+      A_rc_select_type, \
+      A_auth_may_setuid, \
+      A_auth_may_set_cap, \
+      A_auth_learn, \
+      A_cap_process_hiding, \
+      A_max_caps_user, \
+      A_max_caps_program, \
+      A_cap_ld_env, \
+      A_jail_id, \
+      A_jail_ip, \
+      A_jail_flags, \
+      A_jail_max_caps, \
+      A_jail_scd_get, \
+      A_jail_scd_modify, \
+      A_log_program_based, \
+      A_fake_root_uid, \
+      A_audit_uid, \
+      A_auid_exempt, \
+      A_auth_last_auth, \
+      A_remote_ip, \
+      A_vset, \
+      A_udf_scanner \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_process_handles_t {
+	rsbac_list_handle_t gen;
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	rsbac_list_handle_t daz;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_list_handle_t rc;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_list_handle_t auth;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	rsbac_list_handle_t cap;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	rsbac_list_handle_t jail;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	rsbac_list_handle_t udf;
+#endif
+};
+#endif				/* __KERNEL__ */
+
+
+/******************************/
+/* OK, now we define the UM group ACI, holding all information */
+/* the ADF needs for decisions.                                */
+
+#define RSBAC_RC_ACI_GROUP_NAME    "grouprc"
+
+/* Caution: whenever ACI changes, version should be increased!            */
+
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+#define RSBAC_RC_GROUP_ACI_VERSION 1
+#define RSBAC_RC_GROUP_ACI_KEY 13276142
+#endif
+
+#define RSBAC_GROUP_NR_ATTRIBUTES 1
+#define RSBAC_GROUP_ATTR_LIST { \
+      A_rc_type \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_group_handles_t {
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	rsbac_list_handle_t rc;
+#endif
+};
+#endif				/* __KERNEL__ */
+
+/********************************/
+/* NETDEV ACI */
+
+#define RSBAC_GEN_ACI_NETDEV_NAME   "nd_gen"
+#define RSBAC_RC_ACI_NETDEV_NAME    "nd_rc"
+
+#define RSBAC_GEN_NETDEV_ACI_VERSION 1
+#define RSBAC_GEN_NETDEV_ACI_KEY 1001
+struct rsbac_gen_netdev_aci_t {
+	rsbac_log_array_t log_array_low;	/* netdev based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+};
+#define DEFAULT_GEN_NETDEV_ACI \
+    { \
+      .log_array_low = -1, \
+      .log_array_high = -1, \
+    }
+
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+#define RSBAC_RC_NETDEV_ACI_VERSION 1
+#define RSBAC_RC_NETDEV_ACI_KEY 1001
+#endif
+
+#define RSBAC_NETDEV_NR_ATTRIBUTES 3
+#define RSBAC_NETDEV_ATTR_LIST { \
+      A_rc_type, \
+      A_log_array_low, \
+      A_log_array_high \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_netdev_handles_t {
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	rsbac_list_handle_t gen;
+#endif
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+	rsbac_list_handle_t rc;
+#endif
+};
+#endif				/* __KERNEL__ */
+
+/********************************/
+/* NETTEMP ACI */
+
+#define RSBAC_GEN_ACI_NETTEMP_NAME   "nt_gen"
+#define RSBAC_MAC_ACI_NETTEMP_NAME   "nt_mac"
+#define RSBAC_RC_ACI_NETTEMP_NAME    "nt_rc"
+
+#define RSBAC_MAC_ACI_LNETOBJ_NAME   "lnetobj_mac"
+#define RSBAC_RC_ACI_LNETOBJ_NAME    "lnetobj_rc"
+#define RSBAC_MAC_ACI_RNETOBJ_NAME   "rnetobj_mac"
+#define RSBAC_RC_ACI_RNETOBJ_NAME    "rnetobj_rc"
+
+#define RSBAC_GEN_NETOBJ_ACI_VERSION 1
+#define RSBAC_GEN_NETOBJ_ACI_KEY 1001
+struct rsbac_gen_netobj_aci_t {
+	rsbac_log_array_t log_array_low;	/* nettemp/netobj based logging, */
+	rsbac_log_array_t log_array_high;	/* high and low bits */
+};
+#define DEFAULT_GEN_NETOBJ_ACI \
+    { \
+      .log_array_low = -1, \
+      .log_array_high = -1, \
+    }
+
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_MAC_MAINT)
+#define RSBAC_MAC_NETOBJ_ACI_VERSION 1
+#define RSBAC_MAC_NETOBJ_ACI_KEY 1001
+struct rsbac_mac_netobj_aci_t {
+	rsbac_security_level_t sec_level;	/* enum old_rsbac_security_level_t / __u8 */
+	rsbac_mac_category_vector_t mac_categories;	/* MAC category set */
+};
+#define DEFAULT_MAC_NETOBJ_ACI \
+    { \
+      .sec_level = SL_unclassified,  /* security_level (MAC) */ \
+      .mac_categories = RSBAC_MAC_DEF_CAT_VECTOR, \
+    }
+#endif
+
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+#define RSBAC_RC_NETOBJ_ACI_VERSION 1
+#define RSBAC_RC_NETOBJ_ACI_KEY 1001
+#define RSBAC_RC_NETTEMP_ACI_VERSION 1
+#define RSBAC_RC_NETTEMP_ACI_KEY 1002
+
+struct rsbac_rc_nettemp_aci_t {
+	rsbac_rc_type_id_t netobj_type;	/* type inherited to netobj */
+	rsbac_rc_type_id_t nettemp_type;	/* type of this tenplate */
+};
+#define DEFAULT_RC_NETTEMP_ACI \
+    { \
+      .netobj_type = RSBAC_RC_GENERAL_TYPE, \
+      .nettemp_type = RSBAC_RC_GENERAL_TYPE, \
+    }
+#endif
+
+#define RSBAC_NETTEMP_NR_ATTRIBUTES 6
+#define RSBAC_NETTEMP_ATTR_LIST { \
+      A_security_level, \
+      A_mac_categories, \
+      A_rc_type, \
+      A_rc_type_nt, \
+      A_log_array_low, \
+      A_log_array_high \
+      }
+
+#define RSBAC_NETOBJ_NR_ATTRIBUTES 10
+#define RSBAC_NETOBJ_ATTR_LIST { \
+      A_local_sec_level, \
+      A_remote_sec_level, \
+      A_local_mac_categories, \
+      A_remote_mac_categories, \
+      A_local_rc_type, \
+      A_remote_rc_type, \
+      A_local_log_array_low, \
+      A_remote_log_array_low, \
+      A_local_log_array_high, \
+      A_remote_log_array_high \
+      }
+
+#ifdef __KERNEL__
+struct rsbac_nettemp_handles_t {
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+	rsbac_list_handle_t gen;
+#endif
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_MAC_MAINT)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+	rsbac_list_handle_t rc;
+#endif
+};
+
+struct rsbac_lnetobj_handles_t {
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_MAC_MAINT)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+	rsbac_list_handle_t rc;
+#endif
+};
+struct rsbac_rnetobj_handles_t {
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_MAC_MAINT)
+	rsbac_list_handle_t mac;
+#endif
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+	rsbac_list_handle_t rc;
+#endif
+};
+#endif				/* __KERNEL__ */
+
+
+/**********************************************/
+/*              Declarations                  */
+/**********************************************/
+
+#ifdef __KERNEL__
+extern kdev_t rsbac_root_dev;
+
+int rsbac_read_open(char *, struct file **,	/* file */
+		    kdev_t);
+
+int rsbac_write_open(char *, struct file **,	/* file */
+		     kdev_t);
+
+void rsbac_read_close(struct file *);
+
+void rsbac_write_close(struct file *);
+
+extern struct semaphore rsbac_write_sem;
+
+#endif				/* __KERNEL__ */
+
+/**********************************************/
+/*          External Declarations             */
+/**********************************************/
+
+#ifdef __KERNEL__
+
+static inline struct dentry *lock_parent(struct dentry *dentry)
+{
+	struct dentry *dir = dget(dentry->d_parent);
+
+	mutex_lock(&dir->d_inode->i_mutex);
+	return dir;
+}
+
+static inline void unlock_dir(struct dentry *dir)
+{
+	mutex_unlock(&dir->d_inode->i_mutex);
+	dput(dir);
+}
+
+static inline void double_mutex_lock(struct mutex *m1, struct mutex *m2)
+{
+	if (m1 != m2) {
+		if ((unsigned long) m1 < (unsigned long) m2) {
+			struct mutex *tmp = m2;
+			m2 = m1;
+			m1 = tmp;
+		}
+		mutex_lock(m1);
+	}
+	mutex_lock(m2);
+}
+
+static inline void double_mutex_unlock(struct mutex *m1, struct mutex *m2)
+{
+	mutex_unlock(m1);
+	if (m1 != m2)
+		mutex_unlock(m2);
+}
+
+static inline void double_lock(struct dentry *d1, struct dentry *d2)
+{
+	double_mutex_lock(&d1->d_inode->i_mutex, &d2->d_inode->i_mutex);
+}
+
+static inline void double_unlock(struct dentry *d1, struct dentry *d2)
+{
+	double_mutex_unlock(&d1->d_inode->i_mutex, &d2->d_inode->i_mutex);
+	dput(d1);
+	dput(d2);
+}
+
+#ifdef CONFIG_RSBAC_DEBUG
+static inline unsigned long rsbac_stack_free_space(void)
+{
+	unsigned long *n = (unsigned long *)(current + 1);
+	while (!*n)
+		n++;
+	return (unsigned long)n - (unsigned long)(current + 1);
+}
+#else
+#define rsbac_stack_free_space() 0
+#endif
+
+#endif				/* __KERNEL__ */
+
+#endif
diff --git a/include/rsbac/acl.h b/include/rsbac/acl.h
new file mode 100644
index 0000000..3163990
--- /dev/null
+++ b/include/rsbac/acl.h
@@ -0,0 +1,266 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2013: Amon Ott */
+/* API: Data structures               */
+/* and functions for Access           */
+/* Control Information / ACL          */
+/* Last modified: 14/Jan/2013         */
+/************************************ */
+
+#ifndef __RSBAC_ACL_H
+#define __RSBAC_ACL_H
+
+#include <linux/init.h>
+#include <rsbac/types.h>
+
+/***************************************************/
+/*               General Prototypes                */
+/***************************************************/
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+/****************************************************************************/
+/* Initialization, including ACI restoration for all mounted devices from   */
+/* disk. After this call, all ACI is kept in memory for performance reasons,*/
+/* but user and file/dir object ACI are written to disk on every change.    */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern int rsbac_init_acl(void);
+#else
+extern int rsbac_init_acl(void) __init;
+#endif
+
+/* mounting and umounting */
+int rsbac_mount_acl(kdev_t kdev);
+int rsbac_umount_acl(kdev_t kdev);
+
+/* Some information about the current status is also available */
+extern int rsbac_stats_acl(void);
+
+/* Status checking */
+extern int rsbac_check_acl(int correct);
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the spinlocks to protect the targets during */
+/* access.                                                                 */
+
+/* rsbac_acl_set_acl_entry
+ * Set ACL entry for given target and subject to given rights. If entry does
+ * not exist, it is created, thus cutting the inheritance from default/parent.
+ */
+
+int rsbac_acl_set_acl_entry(rsbac_list_ta_number_t ta_number,
+			    enum rsbac_target_t target,
+			    union rsbac_target_id_t tid,
+			    enum rsbac_acl_subject_type_t subj_type,
+			    rsbac_acl_subject_id_t subj_id,
+			    rsbac_acl_rights_vector_t rights,
+			    rsbac_time_t ttl);
+
+/* rsbac_acl_remove_acl_entry
+ * Remove ACL entry for given target and subject. This reactivates the
+ * inheritance from default/parent.
+ */
+
+int rsbac_acl_remove_acl_entry(rsbac_list_ta_number_t ta_number,
+			       enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_acl_subject_type_t subj_type,
+			       rsbac_acl_subject_id_t subj_id);
+
+/* rsbac_acl_remove_acl
+ * Remove ACL for given target. For cleanup on delete.
+ */
+
+int rsbac_acl_remove_acl(rsbac_list_ta_number_t ta_number,
+			 enum rsbac_target_t target,
+			 union rsbac_target_id_t tid);
+
+/* rsbac_acl_add_to_acl_entry
+ * Add given rights to ACL entry for given target and subject. If entry does
+ * not exist, behaviour is exactly like rsbac_acl_set_acl_entry.
+ */
+
+int rsbac_acl_add_to_acl_entry(rsbac_list_ta_number_t ta_number,
+			       enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_acl_subject_type_t subj_type,
+			       rsbac_acl_subject_id_t subj_id,
+			       rsbac_acl_rights_vector_t rights,
+			       rsbac_time_t ttl);
+
+/* rsbac_acl_remove_from_acl_entry
+ * Remove given rights from ACL entry for given target and subject. If entry does
+ * not exist, nothing happens.
+ * This function does NOT remove the ACL entry, so removing all rights results in
+ * NO rights for this subject/target combination!
+ */
+
+int rsbac_acl_remove_from_acl_entry(rsbac_list_ta_number_t ta_number,
+				    enum rsbac_target_t target,
+				    union rsbac_target_id_t tid,
+				    enum rsbac_acl_subject_type_t
+				    subj_type,
+				    rsbac_acl_subject_id_t subj_id,
+				    rsbac_acl_rights_vector_t rights);
+
+/* rsbac_acl_set_mask
+ * Set inheritance mask for given target to given rights. If item does
+ * not exist, it is created.
+ */
+
+int rsbac_acl_set_mask(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_target_t target,
+		       union rsbac_target_id_t tid,
+		       rsbac_acl_rights_vector_t mask);
+
+/* rsbac_acl_get_mask
+ * Get inheritance mask for given target to given rights. If item does
+ * not exist, default mask is returned.
+ */
+
+int rsbac_acl_get_mask(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_target_t target,
+		       union rsbac_target_id_t tid,
+		       rsbac_acl_rights_vector_t * mask_p);
+
+/* rsbac_acl_get_rights
+ * Get effective rights from ACL entry for given target and subject.
+ * If entry does not exist, inherited rights are used. If there is no parent,
+ * the default rights vector for this target type is returned.
+ * This function does NOT add role or group rights to user rights!
+ */
+
+int rsbac_acl_get_rights(rsbac_list_ta_number_t ta_number,
+			 enum rsbac_target_t target,
+			 union rsbac_target_id_t tid,
+			 enum rsbac_acl_subject_type_t subj_type,
+			 rsbac_acl_subject_id_t subj_id,
+			 rsbac_acl_rights_vector_t * rights_p,
+			 rsbac_boolean_t inherit);
+
+/* rsbac_acl_get_single_right
+ * Show, whether a right is set for given target and subject.
+ * If right is not set, it is checked at all parents, unless it has been
+ * masked out *or* it is SUPERVISOR, CONFIG_RSBAC_ACL_SUPER_FILTER is set
+ * and supervisor is masked out.
+ */
+
+int rsbac_acl_get_single_right(enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_acl_subject_type_t subj_type,
+			       rsbac_acl_subject_id_t subj_id,
+			       enum rsbac_adf_request_t right,
+			       rsbac_boolean_t * result);
+
+
+/************************************************************************** */
+/* The rsbac_acl_copy_fd_acl() function copies a file/dir ACL to another    */
+/* file/dir ACL. The old ACL of fd2 is erased before copying.               */
+
+int rsbac_acl_copy_fd_acl(struct rsbac_fs_file_t file1,
+			  struct rsbac_fs_file_t file2);
+
+/************************************************************************** */
+/* The rsbac_acl_copy_pp_acl() function copies a process acl to another     */
+
+int rsbac_acl_copy_pp_acl(rsbac_pid_t old_pid, rsbac_pid_t new_pid);
+
+/*************************************************
+ * rsbac_acl_get_tlist
+ * Get subjects from ACL entries for given target.
+ */
+
+int rsbac_acl_get_tlist(rsbac_list_ta_number_t ta_number,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t tid,
+			struct rsbac_acl_entry_t **entry_pp,
+			rsbac_time_t ** ttl_pp);
+
+/*************************************************
+ * Group management
+ */
+
+/* add a group with new id and fill this id into *group_id_p */
+int rsbac_acl_add_group(rsbac_list_ta_number_t ta_number,
+			rsbac_uid_t owner,
+			enum rsbac_acl_group_type_t type,
+			const char *name, rsbac_acl_group_id_t * group_id_p);
+
+int rsbac_acl_change_group(rsbac_list_ta_number_t ta_number,
+			   rsbac_acl_group_id_t id,
+			   rsbac_uid_t owner,
+			   enum rsbac_acl_group_type_t type, const char *name);
+
+int rsbac_acl_remove_group(rsbac_list_ta_number_t ta_number,
+			   rsbac_acl_group_id_t id);
+
+int rsbac_acl_get_group_entry(rsbac_list_ta_number_t ta_number,
+			      rsbac_acl_group_id_t group,
+			      struct rsbac_acl_group_entry_t *entry_p);
+
+int rsbac_acl_list_groups(rsbac_list_ta_number_t ta_number,
+			  rsbac_uid_t owner,
+			  rsbac_boolean_t include_global,
+			  struct rsbac_acl_group_entry_t **entry_pp);
+
+/* check group existence */
+rsbac_boolean_t rsbac_acl_group_exist(rsbac_acl_group_id_t group);
+
+int rsbac_acl_add_group_member(rsbac_list_ta_number_t ta_number,
+			       rsbac_acl_group_id_t group,
+			       rsbac_uid_t user, rsbac_time_t ttl);
+
+int rsbac_acl_remove_group_member(rsbac_list_ta_number_t ta_number,
+				  rsbac_acl_group_id_t group,
+				  rsbac_uid_t user);
+
+/* check membership */
+rsbac_boolean_t rsbac_acl_group_member(rsbac_acl_group_id_t group,
+				       rsbac_uid_t user);
+
+/* build rsbac_kmalloc'd array of all group memberships of the given user */
+/* returns number of groups or negative error */
+/* Attention: memory deallocation with rsbac_kfree must be done by caller! */
+int rsbac_acl_get_user_groups(rsbac_list_ta_number_t ta_number,
+			      rsbac_uid_t user,
+			      rsbac_acl_group_id_t ** group_pp,
+			      rsbac_time_t ** ttl_pp);
+
+/* Returns number of members or negative error */
+int rsbac_acl_get_group_members(rsbac_list_ta_number_t ta_number,
+				rsbac_acl_group_id_t group,
+				rsbac_uid_t user_array[],
+				rsbac_time_t ttl_array[], int maxnum);
+
+/* Remove subject from all ACLs */
+int rsbac_acl_remove_subject(rsbac_list_ta_number_t ta_number,
+			     struct rsbac_acl_entry_desc_t desc);
+
+/*************************************************/
+/* remove user from all groups and from all ACLs */
+int rsbac_acl_remove_user(rsbac_list_ta_number_t ta_number,
+			  rsbac_uid_t user);
+
+/* Get list of all device entries */
+
+int rsbac_acl_list_all_dev(rsbac_list_ta_number_t ta_number,
+			   struct rsbac_dev_desc_t **id_pp);
+
+int rsbac_acl_list_all_major_dev(rsbac_list_ta_number_t ta_number,
+				 struct rsbac_dev_desc_t **id_pp);
+
+int rsbac_acl_list_all_user(rsbac_list_ta_number_t ta_number,
+			    rsbac_uid_t ** id_pp);
+
+int rsbac_acl_list_all_group(rsbac_list_ta_number_t ta_number,
+			     rsbac_gid_t ** id_pp);
+
+int rsbac_acl_list_all_ipc(rsbac_list_ta_number_t ta_number,
+			   struct rsbac_ipc_t ** id_pp);
+
+#endif
diff --git a/include/rsbac/acl_data_structures.h b/include/rsbac/acl_data_structures.h
new file mode 100644
index 0000000..9766978
--- /dev/null
+++ b/include/rsbac/acl_data_structures.h
@@ -0,0 +1,469 @@
+/**************************************/
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* Data structures / ACL              */
+/* Last modified: 07/Jan/2016         */
+/**************************************/
+
+#ifndef __RSBAC_ACL_DATA_STRUC_H
+#define __RSBAC_ACL_DATA_STRUC_H
+
+#include <linux/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/types.h>
+#include <rsbac/lists.h>
+
+#define RSBAC_ACL_LIST_KEY 0x815affe
+
+#define RSBAC_ACL_GENERAL_FD_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_FD_REQUEST_VECTOR & RSBAC_READ_WRITE_REQUEST_VECTOR ) | RSBAC_EXECUTE_REQUEST_VECTOR | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_FD_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_FD_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_EXECUTE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_FD_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_FD_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_EXECUTE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_DEV_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_DEV_REQUEST_VECTOR & RSBAC_READ_WRITE_REQUEST_VECTOR ) | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_DEV_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_DEV_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_DEV_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_DEV_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_IPC_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_IPC_REQUEST_VECTOR & RSBAC_READ_WRITE_REQUEST_VECTOR ) | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_IPC_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_IPC_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_IPC_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_IPC_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_SCD_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_SCD_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) ) \
+     ) \
+     | RSBAC_ACL_GEN_RIGHTS_VECTOR \
+   }
+
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+#define RSBAC_ACL_GENERAL_SCD_IOPORTS_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) \
+   }
+#endif
+
+#define RSBAC_ACL_GENERAL_SCD_OTHER_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+   }
+
+#define RSBAC_ACL_GENERAL_SCD_NETWORK_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+   }
+
+#define RSBAC_ACL_ACMAN_SCD_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_SCD_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_SCD_OTHER_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_NONE_REQUEST_VECTOR & \
+       ( \
+          ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+        | ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) \
+        | ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) \
+        | ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) \
+        | ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) \
+       ) \
+     ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_SCD_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_SCD_REQUEST_VECTOR & \
+       ( \
+          ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_WRITE) \
+       ) \
+     ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_SCD_OTHER_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_NONE_REQUEST_VECTOR & \
+       ( \
+          ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) \
+        | ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) \
+        | ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) \
+        | ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+        | ((rsbac_request_vector_t) 1 << R_MOUNT) \
+        | ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) \
+        | ((rsbac_request_vector_t) 1 << R_UMOUNT) \
+        | ((rsbac_request_vector_t) 1 << R_SHUTDOWN) \
+       ) \
+     ) \
+     | ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_AUDITOR_SCD_RSBACLOG_ENTRY \
+   { ACLS_USER, \
+     RSBAC_AUDITOR_UID, \
+     ( RSBAC_SCD_REQUEST_VECTOR & \
+       ( \
+          ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+        | ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) \
+       ) \
+     ) \
+   }
+
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+#define RSBAC_ACL_SYSADM_SCD_KMEM_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+   }
+#endif
+
+#define RSBAC_ACL_GENERAL_U_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) | RSBAC_REQUEST_VECTOR(R_SEARCH) \
+     | RSBAC_REQUEST_VECTOR(R_GET_STATUS_DATA) }
+
+#define RSBAC_ACL_ACMAN_U_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     RSBAC_ACL_USER_RIGHTS_VECTOR \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_U_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) | RSBAC_ACL_RIGHTS_VECTOR(R_READ_ATTRIBUTE) \
+     | RSBAC_REQUEST_VECTOR(R_SEARCH) | RSBAC_REQUEST_VECTOR(R_GET_STATUS_DATA) \
+     | RSBAC_REQUEST_VECTOR(R_AUTHENTICATE) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_P_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_PROCESS_REQUEST_VECTOR & RSBAC_READ_WRITE_REQUEST_VECTOR ) | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_P_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_PROCESS_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_P_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_PROCESS_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_G_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     RSBAC_REQUEST_VECTOR(R_SEARCH) | RSBAC_REQUEST_VECTOR(R_READ) }
+
+#define RSBAC_ACL_ACMAN_G_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_GROUP_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_G_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     RSBAC_REQUEST_VECTOR(R_SEARCH) | RSBAC_REQUEST_VECTOR(R_READ) }
+
+#define RSBAC_ACL_GENERAL_NETDEV_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_NETDEV_REQUEST_VECTOR ) | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_NETDEV_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_NETDEV_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_NETDEV_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_NETDEV_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_NETTEMP_NT_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_NETTEMP_REQUEST_VECTOR & RSBAC_READ_REQUEST_VECTOR ) | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_NETTEMP_NT_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_NETTEMP_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_NETTEMP_NT_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_NETTEMP_REQUEST_VECTOR & \
+       ( RSBAC_READ_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_GENERAL_NETOBJ_ENTRY \
+   { ACLS_GROUP, \
+     RSBAC_ACL_GROUP_EVERYONE, \
+     ( RSBAC_NETOBJ_REQUEST_VECTOR & RSBAC_READ_WRITE_REQUEST_VECTOR ) \
+     | RSBAC_REQUEST_VECTOR(R_MODIFY_SYSTEM_DATA) \
+     | RSBAC_ACL_GEN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_ACMAN_NETOBJ_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SECOFF_UID, \
+     ( RSBAC_NETOBJ_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SECURITY_REQUEST_VECTOR ) ) \
+     | RSBAC_REQUEST_VECTOR(R_MODIFY_SYSTEM_DATA) \
+     | RSBAC_ACL_ACMAN_RIGHTS_VECTOR }
+
+#define RSBAC_ACL_SYSADM_NETOBJ_ENTRY \
+   { ACLS_USER, \
+     RSBAC_SYSADM_UID, \
+     ( RSBAC_NETOBJ_REQUEST_VECTOR & \
+       ( RSBAC_READ_WRITE_REQUEST_VECTOR | RSBAC_SYSTEM_REQUEST_VECTOR ) ) \
+     | RSBAC_REQUEST_VECTOR(R_MODIFY_SYSTEM_DATA) \
+     | RSBAC_ACL_SYSADM_RIGHTS_VECTOR }
+
+
+/**********************************************/
+/* Lists of ACL / General subitems            */
+/**********************************************/
+
+/* Each list represents sets of ACL entries, using a set-id and a sublist each */
+
+#define RSBAC_ACL_VERSION 1
+
+/**********************************************/
+/* ACL and device entries for File/Dir ACL    */
+/**********************************************/
+
+#define RSBAC_ACL_FD_FILENAME "aclfd"
+#define RSBAC_ACL_FD_OLD_FILENAME "aclfd."
+#define RSBAC_ACL_DEF_FD_FILENAME "aclfd.df"
+#define RSBAC_ACL_NR_FD_LIST_BITS 2
+#define RSBAC_ACL_FD_LIST_VERSION 3
+#define RSBAC_ACL_DEF_FD_LIST_VERSION 3
+#define RSBAC_ACL_FD_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_FD_OLD_LIST_VERSION 2
+#define RSBAC_ACL_FD_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_FD_OLD_OLD_LIST_VERSION 1
+
+/* The list of devices is also a double linked list, so we define list    */
+/* items and a list head.                                                 */
+
+struct rsbac_acl_device_list_item_t {
+	kdev_t id;
+	u_int mount_count;
+	rsbac_list_handle_t handle;
+	struct rsbac_acl_device_list_item_t *prev;
+	struct rsbac_acl_device_list_item_t *next;
+};
+
+/* To provide consistency we use spinlocks for all list accesses. The     */
+/* 'curr' entry is used to avoid repeated lookups for the same item.       */
+
+struct rsbac_acl_device_list_head_t {
+	struct rsbac_acl_device_list_item_t *head;
+	struct rsbac_acl_device_list_item_t *tail;
+	struct rsbac_acl_device_list_item_t *curr;
+	u_int count;
+};
+
+
+/**********************************************/
+/* ACL entries for Device ACL                 */
+/**********************************************/
+
+#define RSBAC_ACL_DEV_FILENAME "acldev"
+#define RSBAC_ACL_DEV_MAJOR_FILENAME "acldevm"
+#define RSBAC_ACL_DEV_LIST_VERSION 4
+#define RSBAC_ACL_DEV_OLD_LIST_VERSION 3
+#define RSBAC_ACL_DEV_OLD_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEV_OLD_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_DEV_FILENAME "acldev.df"
+#define RSBAC_ACL_DEF_DEV_LIST_VERSION 3
+#define RSBAC_ACL_DEF_DEV_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_DEV_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for IPC ACL                    */
+/**********************************************/
+
+#define RSBAC_ACL_DEF_IPC_FILENAME "aclipc.df"
+#define RSBAC_ACL_DEF_IPC_LIST_VERSION 3
+#define RSBAC_ACL_DEF_IPC_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_IPC_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for SCD ACL                    */
+/**********************************************/
+
+#define RSBAC_ACL_SCD_FILENAME "aclscd"
+#define RSBAC_ACL_DEF_SCD_FILENAME "aclscd.df"
+#define RSBAC_ACL_SCD_LIST_VERSION 3
+#define RSBAC_ACL_SCD_OLD_LIST_VERSION 2
+#define RSBAC_ACL_SCD_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_SCD_LIST_VERSION 3
+#define RSBAC_ACL_DEF_SCD_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_SCD_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for user ACL                   */
+/**********************************************/
+
+#define RSBAC_ACL_U_FILENAME "acluser"
+#define RSBAC_ACL_U_LIST_VERSION 2
+#define RSBAC_ACL_U_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_U_FILENAME "acluser.df"
+#define RSBAC_ACL_DEF_U_LIST_VERSION 3
+#define RSBAC_ACL_DEF_U_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_U_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for process ACL                */
+/**********************************************/
+
+#define RSBAC_ACL_DEF_P_FILENAME "aclproc.df"
+#define RSBAC_ACL_DEF_P_LIST_VERSION 3
+#define RSBAC_ACL_DEF_P_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_P_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for Linux group ACL            */
+/**********************************************/
+
+#define RSBAC_ACL_G_FILENAME "acllgrp"
+#define RSBAC_ACL_G_LIST_VERSION 2
+#define RSBAC_ACL_G_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_G_FILENAME "acllgrp.df"
+#define RSBAC_ACL_DEF_G_LIST_VERSION 3
+#define RSBAC_ACL_DEF_G_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_G_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for Network Device ACL         */
+/**********************************************/
+
+#define RSBAC_ACL_NETDEV_FILENAME "aclndev"
+#define RSBAC_ACL_NETDEV_LIST_VERSION 3
+#define RSBAC_ACL_NETDEV_OLD_LIST_VERSION 2
+#define RSBAC_ACL_NETDEV_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_NETDEV_FILENAME "aclndev.df"
+#define RSBAC_ACL_DEF_NETDEV_LIST_VERSION 3
+#define RSBAC_ACL_DEF_NETDEV_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_NETDEV_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for Network Template NT (template protection) ACL */
+/**********************************************/
+
+#define RSBAC_ACL_NETTEMP_NT_FILENAME "aclntnt"
+#define RSBAC_ACL_NETTEMP_NT_LIST_VERSION 3
+#define RSBAC_ACL_NETTEMP_NT_OLD_LIST_VERSION 2
+#define RSBAC_ACL_NETTEMP_NT_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_NETTEMP_NT_FILENAME "aclntnt.df"
+#define RSBAC_ACL_DEF_NETTEMP_NT_LIST_VERSION 3
+#define RSBAC_ACL_DEF_NETTEMP_NT_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_NETTEMP_NT_OLD_OLD_LIST_VERSION 1
+
+/**********************************************/
+/* ACL entries for Network Object ACL         */
+/**********************************************/
+
+#define RSBAC_ACL_NETTEMP_FILENAME "aclnt"
+#define RSBAC_ACL_NETTEMP_LIST_VERSION 3
+#define RSBAC_ACL_NETTEMP_OLD_LIST_VERSION 2
+#define RSBAC_ACL_NETTEMP_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_NETOBJ_FILENAME "aclno"
+#define RSBAC_ACL_NETOBJ_LIST_VERSION 3
+#define RSBAC_ACL_NETOBJ_OLD_LIST_VERSION 2
+#define RSBAC_ACL_NETOBJ_OLD_OLD_LIST_VERSION 1
+#define RSBAC_ACL_DEF_NETOBJ_FILENAME "aclno.df"
+#define RSBAC_ACL_DEF_NETOBJ_LIST_VERSION 3
+#define RSBAC_ACL_DEF_NETOBJ_OLD_LIST_VERSION 2
+#define RSBAC_ACL_DEF_NETOBJ_OLD_OLD_LIST_VERSION 1
+
+
+/**********************************************/
+/* Group Lists                                */
+/**********************************************/
+
+#define RSBAC_ACL_GROUP_FILENAME "aclgrp"
+#define RSBAC_ACL_GM_FILENAME "aclgm"
+
+/* In acl_types.h: #define RSBAC_ACL_GROUP_VERSION 2 */
+
+#define RSBAC_ACL_GM_VERSION 2
+#define RSBAC_ACL_GM_OLD_VERSION 1
+
+#endif
diff --git a/include/rsbac/acl_getname.h b/include/rsbac/acl_getname.h
new file mode 100644
index 0000000..638b43c
--- /dev/null
+++ b/include/rsbac/acl_getname.h
@@ -0,0 +1,42 @@
+/********************************* */
+/* Rule Set Based Access Control   */
+/* Author and (c) 1999-2001:       */
+/*   Amon Ott <ao@rsbac.org>       */
+/* Getname functions for ACL parts */
+/* Last modified: 02/Aug/2001      */
+/********************************* */
+
+#ifndef __RSBAC_ACL_GETNAME_H
+#define __RSBAC_ACL_GETNAME_H
+
+#include <rsbac/types.h>
+
+char * get_acl_subject_type_name(char * name,
+                                 enum rsbac_acl_subject_type_t value);
+
+#ifndef __KERNEL__
+enum rsbac_acl_subject_type_t get_acl_subject_type_nr(const char * name);
+#endif
+
+char * get_acl_group_syscall_name(char * name,
+                                  enum rsbac_acl_group_syscall_type_t value);
+
+#ifndef __KERNEL__
+enum rsbac_acl_group_syscall_type_t get_acl_group_syscall_nr(const char * name);
+#endif
+
+char * get_acl_special_right_name(char * name,
+                            enum rsbac_acl_special_rights_t value);
+
+#ifndef __KERNEL__
+enum rsbac_acl_special_rights_t get_acl_special_right_nr(const char * name);
+#endif
+
+char * get_acl_scd_type_name(char * name,
+                             enum rsbac_acl_scd_type_t value);
+
+#ifndef __KERNEL__
+enum rsbac_acl_scd_type_t get_acl_scd_type_nr(const char * name);
+#endif
+
+#endif
diff --git a/include/rsbac/acl_types.h b/include/rsbac/acl_types.h
new file mode 100644
index 0000000..0906f59
--- /dev/null
+++ b/include/rsbac/acl_types.h
@@ -0,0 +1,351 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* API: Data types for attributes     */
+/*      and standard module calls     */
+/* Last modified: 17/Feb/2016         */
+/************************************ */
+
+#ifndef __RSBAC_ACL_TYPES_H
+#define __RSBAC_ACL_TYPES_H
+
+#include <linux/types.h>
+
+#define RSBAC_ACL_TTL_KEEP RSBAC_LIST_TTL_KEEP
+
+#define RSBAC_ACL_MAX_MAXNUM 1000000
+
+enum rsbac_acl_subject_type_t {ACLS_USER, ACLS_ROLE, ACLS_GROUP, ACLS_NONE};
+
+typedef __u8 rsbac_acl_int_subject_type_t;
+typedef __u64 rsbac_acl_subject_id_t;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_acl_subject_id_ia32_t;
+#endif
+typedef __u32 rsbac_acl_old_subject_id_t;
+
+#define RSBAC_ACL_GROUP_EVERYONE 0
+
+#define RSBAC_ACL_ROLE_EVERYROLE 64
+
+#define RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE 48
+#define RSBAC_ACL_SPECIAL_RIGHT_BASE 56
+
+enum rsbac_acl_special_rights_t
+  { ACLR_FORWARD = RSBAC_ACL_SPECIAL_RIGHT_BASE,
+    ACLR_ACCESS_CONTROL,
+    ACLR_SUPERVISOR,
+    ACLR_NONE};
+
+typedef __u64 rsbac_acl_rights_vector_t;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_acl_rights_vector_ia32_t;
+#endif
+
+#define RSBAC_ACL_RIGHTS_VECTOR(x) ((rsbac_acl_rights_vector_t) 1 << (x))
+
+#define RSBAC_ACL_SPECIAL_RIGHTS_VECTOR (\
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_FORWARD) | \
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_ACCESS_CONTROL) | \
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_SUPERVISOR) \
+  )
+
+#define RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR (\
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_SUPERVISOR) \
+  )
+#define RSBAC_NWS_REQUEST_VECTOR RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR
+
+#define RSBAC_ACL_ACCESS_CONTROL_RIGHT_VECTOR (\
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_ACCESS_CONTROL) \
+  )
+#define RSBAC_NWA_REQUEST_VECTOR RSBAC_ACL_ACCESS_CONTROL_RIGHT_VECTOR
+
+#define RSBAC_ACL_ALL_RIGHTS_VECTOR (RSBAC_ALL_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+
+#define RSBAC_ACL_DEFAULT_FD_MASK (RSBAC_FD_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_DEV_MASK (RSBAC_DEV_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_SCD_MASK (RSBAC_SCD_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_U_MASK (RSBAC_USER_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_G_MASK (RSBAC_GROUP_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_NETDEV_MASK (RSBAC_NETDEV_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_NETTEMP_MASK (RSBAC_NETTEMP_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+#define RSBAC_ACL_DEFAULT_NETOBJ_MASK (RSBAC_NETOBJ_REQUEST_VECTOR | RSBAC_ACL_SPECIAL_RIGHTS_VECTOR)
+
+#define RSBAC_ACL_USER_RIGHTS_VECTOR (RSBAC_USER_REQUEST_VECTOR \
+                                      | RSBAC_ACL_RIGHTS_VECTOR(R_DELETE))
+
+#define RSBAC_ACL_GROUP_RIGHTS_VECTOR RSBAC_GROUP_REQUEST_VECTOR
+
+#define RSBAC_ACL_GEN_RIGHTS_VECTOR 0
+
+#define RSBAC_ACL_ACMAN_RIGHTS_VECTOR (\
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_FORWARD) | \
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_ACCESS_CONTROL) | \
+  ((rsbac_acl_rights_vector_t) 1 << ACLR_SUPERVISOR) \
+  )
+
+#define RSBAC_ACL_SYSADM_RIGHTS_VECTOR 0
+
+/*
+ * System Control Types, including general SCD types
+ * (start at 32 to allow future SCD types, max is 63)
+ * (should always be same as in RC model)
+ */
+#define AST_min 32
+enum rsbac_acl_scd_type_t{AST_auth_administration = AST_min,
+                          AST_udf_administration,
+                          AST_none};
+
+/* note: the desc struct must be the same as the beginning of the entry struct! */
+struct rsbac_acl_entry_t
+  {
+    rsbac_acl_int_subject_type_t subj_type;  /* enum rsbac_acl_subject_type_t */
+    rsbac_acl_subject_id_t       subj_id;
+    rsbac_acl_rights_vector_t    rights;
+  };
+
+struct rsbac_acl_entry_desc_t
+  {
+    rsbac_acl_int_subject_type_t subj_type;  /* enum rsbac_acl_subject_type_t */
+    rsbac_acl_subject_id_t       subj_id;
+  };
+
+struct rsbac_acl_old_entry_desc_t
+  {
+    rsbac_acl_int_subject_type_t subj_type;  /* enum rsbac_acl_subject_type_t */
+    rsbac_acl_old_subject_id_t   subj_id;
+  };
+
+enum rsbac_acl_group_type_t {ACLG_GLOBAL, ACLG_PRIVATE, ACLG_NONE};
+
+typedef __u32 rsbac_acl_group_id_t;
+
+#define RSBAC_ACL_GROUP_NAMELEN 16
+
+#define RSBAC_ACL_GROUP_VERSION 2
+
+struct rsbac_acl_group_entry_t
+  {
+         rsbac_acl_group_id_t   id;
+         rsbac_uid_t            owner;
+    enum rsbac_acl_group_type_t type;
+         char                   name[RSBAC_ACL_GROUP_NAMELEN];
+  };
+
+/**** syscalls ****/
+
+enum rsbac_acl_syscall_type_t
+  {
+    ACLC_set_acl_entry,
+    ACLC_remove_acl_entry,
+    ACLC_remove_acl,
+    ACLC_add_to_acl_entry,
+    ACLC_remove_from_acl_entry,
+    ACLC_set_mask,
+    ACLC_remove_user,
+    ACLC_none
+  };
+
+struct rsbac_acl_syscall_arg_t
+  {
+    enum   rsbac_target_t              target;
+    union  rsbac_target_id_t           tid;
+    enum   rsbac_acl_subject_type_t    subj_type;
+           rsbac_acl_subject_id_t      subj_id;
+           rsbac_acl_rights_vector_t   rights;
+           rsbac_time_t                ttl;
+  };
+
+struct rsbac_acl_syscall_n_arg_t
+  {
+    enum   rsbac_target_t              target;
+           char                        __user * name;
+    enum   rsbac_acl_subject_type_t    subj_type;
+           rsbac_acl_subject_id_t      subj_id;
+           rsbac_acl_rights_vector_t   rights;
+           rsbac_time_t                ttl;
+  };
+
+
+enum rsbac_acl_group_syscall_type_t
+  {
+    ACLGS_add_group,
+    ACLGS_change_group,
+    ACLGS_remove_group,
+    ACLGS_get_group_entry,
+    ACLGS_list_groups,
+    ACLGS_add_member,
+    ACLGS_remove_member,
+    ACLGS_get_user_groups,
+    ACLGS_get_group_members,
+    ACLGS_none
+  };
+
+struct rsbac_acl_add_group_arg_t
+  {
+    enum rsbac_acl_group_type_t type;
+    char __user * name;
+    rsbac_acl_group_id_t * group_id_p;
+  };
+
+struct rsbac_acl_change_group_arg_t
+  {
+         rsbac_acl_group_id_t     id;
+         rsbac_uid_t              owner;
+    enum rsbac_acl_group_type_t   type;
+         char                  __user * name;
+  };
+
+struct rsbac_acl_remove_group_arg_t
+  {
+    rsbac_acl_group_id_t id;
+  };
+
+struct rsbac_acl_get_group_entry_arg_t
+  {
+    rsbac_acl_group_id_t id;
+    struct rsbac_acl_group_entry_t __user * entry_p;
+  };
+
+struct rsbac_acl_list_groups_arg_t
+  {
+    rsbac_boolean_t        include_global;
+    struct rsbac_acl_group_entry_t __user * group_entry_array;
+    u_int                  maxnum;
+  };
+
+struct rsbac_acl_add_member_arg_t
+  {
+    rsbac_acl_group_id_t group;
+    rsbac_uid_t          user;
+    rsbac_time_t ttl;
+  };
+
+struct rsbac_acl_remove_member_arg_t
+  {
+    rsbac_acl_group_id_t group;
+    rsbac_uid_t          user;
+  };
+
+struct rsbac_acl_get_user_groups_arg_t
+  {
+    rsbac_uid_t            user;
+    rsbac_acl_group_id_t   __user * group_array;
+    rsbac_time_t           __user * ttl_array;
+    u_int                  maxnum;
+  };
+
+struct rsbac_acl_get_group_members_arg_t
+  {
+    rsbac_acl_group_id_t   group;
+    rsbac_uid_t            __user * user_array;
+    rsbac_time_t           __user * ttl_array;
+    u_int                  maxnum;
+  };
+
+union rsbac_acl_group_syscall_arg_t
+  {
+    struct rsbac_acl_add_group_arg_t         add_group;
+    struct rsbac_acl_change_group_arg_t      change_group;
+    struct rsbac_acl_remove_group_arg_t      remove_group;
+    struct rsbac_acl_get_group_entry_arg_t   get_group_entry;
+    struct rsbac_acl_list_groups_arg_t       list_groups;
+    struct rsbac_acl_add_member_arg_t        add_member;
+    struct rsbac_acl_remove_member_arg_t     remove_member;
+    struct rsbac_acl_get_user_groups_arg_t   get_user_groups;
+    struct rsbac_acl_get_group_members_arg_t get_group_members;
+  };
+
+/*
+ * 32 Bit emulation support on x86_64 system
+ */
+
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+struct rsbac_acl_syscall_n_arg_ia32_t
+  {
+    enum   rsbac_target_t              target;
+           __u32                       name;
+    enum   rsbac_acl_subject_type_t    subj_type;
+           rsbac_acl_subject_id_ia32_t subj_id;
+           rsbac_acl_rights_vector_ia32_t rights;
+           rsbac_time_t                ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_add_group_arg_ia32_t
+  {
+    enum rsbac_acl_group_type_t type;
+    __u32 name;
+    __u32 group_id_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_change_group_arg_ia32_t
+  {
+         rsbac_acl_group_id_t     id;
+         rsbac_uid_ia32_t         owner;
+    enum rsbac_acl_group_type_t   type;
+         __u32                    name;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_remove_group_arg_ia32_t
+  {
+    rsbac_acl_group_id_t id;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_get_group_entry_arg_ia32_t
+  {
+    rsbac_acl_group_id_t id;
+    __u32                entry_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_list_groups_arg_ia32_t
+  {
+    rsbac_boolean_t include_global;
+    __u32           group_entry_array;
+    __u32           maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_add_member_arg_ia32_t
+  {
+    rsbac_acl_group_id_t group;
+    rsbac_uid_ia32_t user;
+    rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_remove_member_arg_ia32_t
+  {
+    rsbac_acl_group_id_t group;
+    rsbac_uid_ia32_t     user;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_get_user_groups_arg_ia32_t
+  {
+    rsbac_uid_ia32_t user;
+    __u32       group_array;
+    __u32       ttl_array;
+    __u32       maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsbac_acl_get_group_members_arg_ia32_t
+  {
+    rsbac_acl_group_id_t   group;
+    rsbac_uid_ia32_t            __user * user_array;
+    rsbac_time_t           __user * ttl_array;
+    __u32                  maxnum;
+  } __attribute__ ((aligned (4)));
+
+union rsbac_acl_group_syscall_arg_ia32_t
+  {
+    struct rsbac_acl_add_group_arg_ia32_t         add_group;
+    struct rsbac_acl_change_group_arg_ia32_t      change_group;
+    struct rsbac_acl_remove_group_arg_ia32_t      remove_group;
+    struct rsbac_acl_get_group_entry_arg_ia32_t   get_group_entry;
+    struct rsbac_acl_list_groups_arg_ia32_t       list_groups;
+    struct rsbac_acl_add_member_arg_ia32_t        add_member;
+    struct rsbac_acl_remove_member_arg_ia32_t     remove_member;
+    struct rsbac_acl_get_user_groups_arg_ia32_t   get_user_groups;
+    struct rsbac_acl_get_group_members_arg_ia32_t get_group_members;
+  } __attribute__ ((aligned (4)));
+#endif
+
+#endif
diff --git a/include/rsbac/adf.h b/include/rsbac/adf.h
new file mode 100644
index 0000000..0a7aa68
--- /dev/null
+++ b/include/rsbac/adf.h
@@ -0,0 +1,138 @@
+/******************************* */
+/* Rule Set Based Access Control */
+/* Author and (c) 1999-2009:     */
+/*   Amon Ott <ao@rsbac.org>     */
+/* API: for Access Control       */
+/* Decision Facility             */
+/* Last modified: 16/Jan/2009    */
+/******************************* */
+
+#ifndef __RSBAC_ADF_H
+#define __RSBAC_ADF_H
+
+#include <linux/init.h>
+#include <linux/binfmts.h>
+#include <asm/page.h>
+#include <rsbac/types.h>
+#include <rsbac/debug.h>
+#include <rsbac/fs.h>
+
+/***************************************************/
+/*                   Prototypes                    */
+/***************************************************/
+
+/* Init function */
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern  void rsbac_init_adf(void);
+#else
+extern  void rsbac_init_adf(void) __init;
+#endif
+
+/* This function is the internal decision function, called from the next. */
+/* It allows to ignore a certain module (last parameter), e.g. for asking */
+/* all _other_ modules, but not the calling module, to avoid a circle.    */
+
+extern enum rsbac_adf_req_ret_t
+   rsbac_adf_request_int(enum  rsbac_adf_request_t     request,
+                               rsbac_pid_t             caller_pid,
+                         enum  rsbac_target_t          target,
+                         union rsbac_target_id_t     * tid_p,
+                         enum  rsbac_attribute_t       attr,
+                         union rsbac_attribute_value_t * attr_val_p,
+                         enum  rsbac_switch_target_t   ignore_module);
+
+/*********************************************************************/
+/* rsbac_adf_request()                                               */
+/* This function is the main decision function, called from the AEF. */
+/* It is a simple wrapper to the internal function, setting          */
+/* ignore_module to SW_NONE.                                         */
+
+static inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request( 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)
+  {
+    return rsbac_adf_request_int(request,
+                                 caller_pid,
+                                 target,
+                                 &tid,
+                                 attr,
+                                 &attr_val,
+                                 SW_NONE);
+  }
+
+
+/* If the request returned granted and the operation is performed,           */
+/* the following function is called by the AEF to get all aci set correctly. */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* It returns 0 on success and an error from error.h otherwise.              */
+
+extern  int  rsbac_adf_set_attr(     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t);
+
+#include <linux/types.h>
+#include <linux/dcache.h>
+
+int rsbac_sec_del(struct dentry * dentry_p, u_int may_sync);
+
+int rsbac_sec_trunc(struct dentry * dentry_p,
+                    loff_t new_len, loff_t old_len);
+
+/* This function changes the symlink content by adding a suffix, if
+ * requested. It returns NULL, if unchanged, or a pointer to a
+ * kmalloc'd new char * otherwise, which has to be kfree'd after use.
+ */
+char * rsbac_symlink_redirect(
+  struct inode * inode_p,
+  const char * name,
+  u_int maxlen);
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+extern int rsbac_dac_part_disabled(struct dentry * dentry_p);
+#endif
+
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+extern rsbac_uid_t rsbac_fake_uid(void);
+extern rsbac_uid_t rsbac_fake_euid(void);
+extern int rsbac_uid_faked(void);
+#endif
+
+int rsbac_cap_check_envp(struct linux_binprm *bprm);
+
+extern int rsbac_handle_filldir(const struct file *file, const char *name, const unsigned int namlen, const ino_t ino);
+
+int rsbac_set_audit_uid(rsbac_uid_t uid);
+
+/* Mostly copied from drivers/char/mem.c */
+static inline rsbac_boolean_t rsbac_is_videomem(unsigned long pfn, unsigned long size)
+{
+/* Intel architecture is a security disaster */
+#if defined X86_64 || defined X86
+
+	u64 from = ((u64)pfn) << PAGE_SHIFT;
+	u64 to = from + size;
+	u64 cursor = from;
+
+	while (cursor < to) {
+		if (!devmem_is_allowed(pfn)) {
+			return FALSE;
+		}
+		cursor += PAGE_SIZE;
+		pfn++;
+	}
+	return TRUE;
+#endif
+	return TRUE;
+};
+
+#endif
diff --git a/include/rsbac/adf_main.h b/include/rsbac/adf_main.h
new file mode 100644
index 0000000..5249e15
--- /dev/null
+++ b/include/rsbac/adf_main.h
@@ -0,0 +1,798 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2013:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* Data Structs etc. for Access       */
+/* Control Decision Facility          */
+/* Last modified: 28/Nov/2013         */
+/************************************ */
+
+#ifndef __RSBAC_ADF_MAIN_H
+#define __RSBAC_ADF_MAIN_H
+
+#include <linux/sched.h>
+#include <rsbac/types.h>
+
+#if defined(CONFIG_RSBAC_REG)
+#include <rsbac/reg.h>
+#endif
+
+#ifdef CONFIG_RSBAC_SECDEL
+#include <linux/dcache.h>
+#endif
+
+/***************************************************/
+/*              Global Variables                   */
+/***************************************************/
+
+extern __u64 rsbac_adf_request_count[T_NONE+1];
+extern __u64 rsbac_adf_set_attr_count[T_NONE+1];
+#ifdef CONFIG_RSBAC_XSTATS
+extern __u64 rsbac_adf_request_xcount[T_NONE+1][R_NONE];
+extern __u64 rsbac_adf_set_attr_xcount[T_NONE+1][R_NONE];
+#endif
+
+/* Bitmasks to ignore some requests on some modules */
+
+#ifdef CONFIG_RSBAC_MAC
+#define RSBAC_MAC_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) \
+  )
+#define RSBAC_MAC_SET_ATTR_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) \
+  )
+#endif
+
+#ifdef CONFIG_RSBAC_DAZ
+#define RSBAC_DAZ_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) \
+  )
+#define RSBAC_DAZ_SET_ATTR_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) )
+#endif
+
+#ifdef CONFIG_RSBAC_FF
+#if defined(CONFIG_RSBAC_FF_UM_PROT)
+#define RSBAC_FF_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+  )
+#else
+#define RSBAC_FF_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+  )
+#endif
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH
+#if defined(CONFIG_RSBAC_AUTH_UM_PROT)
+#define RSBAC_AUTH_REQUEST_VECTOR_UM (\
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) )
+#else
+#define RSBAC_AUTH_REQUEST_VECTOR_UM 0
+#endif
+#if defined(CONFIG_RSBAC_AUTH_UM_PROT) || defined(CONFIG_RSBAC_AUTH_GROUP)
+#define RSBAC_AUTH_REQUEST_VECTOR_CG ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP)
+#else
+#define RSBAC_AUTH_REQUEST_VECTOR_CG 0
+#endif
+#if defined(CONFIG_RSBAC_AUTH_GROUP) && defined (CONFIG_RSBAC_AUTH_DAC_GROUP)
+#define RSBAC_AUTH_REQUEST_VECTOR_DG ( \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) )
+#else
+#define RSBAC_AUTH_REQUEST_VECTOR_DG 0
+#endif
+#if defined (CONFIG_RSBAC_AUTH_DAC_OWNER)
+#define RSBAC_AUTH_REQUEST_VECTOR_DO ( \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) )
+#else
+#define RSBAC_AUTH_REQUEST_VECTOR_DO 0
+#endif
+#if defined (CONFIG_RSBAC_AUTH_AUTH_PROT)
+#define RSBAC_AUTH_REQUEST_VECTOR_AA ( \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) )
+#else
+#define RSBAC_AUTH_REQUEST_VECTOR_AA 0
+#endif
+
+#define RSBAC_AUTH_REQUEST_VECTOR (\
+  RSBAC_AUTH_REQUEST_VECTOR_UM | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  RSBAC_AUTH_REQUEST_VECTOR_CG | \
+  RSBAC_AUTH_REQUEST_VECTOR_DG | \
+  RSBAC_AUTH_REQUEST_VECTOR_DO | \
+  RSBAC_AUTH_REQUEST_VECTOR_AA | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) \
+  )
+
+#if defined (CONFIG_RSBAC_AUTH_AUTH_PROT)
+#define RSBAC_AUTH_SET_ATTR_VECTOR_AA ( \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) )
+#else
+#define RSBAC_AUTH_SET_ATTR_VECTOR_AA 0
+#endif
+#define RSBAC_AUTH_SET_ATTR_VECTOR (\
+  RSBAC_AUTH_SET_ATTR_VECTOR_AA | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) \
+  )
+#endif
+
+#ifdef CONFIG_RSBAC_CAP
+#ifdef CONFIG_RSBAC_CAP_PROC_HIDE
+#define RSBAC_CAP_REQUEST_VECTOR ( \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) )
+#else
+#define RSBAC_CAP_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) )
+#endif
+#if defined (CONFIG_RSBAC_CAP_PROC_HIDE) || defined(CONFIG_RSBAC_CAP_LOG_MISSING)
+#define RSBAC_CAP_SET_ATTR_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) )
+#else
+#define RSBAC_CAP_SET_ATTR_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) )
+#endif
+#endif
+
+#ifdef CONFIG_RSBAC_JAIL
+#define RSBAC_JAIL_REQUEST_VECTOR ( \
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) | \
+  ((rsbac_request_vector_t) 1 << R_NET_SHUTDOWN) )
+#define RSBAC_JAIL_SET_ATTR_VECTOR ( \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) )
+#endif
+
+#ifdef CONFIG_RSBAC_PAX
+#define RSBAC_PAX_REQUEST_VECTOR ( \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) )
+#endif
+
+#ifdef CONFIG_RSBAC_RES
+#define RSBAC_RES_REQUEST_VECTOR ( \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) )
+#define RSBAC_RES_SET_ATTR_VECTOR ( \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) )
+#endif
+
+#ifdef CONFIG_RSBAC_UDF
+#define RSBAC_UDF_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) \
+  )
+#define RSBAC_UDF_SET_ATTR_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) )
+#endif
+
+/***************************************************/
+/*              General Prototypes                 */
+/***************************************************/
+
+/* We call this function in kernel/sched.c         */
+extern struct task_struct * find_process_by_pid(pid_t);
+
+#ifdef CONFIG_RSBAC_DEBUG
+extern  enum rsbac_adf_req_ret_t
+   rsbac_adf_request_check (enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             caller_pid,
+                            enum  rsbac_target_t          target,
+                            union rsbac_target_id_t     * tid_p,
+                            enum  rsbac_attribute_t       attr,
+                            union rsbac_attribute_value_t * attr_val_p,
+                                  rsbac_uid_t             owner);
+
+extern int rsbac_adf_set_attr_check( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+#endif
+
+extern enum rsbac_adf_req_ret_t
+    adf_and_plus(enum rsbac_adf_req_ret_t res1,
+                 enum rsbac_adf_req_ret_t res2);
+
+/***************************************************/
+/*              Module Prototypes                  */
+/***************************************************/
+
+/******* MAC ********/
+
+#ifdef CONFIG_RSBAC_MAC
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+extern  rsbac_boolean_t rsbac_switch_mac;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_mac(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_mac( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif  /* MAC */
+
+/******* DAZ ********/
+
+#ifdef CONFIG_RSBAC_DAZ
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+extern  rsbac_boolean_t rsbac_switch_daz;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_daz(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_daz (enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif  /* DAZ */
+ 
+/******* FF ********/
+
+#ifdef CONFIG_RSBAC_FF
+#ifdef CONFIG_RSBAC_SWITCH_FF
+extern  rsbac_boolean_t rsbac_switch_ff;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_ff(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_ff ( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#ifdef CONFIG_RSBAC_SECDEL
+extern rsbac_boolean_t rsbac_need_overwrite_ff(struct dentry * dentry_p);
+#endif
+
+#endif  /* FF */
+ 
+/******* RC ********/
+
+#ifdef CONFIG_RSBAC_RC
+#ifdef CONFIG_RSBAC_SWITCH_RC
+extern  rsbac_boolean_t rsbac_switch_rc;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_rc(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_rc ( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+/* Secure delete/truncate for this module */
+#ifdef CONFIG_RSBAC_SECDEL
+extern rsbac_boolean_t rsbac_need_overwrite_rc(struct dentry * dentry_p);
+#endif
+#endif  /* RC */
+
+/****** AUTH *******/
+
+#ifdef CONFIG_RSBAC_AUTH
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+extern  rsbac_boolean_t rsbac_switch_auth;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_auth(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_auth(enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif /* AUTH */
+
+/****** ACL *******/
+
+#ifdef CONFIG_RSBAC_ACL
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+extern  rsbac_boolean_t rsbac_switch_acl;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_acl(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_acl (enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif /* ACL */
+
+/****** CAP *******/
+
+#ifdef CONFIG_RSBAC_CAP
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+extern  rsbac_boolean_t rsbac_switch_cap;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_cap(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_cap (enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif /* CAP */
+
+/****** JAIL *******/
+
+#ifdef CONFIG_RSBAC_JAIL
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+extern  rsbac_boolean_t rsbac_switch_jail;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_jail(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_jail(enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif /* JAIL */
+
+/******* PAX ********/
+
+#ifdef CONFIG_RSBAC_PAX
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+extern  rsbac_boolean_t rsbac_switch_pax;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_pax(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_pax( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif  /* PAX */
+
+
+/****** RES *******/
+
+#ifdef CONFIG_RSBAC_RES
+#ifdef CONFIG_RSBAC_SWITCH_RES
+extern  rsbac_boolean_t rsbac_switch_res;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_res(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_res (enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#ifdef CONFIG_RSBAC_SECDEL
+extern inline rsbac_boolean_t rsbac_need_overwrite_res(struct dentry * dentry_p)
+  {
+    return FALSE;
+  }
+#endif
+#endif /* RES */
+
+/******* UDF ********/
+
+#ifdef CONFIG_RSBAC_UDF
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+extern  rsbac_boolean_t rsbac_switch_udf;
+#endif
+
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_udf(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_udf (enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#endif  /* UDF */
+
+/****** REG *******/
+
+#if defined(CONFIG_RSBAC_REG)
+extern  enum rsbac_adf_req_ret_t  rsbac_adf_request_reg(
+                                     enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+extern  int  rsbac_adf_set_attr_reg (enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+#ifdef CONFIG_RSBAC_SECDEL
+extern inline rsbac_boolean_t rsbac_need_overwrite_reg(struct dentry * dentry_p)
+  {
+    return FALSE;
+  }
+#endif
+#endif /* REG */
+
+#if defined(CONFIG_RSBAC_REG)
+/* Init */
+#ifdef CONFIG_RSBAC_INIT_DELAY
+void rsbac_reg_init(void);
+#else
+void rsbac_reg_init(void) __init;
+#endif
+
+/* mounting and umounting */
+extern int rsbac_mount_reg(kdev_t kdev);
+extern int rsbac_umount_reg(kdev_t kdev);
+
+/* RSBAC attribute saving to disk can be triggered from outside
+ * param: call lock_kernel() before writing?
+ */
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+extern int rsbac_write_reg(void);
+#endif /* CONFIG_RSBAC_AUTO_WRITE */
+
+/* Status checking */
+extern int rsbac_check_reg(int correct, int check_inode);
+
+#endif /* REG */
+
+#endif /* End of adf_main.h */
diff --git a/include/rsbac/adf_syshelpers.h b/include/rsbac/adf_syshelpers.h
new file mode 100644
index 0000000..5f1f91f
--- /dev/null
+++ b/include/rsbac/adf_syshelpers.h
@@ -0,0 +1,266 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2013:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/*                                    */
+/* Helper Prototypes for model        */
+/* specific system calls              */
+/* Last modified: 18/Nov/2013         */
+/************************************ */
+
+#ifndef __RSBAC_ADF_SYSHELPERS_H
+#define __RSBAC_ADF_SYSHELPERS_H
+
+/* #include <linux/sched.h> */
+#include <rsbac/types.h>
+
+/***************************************************/
+/*              Global Variables                   */
+/***************************************************/
+
+/***************************************************/
+/*              General Prototypes                 */
+/***************************************************/
+
+/***************************************************/
+/*              Module Prototypes                  */
+/***************************************************/
+
+/******* MAC ********/
+
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_MAC_MAINT)
+int  rsbac_mac_set_curr_level(rsbac_security_level_t level,
+                              rsbac_mac_category_vector_t categories);
+
+int  rsbac_mac_get_curr_level(rsbac_security_level_t * level_p,
+                              rsbac_mac_category_vector_t * categories_p);
+
+int  rsbac_mac_get_max_level(rsbac_security_level_t * level_p,
+                             rsbac_mac_category_vector_t * categories_p);
+
+int  rsbac_mac_get_min_level(rsbac_security_level_t * level_p,
+                             rsbac_mac_category_vector_t * categories_p);
+
+int rsbac_mac_add_p_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t uid,
+  rsbac_time_t ttl);
+
+int rsbac_mac_remove_p_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t uid);
+
+int rsbac_mac_add_f_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t uid,
+  rsbac_time_t ttl);
+
+int rsbac_mac_remove_f_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t uid);
+
+#endif  /* MAC */
+
+
+/******* FF ********/
+
+/******* RC ********/
+
+#if defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_RC_MAINT)
+/* These functions in adf/rc/syscalls.c are called via sys_* system calls    */
+/* and check for validity before passing the call to the rc_data_structures. */
+
+/* All roles are always there, so instead of creation, we supply a copy for */
+/* initialization. There is always the well-defined role general to copy    */
+extern int rsbac_rc_sys_copy_role (
+  rsbac_list_ta_number_t ta_number,
+  rsbac_rc_role_id_t from_role,
+  rsbac_rc_role_id_t to_role);
+
+extern int rsbac_rc_sys_copy_type (
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t      target,
+        rsbac_rc_type_id_t     from_type,
+        rsbac_rc_type_id_t     to_type);
+
+/* Getting item values */
+extern int rsbac_rc_sys_get_item (
+  rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t       target,
+  union rsbac_rc_target_id_t    tid,
+  union rsbac_rc_target_id_t    subtid,
+  enum  rsbac_rc_item_t         item,
+  union rsbac_rc_item_value_t * value_p,
+        rsbac_time_t          * ttl_p);
+
+/* Setting item values */
+extern int rsbac_rc_sys_set_item (
+  rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t       target,
+  union rsbac_rc_target_id_t    tid,
+  union rsbac_rc_target_id_t    subtid,
+  enum  rsbac_rc_item_t         item,
+  union rsbac_rc_item_value_t   value,
+        rsbac_time_t            ttl);
+
+/* Set own role, if allowed ( = in role_comp vector of current role) */
+extern int rsbac_rc_sys_change_role (rsbac_rc_role_id_t role, char __user * pass);
+
+/* Getting own effective rights */
+int rsbac_rc_sys_get_eff_rights (
+  rsbac_list_ta_number_t ta_number,
+  enum  rsbac_target_t       target,
+  union rsbac_target_id_t    tid,
+        rsbac_rc_request_vector_t * request_vector,
+        rsbac_time_t          * ttl_p);
+
+int rsbac_rc_sys_get_current_role (rsbac_rc_role_id_t * role_p);
+
+#endif  /* RC || RC_MAINT */
+
+/****** AUTH *******/
+
+#if defined(CONFIG_RSBAC_AUTH) || defined(CONFIG_RSBAC_AUTH_MAINT)
+/* This function is called via sys_rsbac_auth_add_p_cap() system call */
+int rsbac_auth_add_p_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl);
+
+/* This function is called via sys_rsbac_auth_remove_p_cap() system call */
+int rsbac_auth_remove_p_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range);
+
+/* This function is called via sys_rsbac_auth_add_f_cap() system call */
+int rsbac_auth_add_f_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_auth_file_t file,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl);
+
+/* This function is called via sys_rsbac_auth_remove_f_cap() system call */
+int rsbac_auth_remove_f_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_auth_file_t file,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range);
+
+#endif  /* AUTH || AUTH_MAINT */
+
+/****** REG *******/
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+/*
+ * System call dispatcher
+ * Returns 0 on success or -EINVALIDTARGET, if handle is invalid.
+ */
+
+int rsbac_reg_syscall(rsbac_reg_handle_t handle,
+                      void __user * arg);
+#endif /* REG || REG_MAINT */
+
+/****** ACL *******/
+
+#if defined(CONFIG_RSBAC_ACL) || defined(CONFIG_RSBAC_ACL_MAINT)
+int rsbac_acl_sys_set_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t   rights,
+         rsbac_time_t                ttl);
+
+int rsbac_acl_sys_remove_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id);
+
+int rsbac_acl_sys_remove_acl(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid);
+
+int rsbac_acl_sys_add_to_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t   rights,
+         rsbac_time_t                ttl);
+
+int rsbac_acl_sys_remove_from_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t   rights);
+
+int rsbac_acl_sys_set_mask(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+         rsbac_acl_rights_vector_t   mask);
+
+int rsbac_acl_sys_remove_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid);
+
+int rsbac_acl_sys_get_mask(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+         rsbac_acl_rights_vector_t * mask_p);
+
+
+int rsbac_acl_sys_get_rights(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t * rights_p,
+         rsbac_boolean_t             inherit);
+
+int rsbac_acl_sys_get_tlist(
+         rsbac_list_ta_number_t    ta_number,
+  enum   rsbac_target_t            target,
+  union  rsbac_target_id_t         tid,
+  struct rsbac_acl_entry_t      ** entry_pp,
+         rsbac_time_t           ** ttl_pp);
+
+int rsbac_acl_sys_group(
+        rsbac_list_ta_number_t         ta_number,
+  enum  rsbac_acl_group_syscall_type_t call,
+  union rsbac_acl_group_syscall_arg_t  arg);
+
+#endif  /* ACL || ACL_MAINT */
+
+/****** JAIL *******/
+
+#if defined(CONFIG_RSBAC_JAIL)
+/* This function is called via sys_rsbac_jail() system call */
+int rsbac_jail_sys_jail(rsbac_version_t version,
+                        char __user * path,
+                        rsbac_jail_ip_t ip,
+                        rsbac_jail_flags_t flags,
+                        rsbac_cap_vector_t max_caps,
+                        rsbac_jail_scd_vector_t scd_get,
+                        rsbac_jail_scd_vector_t scd_modify);
+#endif
+
+#endif /* End of adf_syshelpers.h */
diff --git a/include/rsbac/auth.h b/include/rsbac/auth.h
new file mode 100644
index 0000000..9960bef
--- /dev/null
+++ b/include/rsbac/auth.h
@@ -0,0 +1,154 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2013:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* API: Data structures               */
+/* and functions for Access           */
+/* Control Information / AUTH         */
+/* Last modified: 09/Aug/2013         */
+/************************************ */
+
+#ifndef __RSBAC_AUTH_H
+#define __RSBAC_AUTH_H
+
+#include <linux/init.h>
+#include <rsbac/types.h>
+
+/***************************************************/
+/*               General Prototypes                */
+/***************************************************/
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+/****************************************************************************/
+/* Initialization, including ACI restoration for all mounted devices from   */
+/* disk. After this call, all ACI is kept in memory for performance reasons,*/
+/* but user and file/dir object ACI are written to disk on every change.    */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern int rsbac_init_auth(void);
+#else
+extern int rsbac_init_auth(void) __init;
+#endif
+
+/* mounting and umounting */
+int rsbac_mount_auth(kdev_t kdev);
+int rsbac_umount_auth(kdev_t kdev);
+
+/* Some information about the current status is also available */
+extern int rsbac_stats_auth(void);
+
+/* Status checking */
+extern int rsbac_check_auth(int correct, int check_inode);
+
+/* RSBAC attribute saving to disk can be triggered from outside
+ * param: call lock_kernel() before writing?
+ */
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+extern int rsbac_write_auth(rsbac_boolean_t);
+#endif /* CONFIG_RSBAC_AUTO_WRITE */
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the semaphores to protect the targets during */
+/* access.                                                                  */
+/* Trying to access a never created or removed set returns an error!        */
+
+/* rsbac_auth_add_to_p_capset */
+/* Add a set member to a set sublist. Set behaviour: also returns success, */
+/* if member was already in set! */
+
+int rsbac_auth_add_to_p_capset(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl);
+
+int rsbac_auth_add_to_f_capset(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_auth_file_t file,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl);
+
+/* rsbac_auth_remove_from_p_capset */
+/* Remove a set member from a sublist. Set behaviour: Returns no error, if */
+/* member is not in list.                                                  */
+
+int rsbac_auth_remove_from_p_capset(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range);
+
+int rsbac_auth_remove_from_f_capset(
+        rsbac_list_ta_number_t ta_number,
+        rsbac_auth_file_t file,
+  enum  rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range);
+
+/* rsbac_auth_clear_p_capset */
+/* Remove all set members from a sublist. Set behaviour: Returns no error, */
+/* if list is empty.                                                       */
+
+int rsbac_auth_clear_p_capset(
+       rsbac_list_ta_number_t ta_number,
+       rsbac_pid_t pid,
+  enum rsbac_auth_cap_type_t cap_type);
+
+int rsbac_auth_clear_f_capset(
+       rsbac_list_ta_number_t ta_number,
+       rsbac_auth_file_t file,
+  enum rsbac_auth_cap_type_t cap_type);
+
+/* rsbac_auth_p_capset_member */
+/* Return truth value, whether member is in set */
+
+rsbac_boolean_t  rsbac_auth_p_capset_member(rsbac_pid_t pid,
+                                    enum rsbac_auth_cap_type_t cap_type,
+                                    rsbac_uid_t member);
+
+/* rsbac_auth_remove_p_capset */
+/* Remove a full set. After this call the given id can only be used for */
+/* creating a new set, anything else returns an error.                  */
+/* To empty an existing set use rsbac_auth_clear_p_capset.                */
+
+int rsbac_auth_remove_p_capsets(rsbac_pid_t pid);
+
+int rsbac_auth_remove_f_capsets(rsbac_auth_file_t file);
+
+/* rsbac_auth_copy_fp_capset */
+/* copy a file capset to a process capset */
+int rsbac_auth_copy_fp_capset(rsbac_auth_file_t    file,
+                              rsbac_pid_t p_cap_set_id);
+
+/* rsbac_auth_copy_pp_capset */
+/* copy a process capset to another process capset */
+int rsbac_auth_copy_pp_capset(rsbac_pid_t old_p_set_id,
+                              rsbac_pid_t new_p_set_id);
+
+/* rsbac_auth_get_f_caplist */
+/* copy a file/dir capset to an array of length 2 * maxnum (first+last), */
+/* returns number of caps copied */
+int rsbac_auth_get_f_caplist(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_auth_file_t file,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t **caplist_p,
+         rsbac_time_t **ttllist_p);
+
+/* rsbac_auth_get_p_caplist */
+/* copy a process capset to an array of length 2 * maxnum (first+last), */
+/* returns number of caps copied */
+int rsbac_auth_get_p_caplist(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t **caplist_p,
+         rsbac_time_t **ttllist_p);
+
+#endif
diff --git a/include/rsbac/auth_data_structures.h b/include/rsbac/auth_data_structures.h
new file mode 100644
index 0000000..5ef0ea1
--- /dev/null
+++ b/include/rsbac/auth_data_structures.h
@@ -0,0 +1,97 @@
+/**************************************/
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016:          */
+/*   Amon Ott <ao@rsbac.org> */
+/* Data structures / AUTH             */
+/* Last modified: 07/Jan/2016         */
+/**************************************/
+
+#ifndef __RSBAC_AUTH_DATA_STRUC_H
+#define __RSBAC_AUTH_DATA_STRUC_H
+
+#include <linux/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/types.h>
+
+/**********************************************/
+/* Capability lists                           */
+/**********************************************/
+
+#define RSBAC_AUTH_LIST_KEY 626281
+
+#define RSBAC_AUTH_P_LIST_VERSION 1
+#define RSBAC_AUTH_P_LIST_NAME "authproc"
+#define RSBAC_AUTH_P_EFF_LIST_NAME "authproceff"
+#define RSBAC_AUTH_P_FS_LIST_NAME "authprocfs"
+#define RSBAC_AUTH_P_GROUP_LIST_NAME "authprocgr"
+#define RSBAC_AUTH_P_GROUP_EFF_LIST_NAME "authprocgreff"
+#define RSBAC_AUTH_P_GROUP_FS_LIST_NAME "authprocgrfs"
+
+#define RSBAC_AUTH_FD_FILENAME "authfd"
+#define RSBAC_AUTH_FD_EFF_FILENAME "authfde"
+#define RSBAC_AUTH_FD_FS_FILENAME "authfdf"
+#define RSBAC_AUTH_FD_GROUP_FILENAME "authfg"
+#define RSBAC_AUTH_FD_GROUP_EFF_FILENAME "authfge"
+#define RSBAC_AUTH_FD_GROUP_FS_FILENAME "authfgf"
+#define RSBAC_AUTH_FD_OLD_FILENAME "authfd."
+#define RSBAC_AUTH_FD_OLD_EFF_FILENAME "authfde."
+#define RSBAC_AUTH_FD_OLD_FS_FILENAME "authfdf."
+#define RSBAC_AUTH_FD_OLD_GROUP_FILENAME "authfg."
+#define RSBAC_AUTH_FD_OLD_GROUP_EFF_FILENAME "authfge."
+#define RSBAC_AUTH_FD_OLD_GROUP_FS_FILENAME "authfgf."
+#define RSBAC_AUTH_NR_CAP_FD_LIST_HASH_BITS 2
+#define RSBAC_AUTH_NR_CAP_EFF_FD_LIST_HASH_BITS 1
+#define RSBAC_AUTH_NR_CAP_FS_FD_LIST_HASH_BITS 1
+#define RSBAC_AUTH_NR_CAP_GROUP_FD_LIST_HASH_BITS 2
+#define RSBAC_AUTH_NR_CAP_GROUP_EFF_FD_LIST_HASH_BITS 1
+#define RSBAC_AUTH_NR_CAP_GROUP_FS_FD_LIST_HASH_BITS 1
+
+#define RSBAC_AUTH_FD_LIST_VERSION 2
+#define RSBAC_AUTH_FD_EFF_LIST_VERSION 2
+#define RSBAC_AUTH_FD_FS_LIST_VERSION 2
+#define RSBAC_AUTH_FD_GROUP_LIST_VERSION 2
+#define RSBAC_AUTH_FD_GROUP_EFF_LIST_VERSION 2
+#define RSBAC_AUTH_FD_GROUP_FS_LIST_VERSION 2
+#define RSBAC_AUTH_FD_OLD_LIST_VERSION 1
+#define RSBAC_AUTH_FD_EFF_OLD_LIST_VERSION 1
+#define RSBAC_AUTH_FD_FS_OLD_LIST_VERSION 1
+#define RSBAC_AUTH_FD_GROUP_OLD_LIST_VERSION 1
+#define RSBAC_AUTH_FD_GROUP_EFF_OLD_LIST_VERSION 1
+#define RSBAC_AUTH_FD_GROUP_FS_OLD_LIST_VERSION 1
+
+/* The list of devices is also a double linked list, so we define list    */
+/* items and a list head.                                                 */
+
+struct rsbac_auth_device_list_item_t {
+	kdev_t id;		/* set to 0 before deletion */
+	u_int mount_count;
+	rsbac_list_handle_t handle;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	rsbac_list_handle_t eff_handle;
+	rsbac_list_handle_t fs_handle;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	rsbac_list_handle_t
+	    group_handle;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	rsbac_list_handle_t
+	    group_eff_handle;
+	rsbac_list_handle_t
+	    group_fs_handle;
+#endif
+#endif
+	struct rsbac_auth_device_list_item_t *prev;
+	struct rsbac_auth_device_list_item_t *next;
+};
+
+/* To provide consistency we use spinlocks for all list accesses. The     */
+/* 'curr' entry is used to avoid repeated lookups for the same item.       */
+
+struct rsbac_auth_device_list_head_t {
+	struct rsbac_auth_device_list_item_t *head;
+	struct rsbac_auth_device_list_item_t *tail;
+	struct rsbac_auth_device_list_item_t *curr;
+	u_int count;
+};
+
+#endif
diff --git a/include/rsbac/cap_getname.h b/include/rsbac/cap_getname.h
new file mode 100644
index 0000000..e5024a4
--- /dev/null
+++ b/include/rsbac/cap_getname.h
@@ -0,0 +1,14 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 1999-2005:        */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for CAP module */
+/* Last modified: 28/Jan/2005       */
+/********************************** */
+
+#ifndef __RSBAC_CAP_GETNAME_H
+#define __RSBAC_CAP_GETNAME_H
+
+void rsbac_cap_log_missing_cap(int cap);
+
+#endif
diff --git a/include/rsbac/daz.h b/include/rsbac/daz.h
new file mode 100644
index 0000000..9da0112
--- /dev/null
+++ b/include/rsbac/daz.h
@@ -0,0 +1,27 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2005: Amon Ott */
+/* API:                               */
+/* Functions for Access               */
+/* Control Information / DAZ          */
+/* Last modified: 18/Jan/2005         */
+/************************************ */
+
+#ifndef __RSBAC_DAZ_H
+#define __RSBAC_DAZ_H
+
+#include <rsbac/types.h>
+
+/* Get ttl for new cache items in seconds */
+/* This function returns 0, if no cache is available, and the ttl value
+   otherwise */
+rsbac_time_t rsbac_daz_get_ttl(void);
+
+/* Set ttl for new cache items in seconds */
+/* ttl must be positive, values bigger than 10 years in seconds
+   (RSBAC_LIST_MAX_AGE_LIMIT in lists.h) are reduced to this limit */
+void rsbac_daz_set_ttl(rsbac_time_t ttl);
+
+/* Flush DAZuko cache lists */
+int rsbac_daz_flush_cache(void);
+#endif
diff --git a/include/rsbac/debug.h b/include/rsbac/debug.h
new file mode 100644
index 0000000..dff03cb
--- /dev/null
+++ b/include/rsbac/debug.h
@@ -0,0 +1,299 @@
+/******************************* */
+/* Rule Set Based Access Control */
+/* Author and (c) 1999-2016:     */
+/*   Amon Ott <ao@rsbac.org>     */
+/* debug definitions             */
+/* Last modified: 27/Mar/2016    */
+/******************************* */
+
+#ifndef __RSBAC_DEBUG_H
+#define __RSBAC_DEBUG_H
+
+#include <linux/init.h>
+//#include <rsbac/types.h>
+
+#define set_rsbac_softmode 1
+#define set_rsbac_softmode_once 2
+#define set_rsbac_softmode_never 4
+#define set_rsbac_freeze 8
+#define set_rsbac_um_no_excl 16
+#define set_rsbac_auth_learn 32
+#define set_rsbac_acl_learn_fd 64
+#define set_rsbac_cap_log_missing 128
+#define set_rsbac_jail_log_missing 256
+#define set_rsbac_dac_disable 512
+#define set_rsbac_no_delay_init 1024
+#define set_rsbac_no_defaults 2048
+#define set_rsbac_nosyslog 4096
+#define set_rsbac_cap_process_hiding 8192
+#define set_rsbac_cap_learn 16384
+#define set_rsbac_rc_learn 32768
+
+extern unsigned long int rsbac_flags;
+extern void rsbac_flags_set(unsigned long int);
+
+extern int rsbac_debug_no_write;
+
+#ifdef CONFIG_RSBAC_DEBUG
+extern int rsbac_debug_ds;
+extern int rsbac_debug_write;
+extern int rsbac_debug_stack;
+extern int rsbac_debug_lists;
+extern int rsbac_debug_aef;
+#endif
+
+extern int rsbac_debug_adf_default;
+extern rsbac_log_entry_t  rsbac_log_levels[R_NONE+1];
+
+#define RSBAC_LOG_LEVELS_NAME "log_levels"
+#define RSBAC_LOG_LEVEL_LIST_NAME "ll"
+#define RSBAC_LOG_LEVEL_VERSION 4
+#define RSBAC_LOG_LEVEL_OLD_VERSION 3
+#define RSBAC_LOG_LEVEL_OLD_OLD_VERSION 2
+#define RSBAC_LOG_LEVEL_KEY 13123231
+
+
+extern int rsbac_no_defaults;
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern void rsbac_init_debug(void);
+#else
+extern void rsbac_init_debug(void) __init;
+#endif
+
+extern rsbac_boolean_t rsbac_parse_koptions(char *);
+
+#define RSBAC_WAKEUP_KEY 'w'
+#define RSBAC_WAKEUP_UKEY 'W'
+
+#ifdef CONFIG_RSBAC_SOFTMODE
+#define RSBAC_SOFTMODE_KEY 'x'
+#define RSBAC_SOFTMODE_UKEY 'X'
+extern int rsbac_softmode;
+extern int rsbac_softmode_prohibit;
+static inline int rsbac_in_softmode(void)
+  {
+    return rsbac_softmode;
+  }
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+extern int  rsbac_ind_softmode[SW_NONE];
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_FREEZE)
+extern int rsbac_freeze;
+#endif
+
+extern int rsbac_list_recover;
+extern int rsbac_list_noread;
+extern u_int rsbac_list_auto_rehash_trigger;
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+extern rsbac_time_t rsbac_fd_cache_ttl;
+extern u_int rsbac_fd_cache_disable;
+extern u_int rsbac_fd_cache_fuse;
+extern u_int rsbac_fd_cache_ceph;
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+extern rsbac_time_t rsbac_um_name_cache_ttl;
+extern u_int rsbac_um_name_cache_disable;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+extern rsbac_time_t rsbac_list_check_interval;
+#endif
+
+#if defined(CONFIG_RSBAC_CAP_PROC_HIDE)
+extern int rsbac_cap_process_hiding;
+#endif
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+extern int rsbac_cap_log_missing;
+#endif
+#ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+extern int rsbac_jail_log_missing;
+#endif
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+extern int rsbac_dac_disable;
+extern int rsbac_dac_is_disabled(void);
+#endif
+
+#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+extern int rsbac_nosyslog;
+#endif
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern int rsbac_no_delay_init;
+extern kdev_t rsbac_delayed_root;
+extern char rsbac_delayed_root_str[];
+#endif
+
+/* rsbac_printk(): You must always prepend the loglevel. As sequence numbers
+ * are per rsbac_printk() message, it is strongly recommended to output single
+ * full lines only.
+ * Example:
+ * rsbac_printk(KERN_DEBUG "Test value: %u\n", testval);
+ */
+extern int rsbac_printk(const char *, ...);
+
+#ifdef CONFIG_RSBAC_DEBUG
+#define rsbac_pr_debug(type, fmt, arg...) \
+	do { if (rsbac_debug_##type) \
+		rsbac_printk(KERN_DEBUG "%s(): " fmt, __FUNCTION__, ##arg); \
+	} while (0)
+#else
+#define rsbac_pr_debug(type, fmt, arg...) do { } while (0)
+#endif
+
+#define rsbac_pr_get_error(attr) \
+	do { rsbac_ds_get_error (__FUNCTION__, attr); \
+	} while (0)
+#define rsbac_pr_set_error(attr) \
+	do { rsbac_ds_set_error (__FUNCTION__, attr); \
+	} while (0)
+#define rsbac_pr_get_error_num(attr, num) \
+	do { rsbac_ds_get_error_num (__FUNCTION__, attr, num); \
+	} while (0)
+#define rsbac_pr_set_error_num(attr, num) \
+	do { rsbac_ds_set_error_num (__FUNCTION__, attr, num); \
+	} while (0)
+
+#define rsbac_rc_pr_get_error(item) \
+	do { rsbac_rc_ds_get_error (__FUNCTION__, item); \
+	} while (0)
+#define rsbac_rc_pr_set_error(item) \
+	do { rsbac_rc_ds_set_error (__FUNCTION__, item); \
+	} while (0)
+
+#define RSBAC_LOG_MAXLINE 2020
+
+#if defined(CONFIG_RSBAC_RMSG)
+extern int rsbac_log(int, char *, int);
+
+#define RSBAC_LOG_MAXREADBUF (rsbac_min(8192,RSBAC_MAX_KMALLOC))
+
+struct rsbac_log_list_item_t {
+	struct rsbac_log_list_item_t *next;
+	u16 size;
+	char buffer[0];
+};
+
+struct rsbac_log_list_head_t {
+	struct rsbac_log_list_item_t *head;
+	struct rsbac_log_list_item_t *tail;
+	u_int count;
+	u_long lost;
+};
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+extern rsbac_pid_t rsbaclogd_pid;
+#endif
+#endif
+
+#ifdef CONFIG_RSBAC_NET
+extern int rsbac_debug_ds_net;
+extern int rsbac_debug_aef_net;
+extern int rsbac_debug_adf_net;
+#endif
+
+extern void wakeup_rsbacd(u_long dummy);
+
+/* switch log level for request */
+void  rsbac_adf_log_switch(rsbac_adf_request_int_t request,
+                           enum rsbac_target_t target,
+                           rsbac_enum_t value);
+
+int rsbac_get_adf_log(rsbac_adf_request_int_t request,
+                      enum rsbac_target_t target,
+                      u_int * value_p);
+
+#ifdef CONFIG_RSBAC_DEBUG
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+extern int rsbac_debug_auto;
+#endif /* CONFIG_RSBAC_AUTO_WRITE > 0 */
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+extern int rsbac_debug_fdcache;
+#endif
+
+#if defined(CONFIG_RSBAC_MAC)
+extern int rsbac_debug_ds_mac;
+extern int rsbac_debug_aef_mac;
+extern int rsbac_debug_adf_mac;
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+extern int rsbac_debug_adf_daz;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+extern int rsbac_debug_ds_rc;
+extern int rsbac_debug_aef_rc;
+extern int rsbac_debug_adf_rc;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+extern int rsbac_debug_ds_auth;
+extern int rsbac_debug_aef_auth;
+extern int rsbac_debug_adf_auth;
+#endif
+
+#if defined(CONFIG_RSBAC_REG)
+extern int rsbac_debug_reg;
+#endif
+
+#if defined(CONFIG_RSBAC_ACL)
+extern int rsbac_debug_ds_acl;
+extern int rsbac_debug_aef_acl;
+extern int rsbac_debug_adf_acl;
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+extern int rsbac_debug_aef_jail;
+extern int rsbac_debug_adf_jail;
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+extern int rsbac_debug_adf_pax;
+#endif
+
+#if defined(CONFIG_RSBAC_UM)
+extern int rsbac_debug_ds_um;
+extern int rsbac_debug_aef_um;
+extern int rsbac_debug_adf_um;
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+extern int rsbac_debug_adf_udf;
+#endif
+
+#endif /* DEBUG */
+
+#if defined(CONFIG_RSBAC_UM_EXCL)
+extern int rsbac_um_no_excl;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH) || defined(CONFIG_RSBAC_AUTH_MAINT)
+extern int rsbac_auth_enable_login;
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+extern int rsbac_auth_learn;
+#define RSBAC_AUTH_LEARN_TA_NAME "AUTH-learn"
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+extern int rsbac_rc_learn;
+#define RSBAC_RC_LEARN_TA_NAME "RC-learn"
+#endif
+
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+extern int rsbac_cap_learn;
+#define RSBAC_CAP_LEARN_TA_NAME "CAP-learn"
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_LEARN)
+extern int rsbac_acl_learn_fd;
+#define RSBAC_ACL_LEARN_TA_NAME "ACL-FD-learn"
+#endif
+
+#endif
diff --git a/include/rsbac/error.h b/include/rsbac/error.h
new file mode 100644
index 0000000..33fa1da
--- /dev/null
+++ b/include/rsbac/error.h
@@ -0,0 +1,66 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2008: Amon Ott  */
+/* Helper functions for all parts      */
+/* Last modified: 03/Mar/2008          */
+/************************************* */
+
+#ifndef __RSBAC_ERROR_H
+#define __RSBAC_ERROR_H
+
+#ifdef __KERNEL__
+#include <linux/errno.h>
+#else
+#include <errno.h>
+#endif
+
+/* Error values             */
+
+#define RSBAC_EPERM               1001
+#define RSBAC_EACCESS             1002
+#define RSBAC_EREADFAILED         1003
+#define RSBAC_EWRITEFAILED        1004
+#define RSBAC_EINVALIDPOINTER     1005
+#define RSBAC_ENOROOTDIR          1006
+#define RSBAC_EPATHTOOLONG        1007
+#define RSBAC_ENOROOTDEV          1008
+#define RSBAC_ENOTFOUND           1009
+#define RSBAC_ENOTINITIALIZED     1010
+#define RSBAC_EREINIT             1011
+#define RSBAC_ECOULDNOTADDDEVICE  1012
+#define RSBAC_ECOULDNOTADDITEM    1013
+#define RSBAC_ECOULDNOTCREATEPATH 1014
+#define RSBAC_EINVALIDATTR        1015
+#define RSBAC_EINVALIDDEV         1016
+#define RSBAC_EINVALIDTARGET      1017
+#define RSBAC_EINVALIDVALUE       1018
+#define RSBAC_EEXISTS             1019
+#define RSBAC_EINTERNONLY         1020
+#define RSBAC_EINVALIDREQUEST     1021
+#define RSBAC_ENOTWRITABLE        1022
+#define RSBAC_EMALWAREDETECTED    1023
+#define RSBAC_ENOMEM              1024
+#define RSBAC_EDECISIONMISMATCH   1025
+#define RSBAC_EINVALIDVERSION     1026
+#define RSBAC_EINVALIDMODULE      1027
+#define RSBAC_EEXPIRED            1028
+#define RSBAC_EMUSTCHANGE         1029
+#define RSBAC_EBUSY               1030
+#define RSBAC_EINVALIDTRANSACTION 1031
+#define RSBAC_EWEAKPASSWORD       1032
+#define RSBAC_EINVALIDLIST        1033
+#define RSBAC_EFROMINTERRUPT      1034
+
+#define RSBAC_EMAX 1034
+
+#define RSBAC_ERROR( res ) ((res <= -RSBAC_EPERM) && (res >= -RSBAC_EMAX))
+
+#ifndef __KERNEL__
+/* exit on error */
+void error_exit(int error);
+
+/* show error */
+void show_error(int error);
+#endif
+
+#endif
diff --git a/include/rsbac/fs.h b/include/rsbac/fs.h
new file mode 100644
index 0000000..9ed52a3
--- /dev/null
+++ b/include/rsbac/fs.h
@@ -0,0 +1,58 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2015: Amon Ott  */
+/* File system                         */
+/* helper functions for all parts      */
+/* Last modified: 07/Jul/2015          */
+/************************************* */
+
+#ifndef __RSBAC_FS_H
+#define __RSBAC_FS_H
+
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <linux/root_dev.h>
+#include <linux/sched.h>
+
+/* original lookup_dentry function without rsbac patch for adf call */
+
+struct dentry * rsbac_lookup_hash(struct qstr *name, struct dentry * base);
+struct dentry * rsbac_lookup_one_len(const char * name, struct dentry * base, int len);
+
+#ifndef SOCKFS_MAGIC
+#define SOCKFS_MAGIC 0x534F434B
+#endif
+
+#ifndef SYSFS_MAGIC
+#define SYSFS_MAGIC 0x62656572
+#endif
+
+#ifndef OCFS2_SUPER_MAGIC
+#define OCFS2_SUPER_MAGIC 0x7461636f
+#endif
+
+struct vfsmount * rsbac_get_vfsmount(kdev_t kdev);
+
+extern void __fput(struct file *);
+
+#ifndef SHM_FS_MAGIC
+#define SHM_FS_MAGIC 0x02011994
+#endif
+
+static inline int init_private_file(struct file *filp, struct dentry *dentry, int mode)
+{
+	memset(filp, 0, sizeof(*filp));
+	filp->f_mode   = mode;
+	atomic_long_set(&filp->f_count, 1);
+	filp->f_path.dentry = dentry;
+	filp->f_cred = current_cred();
+	filp->f_op     = dentry->d_inode->i_fop;
+	filp->f_mapping     = dentry->d_inode->i_mapping;
+	file_ra_state_init(&filp->f_ra, filp->f_mapping);
+	if (filp->f_op->open)
+		return filp->f_op->open(dentry->d_inode, filp);
+	else
+		return 0;
+}
+
+#endif
diff --git a/include/rsbac/gen_lists.h b/include/rsbac/gen_lists.h
new file mode 100644
index 0000000..97f7235
--- /dev/null
+++ b/include/rsbac/gen_lists.h
@@ -0,0 +1,286 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/* Generic lists - internal structures               */
+/* Last modified: 07/Jan/2016                        */
+/*************************************************** */
+
+#ifndef __RSBAC_GEN_LISTS_H
+#define __RSBAC_GEN_LISTS_H
+
+#include <linux/init.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/lists.h>
+#include <rsbac/repl_lists.h>
+
+/* Sanity limit of list size, regardless of RSBAC_LIST_MAX_NR_ITEMS in lists.h */
+#define RSBAC_LIST_MAX_NR_ITEMS_LIMIT 65000
+
+#define RSBAC_LIST_DISK_VERSION 10003
+#define RSBAC_LIST_DISK_OLD_VERSION 10002
+#define RSBAC_LIST_NONAME "(no name)"
+#define RSBAC_LIST_PROC_NAME "gen_lists"
+#define RSBAC_LIST_COUNTS_PROC_NAME "gen_lists_counts"
+
+#define RSBAC_LIST_TA_KEY 0xface99
+
+#define RSBAC_LIST_MAX_OLD_HASH 32
+#define RSBAC_LIST_LOL_MAX_OLD_HASH 16
+
+/* Rehashing interval in s - rehashing is triggered by rsbacd, so might happen
+ * less frequently, if rsbacd wakes up later.
+ */
+#define RSBAC_LIST_REHASH_INTERVAL 60
+
+/* Prototypes */
+
+/* Init */
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_list_init(void);
+#else
+int __init rsbac_list_init(void);
+#endif
+
+/* Status checking */
+int rsbac_check_lists(const int correct);
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+int rsbac_write_lists(void);
+#endif
+
+/* Data Structures */
+
+/* All items will be organized in double linked lists
+ * However, we do not know the descriptor or item sizes, so we will access them
+   with offsets later and only define the list links here.
+ */
+
+struct rsbac_list_item_t {
+	struct rsbac_list_item_t *prev;
+	struct rsbac_list_item_t *next;
+	rsbac_time_t max_age;
+};
+
+/* lists of lists ds */
+struct rsbac_list_lol_item_t {
+	struct rsbac_list_lol_item_t *prev;
+	struct rsbac_list_lol_item_t *next;
+	struct rsbac_list_item_t *head;
+	struct rsbac_list_item_t *tail;
+	struct rsbac_list_item_t *curr;
+	u_long count;
+	rsbac_time_t max_age;
+};
+
+typedef __u32 rsbac_list_count_t;
+
+struct rsbac_list_hashed_t {
+	struct rsbac_list_item_t *head;
+	struct rsbac_list_item_t *tail;
+	struct rsbac_list_item_t *curr;
+	rsbac_list_count_t count;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	rsbac_ta_number_t ta_copied;
+	struct rsbac_list_item_t *ta_head;
+	struct rsbac_list_item_t *ta_tail;
+	struct rsbac_list_item_t *ta_curr;
+	rsbac_list_count_t ta_count;
+#endif
+};
+
+struct rsbac_list_lol_hashed_t {
+	struct rsbac_list_lol_item_t *head;
+	struct rsbac_list_lol_item_t *tail;
+	struct rsbac_list_lol_item_t *curr;
+	rsbac_list_count_t count;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	rsbac_ta_number_t ta_copied;
+	struct rsbac_list_lol_item_t *ta_head;
+	struct rsbac_list_lol_item_t *ta_tail;
+	struct rsbac_list_lol_item_t *ta_curr;
+	rsbac_list_count_t ta_count;
+#endif
+};
+
+/* Since all registrations will be organized in double linked lists, we must
+ * have list items and a list head.
+ * The pointer to this item will also be used as list handle. */
+
+struct rsbac_list_reg_item_t {
+	struct rsbac_list_info_t info;
+	u_int flags;
+	rsbac_boolean_t dirty;
+	rsbac_boolean_t no_write;
+	__u8 hash_bits;
+	__u16 max_items_per_hash;
+	rsbac_list_hash_function_t * hash_function;
+	rsbac_list_compare_function_t *compare;
+	rsbac_list_get_conv_t *get_conv;
+	void *def_data;
+	char name[RSBAC_LIST_MAX_FILENAME + 1];
+	kdev_t device;
+	spinlock_t lock;
+	struct rsbac_list_rcu_free_head_t * rcu_free;
+	struct kmem_cache * slab;
+	char * slabname;
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+	struct proc_dir_entry *proc_entry_p;
+#endif
+	struct rsbac_nanotime_t lastchange;
+	char old_name_base[RSBAC_LIST_MAX_FILENAME + 1];
+#ifdef CONFIG_RSBAC_LIST_STATS
+	__u64 read_count;
+	__u64 write_count;
+#endif
+	struct rsbac_list_reg_item_t *prev;
+	struct rsbac_list_reg_item_t *next;
+	struct rsbac_list_reg_item_t *self;
+	/* The hashed list heads are allocated dynamically! */
+	struct rsbac_list_hashed_t * hashed;
+};
+
+struct rsbac_list_lol_reg_item_t {
+	struct rsbac_list_lol_info_t info;
+	u_int flags;
+	rsbac_boolean_t dirty;
+	rsbac_boolean_t no_write;
+	__u8 hash_bits;
+	__u16 max_items_per_hash;
+	__u16 max_subitems;
+	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;
+	void *def_data;
+	void *def_subdata;
+	char name[RSBAC_LIST_MAX_FILENAME + 1];
+	kdev_t device;
+	spinlock_t lock;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_free;
+	rsbac_list_hash_function_t * hash_function;
+	struct kmem_cache * slab;
+	char * slabname;
+	struct kmem_cache * subslab;
+	char * subslabname;
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+	struct proc_dir_entry *proc_entry_p;
+#endif
+	struct rsbac_nanotime_t lastchange;
+	char old_name_base[RSBAC_LIST_MAX_FILENAME + 1];
+#ifdef CONFIG_RSBAC_LIST_STATS
+	__u64 read_count;
+	__u64 write_count;
+#endif
+	struct rsbac_list_lol_reg_item_t *prev;
+	struct rsbac_list_lol_reg_item_t *next;
+	struct rsbac_list_lol_reg_item_t *self;
+	/* The hashed list heads are allocated dynamically! */
+	struct rsbac_list_lol_hashed_t * hashed;
+};
+
+/* To provide consistency we use spinlocks for all list accesses. The
+   'curr' entry is used to avoid repeated lookups for the same item. */
+
+struct rsbac_list_reg_head_t {
+	struct rsbac_list_reg_item_t *head;
+	struct rsbac_list_reg_item_t *tail;
+	struct rsbac_list_reg_item_t *curr;
+	spinlock_t lock;
+	struct lock_class_key lock_class;
+	u_int count;
+};
+
+struct rsbac_list_lol_reg_head_t {
+	struct rsbac_list_lol_reg_item_t *head;
+	struct rsbac_list_lol_reg_item_t *tail;
+	struct rsbac_list_lol_reg_item_t *curr;
+	spinlock_t lock;
+	struct lock_class_key lock_class;
+	u_int count;
+};
+
+/* Internal helper list of filled write buffers */
+
+struct rsbac_list_buffer_t {
+	struct rsbac_list_buffer_t * next;
+	u_int len;
+	char data[0];
+};
+
+#define RSBAC_LIST_BUFFER_SIZE 8192
+#define RSBAC_LIST_BUFFER_DATA_SIZE (RSBAC_LIST_BUFFER_SIZE - sizeof(struct rsbac_list_buffer_t))
+
+struct rsbac_list_write_item_t {
+	struct rsbac_list_write_item_t *prev;
+	struct rsbac_list_write_item_t *next;
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_buffer_t *buffer;
+	char name[RSBAC_LIST_MAX_FILENAME + 1];
+	kdev_t device;
+};
+
+struct rsbac_list_write_head_t {
+	struct rsbac_list_write_item_t *head;
+	struct rsbac_list_write_item_t *tail;
+	u_int count;
+};
+
+struct rsbac_list_lol_write_item_t {
+	struct rsbac_list_lol_write_item_t *prev;
+	struct rsbac_list_lol_write_item_t *next;
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_buffer_t *buffer;
+	char name[RSBAC_LIST_MAX_FILENAME + 1];
+	kdev_t device;
+};
+
+struct rsbac_list_lol_write_head_t {
+	struct rsbac_list_lol_write_item_t *head;
+	struct rsbac_list_lol_write_item_t *tail;
+	u_int count;
+};
+
+
+/* Data structs for file timeout book keeping list filelist */
+struct rsbac_list_filelist_desc_t {
+	char filename[RSBAC_LIST_MAX_FILENAME + 1];
+};
+
+struct rsbac_list_filelist_data_t {
+	rsbac_time_t timestamp;
+	rsbac_time_t max_age;
+};
+
+struct rsbac_list_ta_data_t {
+	rsbac_time_t start;
+	rsbac_time_t timeout;
+	rsbac_uid_t commit_uid;
+	char name[RSBAC_LIST_TA_MAX_NAMELEN];
+	char password[RSBAC_LIST_TA_MAX_PASSLEN];
+};
+
+struct rsbac_list_rcu_free_head_t {
+	/* rcu _must_ stay first */
+	struct rcu_head rcu;
+	struct kmem_cache * slab;
+	struct rsbac_list_rcu_free_item_t * head;
+	struct rsbac_list_item_t * item_chain;
+};
+
+struct rsbac_list_rcu_free_head_lol_t {
+	/* rcu _must_ stay first */
+	struct rcu_head rcu;
+	struct kmem_cache * slab;
+	struct kmem_cache * subslab;
+	struct rsbac_list_rcu_free_item_t * head;
+	struct rsbac_list_rcu_free_item_t * subhead;
+	struct rsbac_list_lol_item_t * lol_item_chain;
+	struct rsbac_list_item_t * lol_item_subchain;
+};
+
+struct rsbac_list_rcu_free_item_t {
+	struct rsbac_list_rcu_free_item_t * next;
+	void * mem;
+};
+
+#endif
diff --git a/include/rsbac/getname.h b/include/rsbac/getname.h
new file mode 100644
index 0000000..1a1d577
--- /dev/null
+++ b/include/rsbac/getname.h
@@ -0,0 +1,101 @@
+/******************************** */
+/* Rule Set Based Access Control  */
+/* Author and (c) 1999-2007:      */
+/* Amon Ott <ao@rsbac.org>        */
+/* Getname functions for all parts*/
+/* Last modified: 17/Sep/2007     */
+/******************************** */
+
+#ifndef __RSBAC_GETNAME_H
+#define __RSBAC_GETNAME_H
+
+#include <rsbac/types.h>
+#ifdef CONFIG_RSBAC_XSTATS
+#include <rsbac/syscalls.h>
+#endif
+
+#if defined(__KERNEL__) && defined(CONFIG_RSBAC_LOG_FULL_PATH)
+#include <linux/fs.h>
+#if (CONFIG_RSBAC_MAX_PATH_LEN > 2000)
+#undef CONFIG_RSBAC_MAX_PATH_LEN
+#define CONFIG_RSBAC_MAX_PATH_LEN 2000
+#endif
+#if (CONFIG_RSBAC_MAX_PATH_LEN < RSBAC_MAXNAMELEN)
+#undef CONFIG_RSBAC_MAX_PATH_LEN
+#define CONFIG_RSBAC_MAX_PATH_LEN RSBAC_MAXNAMELEN
+#endif
+#endif
+
+extern char * get_request_name(char * , enum rsbac_adf_request_t);
+
+extern enum rsbac_adf_request_t get_request_nr(const char *);
+
+extern char * get_result_name(char * , enum rsbac_adf_req_ret_t);
+
+extern enum rsbac_adf_req_ret_t get_result_nr(const char *);
+
+extern enum rsbac_switch_target_t get_attr_module(enum rsbac_attribute_t attr);
+
+extern char * get_attribute_name(char * , enum rsbac_attribute_t);
+
+extern char * get_attribute_value_name(     char *            attr_val_name,
+                                       enum rsbac_attribute_t attr,
+                                       union rsbac_attribute_value_t * attr_val_p);
+
+extern enum rsbac_attribute_t get_attribute_nr(const char *);
+
+extern char * get_target_name(char * , enum  rsbac_target_t,
+                              char * , union rsbac_target_id_t);
+
+extern char * get_target_name_only(char * target_type_name,
+                                   enum   rsbac_target_t target);
+
+extern enum rsbac_target_t get_target_nr(const char *);
+
+extern char * get_ipc_target_name(char *,
+                                  enum rsbac_ipc_type_t);
+
+extern enum rsbac_ipc_type_t get_ipc_target_nr(const char *);
+
+extern char * get_scd_type_name(char *,
+                                enum rsbac_scd_type_t);
+
+extern enum rsbac_scd_type_t get_scd_type_nr(const char *);
+
+extern char * get_switch_target_name(char *,
+                                     enum rsbac_switch_target_t);
+
+extern enum rsbac_switch_target_t get_switch_target_nr(const char *);
+
+extern char * get_error_name(char *,
+                             int);
+
+#ifndef __KERNEL__
+extern char * get_attribute_param(char * , enum rsbac_attribute_t);
+#endif
+
+extern char * get_log_level_name(char *,
+                                  enum rsbac_log_level_t);
+
+extern enum rsbac_log_level_t get_log_level_nr(const char *);
+
+#ifdef __KERNEL__
+int rsbac_lookup_full_path(struct dentry * dentry_p, char path[], int maxlen, int pseudonymize);
+
+static inline int rsbac_get_full_path(struct dentry * dentry_p, char path[], int maxlen)
+{
+  return rsbac_lookup_full_path(dentry_p, path, maxlen, 1);
+}
+#endif
+
+char * get_cap_name(char * name,
+                    u_int value);
+
+int get_cap_nr(const char * name);
+
+#ifdef CONFIG_RSBAC_XSTATS
+char *get_syscall_name(char *syscall_name,
+                       enum rsbac_syscall_t syscall);
+#endif
+
+#endif
diff --git a/include/rsbac/helpers.h b/include/rsbac/helpers.h
new file mode 100644
index 0000000..04273c6
--- /dev/null
+++ b/include/rsbac/helpers.h
@@ -0,0 +1,157 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2013: Amon Ott  */
+/* Helper functions for all parts      */
+/* Last modified:  14/Jan/2013         */
+/************************************* */
+
+#ifndef __RSBAC_HELPER_H
+#define __RSBAC_HELPER_H
+
+#include <linux/types.h>
+#include <rsbac/types.h>
+#ifdef __KERNEL__
+#include <rsbac/rkmem.h>
+#endif
+
+char * inttostr(char[], int);
+
+char * ulongtostr(char[], u_long);
+
+/* convert u_long_long to binary string representation for MAC module */
+char * u64tostrmac(char[], __u64);
+
+char * u32tostrcap(char * str, __u32 i);
+__u32 strtou32cap(char * str, __u32 * i_p);
+
+int rsbac_get_vset_num(char * sourcename, rsbac_um_set_t * vset_p);
+
+#ifndef __KERNEL__
+void locale_init(void);
+
+int rsbac_lib_version(void);
+int rsbac_u32_compare(__u32 * a, __u32 * b);
+int rsbac_u32_void_compare(const void *a, const void *b);
+
+int rsbac_user_compare(const void * a, const void * b);
+int rsbac_group_compare(const void * a, const void * b);
+int rsbac_nettemp_id_compare(const void * a, const void * b);
+
+int rsbac_dev_compare(const void * desc1,
+                      const void * desc2);
+
+char * get_user_name(rsbac_uid_t user, char * name);
+
+char * get_group_name(rsbac_gid_t group, char * name);
+
+int rsbac_get_uid_name(rsbac_uid_t * uid, char * name, char * sourcename);
+
+int rsbac_get_fullname(char * fullname, rsbac_uid_t uid);
+
+static inline int rsbac_get_uid(rsbac_uid_t * uid, char * sourcename)
+  {
+    return rsbac_get_uid_name(uid, NULL, sourcename);
+  }
+
+int rsbac_get_gid_name(rsbac_gid_t * gid, char * name, char * sourcename);
+
+static inline int rsbac_get_gid(rsbac_gid_t * gid, char * sourcename)
+  {
+    return rsbac_get_gid_name(gid, NULL, sourcename);
+  }
+
+/* covert u_long_long to binary string representation for log array */
+char * u64tostrlog(char[], __u64);
+/* and back */
+__u64 strtou64log(char[], __u64 *);
+
+/* convert u_long_long to binary string representation for MAC module */
+/* and back */
+__u64 strtou64mac(char[], __u64 *);
+
+/* covert u_long_long to binary string representation for RC module */
+char * u64tostrrc(char[], __u64);
+/* and back */
+__u64 strtou64rc(char[], __u64 *);
+
+/* covert u_long_long to binary string representation for RC module / rights */
+char * u64tostrrcr(char[], __u64);
+/* and back */
+__u64 strtou64rcr(char[], __u64 *);
+
+/* ACL back */
+__u64 strtou64acl(char[], __u64 *);
+
+char * devdesctostr(char * str, struct rsbac_dev_desc_t dev);
+
+int strtodevdesc(char * str, struct rsbac_dev_desc_t * dev_p);
+#endif
+
+/* covert u_long_long to binary string representation for ACL module */
+char * u64tostracl(char[], __u64);
+
+char * longtostr(char[], long);
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+rsbac_um_set_t rsbac_get_vset(void);
+#else
+static inline rsbac_um_set_t rsbac_get_vset(void)
+  {
+    return 0;
+  }
+#endif
+
+int rsbac_get_owner(rsbac_uid_t * user_p);
+
+static inline int rsbac_get_user(void * kern_p, void __user * user_p, int size)
+  {
+    if(kern_p && user_p && (size > 0))
+      {
+        return copy_from_user(kern_p, user_p, size);
+      }
+    return 0;
+  }
+
+
+static inline int rsbac_put_user(void * kern_p, void __user * user_p, int size)
+  {
+    if(kern_p && user_p && (size > 0))
+      {
+        return copy_to_user(user_p,kern_p,size);
+      }
+    return 0;
+  }
+
+static inline struct filename * rsbac_getname(const char __user * name)
+  {
+    return getname(name);
+  }
+
+static inline void rsbac_putname(struct filename * name)
+  {
+    putname(name);
+  }
+
+static inline int clear_user_buf(char * ubuf, int len)
+  {
+    return clear_user(ubuf,len);
+  }
+
+void rsbac_get_attr_error(char * , enum rsbac_adf_request_t);
+
+void rsbac_ds_get_error(const char * function, enum rsbac_attribute_t attr);
+void rsbac_ds_get_error_num(const char * function, enum rsbac_attribute_t attr, int err);
+void rsbac_ds_set_error(const char * function, enum rsbac_attribute_t attr);
+void rsbac_ds_set_error_num(const char * function, enum rsbac_attribute_t attr, int err);
+
+#ifdef CONFIG_RSBAC_RC
+void rsbac_rc_ds_get_error(const char * function, enum rsbac_rc_item_t item);
+void rsbac_rc_ds_set_error(const char * function, enum rsbac_rc_item_t item);
+#endif
+
+#endif /* KERNEL */
+
+#endif
diff --git a/include/rsbac/hooks.h b/include/rsbac/hooks.h
new file mode 100644
index 0000000..10cd794
--- /dev/null
+++ b/include/rsbac/hooks.h
@@ -0,0 +1,24 @@
+/******************************* */
+/* Rule Set Based Access Control */
+/* Author and (c) 1999-2006:     */
+/*   Amon Ott <ao@rsbac.org>     */
+/* Common include file set       */
+/* Last modified: 31/Mar/2006    */
+/******************************* */
+
+#ifndef __RSBAC_HOOKS_H
+#define __RSBAC_HOOKS_H
+
+#ifdef CONFIG_RSBAC
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/helpers.h>
+#include <rsbac/fs.h>
+#include <rsbac/debug.h>
+//#include <rsbac/aci_data_structures.h>
+//#include <rsbac/adf_main.h>
+#else
+#define rsbac_kthreads_init() do {} while(0)
+#endif
+
+#endif
diff --git a/include/rsbac/jail.h b/include/rsbac/jail.h
new file mode 100644
index 0000000..73d321b
--- /dev/null
+++ b/include/rsbac/jail.h
@@ -0,0 +1,16 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2007:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* Global definitions for JAIL module */
+/* Last modified: 29/Jan/2007         */
+/************************************ */
+
+#ifndef __RSBAC_JAIL_H
+#define __RSBAC_JAIL_H
+
+extern rsbac_jail_id_t rsbac_jail_syslog_jail_id;
+
+rsbac_boolean_t rsbac_jail_exists(rsbac_jail_id_t jail_id);
+
+#endif
diff --git a/include/rsbac/jail_getname.h b/include/rsbac/jail_getname.h
new file mode 100644
index 0000000..01a301f
--- /dev/null
+++ b/include/rsbac/jail_getname.h
@@ -0,0 +1,14 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 1999-2005:        */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for JAIL module */
+/* Last modified: 27/May/2005       */
+/********************************** */
+
+#ifndef __RSBAC_JAIL_GETNAME_H
+#define __RSBAC_JAIL_GETNAME_H
+
+void rsbac_jail_log_missing_cap(int cap);
+
+#endif
diff --git a/include/rsbac/lists.h b/include/rsbac/lists.h
new file mode 100644
index 0000000..72efd41
--- /dev/null
+++ b/include/rsbac/lists.h
@@ -0,0 +1,959 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/* Generic List Management                           */
+/* Last modified: 07/Jan/2016                        */
+/*************************************************** */
+
+/* Note: lol = list of lists, a two-level list structure */
+
+#ifndef __RSBAC_LISTS_H
+#define __RSBAC_LISTS_H
+
+#include <linux/init.h>
+#include <rsbac/rkmem.h>
+
+#define RSBAC_LIST_VERSION 3
+
+typedef void *rsbac_list_handle_t;
+typedef __u32 rsbac_list_key_t;
+
+/* Maximum length for list (file)names */
+#define RSBAC_LIST_MAX_FILENAME 15
+
+/* Limit for max_age_in_seconds: ca. 10 years */
+#define RSBAC_LIST_MAX_AGE_LIMIT (3600 * 24 * 366 * 10)
+
+/* Maximum desc_size + data_size: 8K - some space for metadata */
+#define RSBAC_LIST_MAX_ITEM_SIZE (8192 - 64)
+
+#define RSBAC_LIST_MIN_MAX_HASH_BITS 3
+/* This must never be > 31 or we badly break the hash functions
+ * and kmalloc
+ */
+#define RSBAC_LIST_MAX_MAX_HASH_BITS 18
+
+/* standard hash functions */
+u_int rsbac_list_hash_u32(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_fd(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_old_fd(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_pid(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_uid(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_gid(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_ipc(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_dev(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_nettemp(void * desc, __u8 hash_bits);
+u_int rsbac_list_hash_netobj(void * desc, __u8 hash_bits);
+
+/****************************/
+/* List Registration Flags: */
+
+/* Make persistent, i.e., save to and restore from disk */
+#define RSBAC_LIST_PERSIST 1
+
+/* Ignore old list contents (still checks key, if list exists on disk) */
+#define RSBAC_LIST_IGNORE_OLD 2
+
+/* Ignore old list contents, if version upconversion is not supported
+ * (no get_conv, or get_conv returned NULL) - without this flag, registration fails, if
+ * list cannot be converted.
+ */
+#define RSBAC_LIST_IGNORE_UNSUPP_VERSION 4
+
+/* Temporarily disallow writing list to disk, e.g. for upgrade tests */
+#define RSBAC_LIST_NO_WRITE 8
+
+/* Provide a binary backup file as /proc/rsbac-info/backup/filename */
+#define RSBAC_LIST_BACKUP 16
+
+/* Use provided default data, return it for unexisting items and
+   automatically create and cleanup items with default data as necessary.
+   (only items with 0 ttl (unlimited) get removed)
+   (lol items with default data only get removed, if they have no subitems) */
+#define RSBAC_LIST_DEF_DATA 32
+
+/* Use provided default subitem data, return it for unexisting subitems and
+   automatically create and cleanup subitems with default data as necessary.
+   (only subitems with 0 ttl (unlimited) get removed) */
+#define RSBAC_LIST_DEF_SUBDATA 64
+
+/* Replicate list to replication partners.
+   Must be enabled in config. */
+#define RSBAC_LIST_REPLICATE 128
+
+/* Allow automatic online resizing of the list hashing table.
+   Requires that the provided hash function uses the hash_bits parameter. */
+#define RSBAC_LIST_AUTO_HASH_RESIZE 256
+
+/* Disable limit of RSBAC_LIST_MAX_NR_ITEMS items per single list. */
+#define RSBAC_LIST_NO_MAX 512
+
+/* Disable warning if max_entries prevents adding of items */
+#define RSBAC_LIST_NO_MAX_WARN 1024
+
+/* Use own slab for this list */
+#define RSBAC_LIST_OWN_SLAB 2048
+
+/* Maximum number of items per single list, the total limit is at
+ * RSBAC_LIST_MAX_NR_ITEMS * (2^hash_bits).
+ * Limits can be disabled per list with RSBAC_LIST_NO_MAX flag and
+ * changed with rsbac_list_max_items() and rsbac_list_lol_max_items().
+ * In fact, size is still limited to the sanity value
+ * RSBAC_LIST_MAX_NR_ITEMS_LIMIT, defined in gen_lists.h.
+ */
+
+#define RSBAC_LIST_MAX_NR_ITEMS 10000
+#define RSBAC_LIST_MAX_NR_SUBITEMS 10000
+
+/****************************/
+/* Function prototypes */
+
+/* Function to compare two descriptors, returns 0, if equal, a negative value,
+ * if desc1 < desc2 and a positive value, if desc1 > desc2 (like memcmp).
+ * Used for lookup and list optimization.
+ * Note: Non-0 values are only used for list optimization and do not necessarily
+ * imply a real order of values.
+ */
+typedef int rsbac_list_compare_function_t(void *desc1, void *desc2);
+
+int rsbac_list_compare_u32(void * desc1, void * desc2);
+
+/* Function to compare two datas, returns 0, if equal, and another value,
+ * if not.
+ * Used for lookup by data.
+ * Note: list optimization is based on descriptors, so data lookup is always
+ * linear search from first to last element in list order.
+ */
+typedef int rsbac_list_data_compare_function_t(void *data1, void *data2);
+
+/* Function to compare two descs with a parameter, returns TRUE,
+ * if item is selected, and FALSE, if not.
+ * Used for selected lists of descriptors.
+ */
+typedef int rsbac_list_desc_selector_function_t(void *desc, void * param);
+
+/* conversion function to upconvert old on-disk descs and datas to actual version */
+/* must return 0 on success or error otherwise */
+/* Attention: if old or new data_size is 0, the respective data pointer is NULL! */
+typedef int rsbac_list_conv_function_t(void *old_desc,
+				       void *old_data,
+				       void *new_desc, void *new_data);
+
+/* callback function to return an upconvert function for on-disk-version, if versions differ */
+/* Note: Lists implementation does not assume anything about your version number apart
+   from being of type rsbac_version_t. Use it as you like. */
+typedef rsbac_list_conv_function_t *rsbac_list_get_conv_t(rsbac_version_t
+							  old_version);
+
+/* hash function to return a hash for the descriptor in the range 0 to (1 << hash_bits) - 1 */
+typedef u_int rsbac_list_hash_function_t(void * desc, __u8 hash_bits);
+
+/* get generic list registration version */
+rsbac_version_t rsbac_list_version(void);
+
+
+/* List info: This struct will be written to disk */
+/*
+ * list_version: a simple __u32 version number for the list. If old on-disk version is
+   different, conversion is tried (depending on flags and get_conv function)
+ * key: secret __u32 key, which must be the same as in on-disk version, if persistent
+ * desc_size: size of the descriptor (error is returned, if list exists and value differs)
+              internally reset to sizeof(__u32) for u32 call variants
+ * data_size: size of data (error is returned, if list exists and value differs)
+              set to 0 for sets without data
+ * subdesc_size: size of the descriptor of the sublist (error is returned, if list exists
+              and value differs), internally reset to sizeof(__u32) for u32 call variants
+ * subdata_size: size of sublist data (error is returned, if list exists and value differs)
+              set to 0 for sets without data
+ * max_age: seconds until unchanged list file (no add or remove) will be purged.
+   Maximum value is RSBAC_LIST_MAX_AGE_LIMIT (s.a.), use 0 for unlimited lifetime.
+   (purging not yet implemented - only reused without key, please cleanup by hand)
+ */
+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;
+};
+
+
+/* register a new list */
+/*
+ * If list with same name exists in memory, error -RSBAC_EEXISTS is returned.
+ * If list with same name and key exists on device, it is restored depending on
+   the flags.
+ * If list with same name, but different key exists on disk, access is denied
+   (error -EPERM).
+ *
+ * ds_version: for binary modules, must be RSBAC_LIST_VERSION. If version
+   differs, return error.
+ * handle_p: for all list accesses, an opaque handle is put into *handle_p.
+ * flags: see flag values
+ * compare: for lookup and list optimization, can be NULL, then
+   memcmp(desc1, desc2, desc_size) is used
+ * subcompare: for item lookup and optimization of sublist, can be NULL, then
+   memcmp(desc1, desc2, desc_size) is used
+ * get_conv: function to deliver conversion function for given version
+ * get_subconv: function to deliver sublist item conversion function for given
+   version
+ * def_data: default data value for flag RSBAC_LIST_DEF_DATA
+   (if NULL, flag is cleared)
+ * def_subdata: default subdata value for flag RSBAC_LIST_DEF_SUBDATA
+   (if NULL, flag is cleared)
+ * name: the on-disk name, should be distinct and max. 7 or 8.2 chars
+   (maxlen of RSBAC_LIST_MAX_FILENAME supported) (only used for statistics, if
+   non-persistent)
+ * device: the device to read list from or to save list to - use 0 for root dev
+   (ignored, if non-persistent)
+ * hash_bits: Number of bits of hashes for this list, minimum is 1,
+   maximum is rsbac_list_max_hash_bits,
+   which is derived from CONFIG_RSBAC_LIST_MAX_HASH_BITS and must not be more than 31
+   Number of hashes is 2^hash_bits.
+   If > maximum, it will be reduced to maximum automatically.
+ * hash_function: Hash function(desc,hash_bits), must always return a value
+   from 0 to 2^hash_bits - 1.
+ * old_base_name: If not NULL and persistent list with name cannot be read,
+   try to read all old_base_name<n> with n from 0 to 31.
+ */
+
+int rsbac_list_register_hashed(rsbac_version_t ds_version,
+			rsbac_list_handle_t * handle_p,
+			struct rsbac_list_info_t *info_p,
+			u_int flags,
+			rsbac_list_compare_function_t * compare,
+			rsbac_list_get_conv_t * get_conv,
+			void *def_data,
+			char *name, kdev_t device,
+			__u8 hash_bits,
+			rsbac_list_hash_function_t hash_function,
+			char * old_base_name);
+
+int rsbac_list_lol_register_hashed(rsbac_version_t ds_version,
+			rsbac_list_handle_t * handle_p,
+			struct rsbac_list_lol_info_t *info_p,
+			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,
+			void *def_data,
+			void *def_subdata,
+			char *name, kdev_t device,
+			__u8 hash_bits,
+			rsbac_list_hash_function_t hash_function,
+			char * old_base_name);
+
+/* Old and simpler registration function, sets hash_bits to 0,
+ * hash_function to NULL and old_base_name to NULL.
+ */
+
+int rsbac_list_register(rsbac_version_t ds_version,
+			rsbac_list_handle_t * handle_p,
+			struct rsbac_list_info_t *info_p,
+			u_int flags,
+			rsbac_list_compare_function_t * compare,
+			rsbac_list_get_conv_t * get_conv,
+			void *def_data, 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_p,
+			    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,
+			    void *def_data,
+			    void *def_subdata, char *name, kdev_t device);
+
+/* destroy list */
+/* list is destroyed, disk file is deleted */
+/* list must have been opened with register */
+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);
+
+/* detach from list */
+/* list is saved (if persistent) and removed from memory. Call register for new access. */
+/* Must not be called with spinlock held. */
+
+int rsbac_list_detach(rsbac_list_handle_t * handle_p,
+		      rsbac_list_key_t key);
+
+int rsbac_list_lol_detach(rsbac_list_handle_t * handle_p,
+			  rsbac_list_key_t key);
+
+/* set list's no_write flag */
+/* TRUE: do not write to disk, FALSE: writing allowed */
+int rsbac_list_no_write
+    (rsbac_list_handle_t handle, rsbac_list_key_t key,
+     rsbac_boolean_t no_write);
+
+int rsbac_list_lol_no_write
+    (rsbac_list_handle_t handle, rsbac_list_key_t key,
+     rsbac_boolean_t no_write);
+
+/* Set max_items_per_hash */
+int rsbac_list_max_items(rsbac_list_handle_t handle, rsbac_list_key_t key,
+			u_int max_items);
+
+int rsbac_list_lol_max_items(rsbac_list_handle_t handle, rsbac_list_key_t key,
+			u_int max_items, u_int max_subitems);
+
+/* Single list checking, good for cleanup of items with ttl in the past. */
+/* This functionality is also included in the big rsbac_check(). */
+
+int rsbac_list_check(rsbac_list_handle_t handle, const int correct);
+
+int rsbac_list_lol_check(rsbac_list_handle_t handle, const int correct);
+
+/* Transaction Support */
+#ifdef CONFIG_RSBAC_LIST_TRANS
+int rsbac_list_ta_begin(rsbac_time_t ttl,
+			rsbac_list_ta_number_t * ta_number_p,
+			rsbac_uid_t commit_uid,
+			char * name, char *password);
+
+int rsbac_list_ta_refresh(rsbac_time_t ttl,
+			  rsbac_list_ta_number_t ta_number,
+			  char *password);
+
+int rsbac_list_ta_commit(rsbac_list_ta_number_t ta_number, char *password);
+
+int rsbac_list_ta_forget(rsbac_list_ta_number_t ta_number, char *password);
+
+/* Returns TRUE, if transaction ta_number exists, and FALSE, if not. */
+int rsbac_list_ta_exist(rsbac_list_ta_number_t ta_number);
+#endif
+
+/* add with time-to-live - after this time in seconds the item gets automatically removed */
+/* set to 0 for unlimited (default), RSBAC_LIST_TTL_KEEP to keep previous setting */
+int rsbac_ta_list_add_ttl(rsbac_list_ta_number_t ta_number,
+			  rsbac_list_handle_t handle,
+			  rsbac_time_t ttl, void *desc, void *data);
+
+static inline int rsbac_list_add_ttl(rsbac_list_handle_t handle,
+		       rsbac_time_t ttl, void *desc, void *data)
+{
+	return rsbac_ta_list_add_ttl(0, handle, ttl, desc, data);
+}
+
+static inline int rsbac_list_add(rsbac_list_handle_t handle, void *desc, void *data)
+{
+	return rsbac_ta_list_add_ttl(0, handle, RSBAC_LIST_TTL_KEEP, desc,
+				     data);
+}
+
+/* Add list of lists sublist item, item for desc must exist */
+int rsbac_ta_list_lol_subadd_ttl(rsbac_list_ta_number_t ta_number,
+				 rsbac_list_handle_t handle,
+				 rsbac_time_t ttl,
+				 void *desc, void *subdesc, void *subdata);
+
+static inline int rsbac_list_lol_subadd_ttl(rsbac_list_handle_t handle,
+			      rsbac_time_t ttl,
+			      void *desc, void *subdesc, void *subdata)
+{
+	return rsbac_ta_list_lol_subadd_ttl(0, handle, ttl, desc, subdesc,
+					    subdata);
+}
+
+static inline int rsbac_list_lol_subadd(rsbac_list_handle_t handle,
+			  void *desc, void *subdesc, void *subdata)
+{
+	return rsbac_ta_list_lol_subadd_ttl(0, handle, RSBAC_LIST_TTL_KEEP,
+					    desc, subdesc, subdata);
+}
+
+/* add with time-to-live - after this time in seconds the item gets automatically removed */
+int rsbac_ta_list_lol_add_ttl(rsbac_list_ta_number_t ta_number,
+			      rsbac_list_handle_t handle,
+			      rsbac_time_t ttl, void *desc, void *data);
+
+static inline int rsbac_list_lol_add_ttl(rsbac_list_handle_t handle,
+			   rsbac_time_t ttl, void *desc, void *data)
+{
+	return rsbac_ta_list_lol_add_ttl(0, handle, ttl, desc, data);
+}
+
+static inline int rsbac_list_lol_add(rsbac_list_handle_t handle, void *desc, void *data)
+{
+	return rsbac_ta_list_lol_add_ttl(0, handle, RSBAC_LIST_TTL_KEEP,
+					 desc, data);
+}
+
+/* remove item */
+int rsbac_ta_list_remove(rsbac_list_ta_number_t ta_number,
+			 rsbac_list_handle_t handle, void *desc);
+
+static inline int rsbac_list_remove(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_remove(0, handle, desc);
+}
+
+/* remove all items */
+int rsbac_ta_list_remove_all(rsbac_list_ta_number_t ta_number,
+			     rsbac_list_handle_t handle);
+
+static inline int rsbac_list_remove_all(rsbac_list_handle_t handle)
+{
+	return rsbac_ta_list_remove_all(0, handle);
+}
+
+/* remove item from sublist - also succeeds, if item for desc or subdesc does not exist */
+int rsbac_ta_list_lol_subremove(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle,
+				void *desc, void *subdesc);
+
+static inline int rsbac_list_lol_subremove(rsbac_list_handle_t handle,
+			     void *desc, void *subdesc)
+{
+	return rsbac_ta_list_lol_subremove(0, handle, desc, subdesc);
+}
+
+int rsbac_ta_list_lol_subremove_count(rsbac_list_ta_number_t ta_number,
+				      rsbac_list_handle_t handle,
+				      void *desc, u_long count);
+
+
+/* remove same subitem from all sublists */
+int rsbac_ta_list_lol_subremove_from_all(rsbac_list_ta_number_t ta_number,
+					 rsbac_list_handle_t handle,
+					 void *subdesc);
+
+static inline int rsbac_list_lol_subremove_from_all(rsbac_list_handle_t handle,
+				      void *subdesc)
+{
+	return rsbac_ta_list_lol_subremove_from_all(0, handle, subdesc);
+}
+
+/* remove all subitems from list */
+int rsbac_ta_list_lol_subremove_all(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void *desc);
+
+static inline int rsbac_list_lol_subremove_all(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_lol_subremove_all(0, handle, desc);
+}
+
+int rsbac_ta_list_lol_remove(rsbac_list_ta_number_t ta_number,
+			     rsbac_list_handle_t handle, void *desc);
+
+static inline int rsbac_list_lol_remove(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_lol_remove(0, handle, desc);
+}
+
+int rsbac_ta_list_lol_remove_all(rsbac_list_ta_number_t ta_number,
+				 rsbac_list_handle_t handle);
+
+static inline int rsbac_list_lol_remove_all(rsbac_list_handle_t handle)
+{
+	return rsbac_ta_list_lol_remove_all(0, handle);
+}
+
+
+/* get item data */
+/* Item data is copied - we cannot give a pointer, because item could be
+ * removed */
+/* also get time-to-live - after this time in seconds the item gets automatically removed */
+/* both ttl_p and data can be NULL, they are then simply not returned */
+int rsbac_ta_list_get_data_ttl(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle,
+			       rsbac_time_t * ttl_p,
+			       void *desc, void *data);
+
+static inline int rsbac_list_get_data_ttl(rsbac_list_handle_t handle,
+			    rsbac_time_t * ttl_p, void *desc, void *data)
+{
+	return rsbac_ta_list_get_data_ttl(0, handle, ttl_p, desc, data);
+}
+
+static inline int rsbac_list_get_data(rsbac_list_handle_t handle, void *desc, void *data)
+{
+	return rsbac_ta_list_get_data_ttl(0, handle, NULL, desc, data);
+}
+
+/* get data from a subitem */
+/* also get time-to-live - after this time in seconds the item gets automatically removed */
+/* both ttl_p and data can be NULL, they are then simply not returned */
+int rsbac_ta_list_lol_get_subdata_ttl(rsbac_list_ta_number_t ta_number,
+				      rsbac_list_handle_t handle,
+				      rsbac_time_t * ttl_p,
+				      void *desc,
+				      void *subdesc, void *subdata);
+
+static inline int rsbac_list_lol_get_subdata_ttl(rsbac_list_handle_t handle,
+				   rsbac_time_t * ttl_p,
+				   void *desc,
+				   void *subdesc, void *subdata)
+{
+	return rsbac_ta_list_lol_get_subdata_ttl(0, handle,
+						 ttl_p, desc, subdesc,
+						 subdata);
+}
+
+static inline int rsbac_list_lol_get_subdata(rsbac_list_handle_t handle,
+			       void *desc, void *subdesc, void *subdata)
+{
+	return rsbac_ta_list_lol_get_subdata_ttl(0, handle, NULL, desc,
+						 subdesc, subdata);
+}
+
+/* also get time-to-live - after this time in seconds the item gets automatically removed */
+/* both ttl_p and data can be NULL, they are then simply not returned */
+int rsbac_ta_list_lol_get_data_ttl(rsbac_list_ta_number_t ta_number,
+				   rsbac_list_handle_t handle,
+				   rsbac_time_t * ttl_p,
+				   void *desc, void *data);
+
+static inline int rsbac_list_lol_get_data_ttl(rsbac_list_handle_t handle,
+				rsbac_time_t * ttl_p,
+				void *desc, void *data)
+{
+	return rsbac_ta_list_lol_get_data_ttl(0, handle, ttl_p, desc,
+					      data);
+}
+
+static inline int rsbac_list_lol_get_data(rsbac_list_handle_t handle,
+			    void *desc, void *data)
+{
+	return rsbac_ta_list_lol_get_data_ttl(0, handle, NULL, desc, data);
+}
+
+/* get item desc by data */
+/* Item desc is copied - we cannot give a pointer, because item could be
+ * removed.
+ * If no compare function is provided (NULL value), memcmp is used.
+ * Note: The data value given here is always used as second parameter to the
+ *       compare function, so you can use different types for storage and
+ *       lookup.
+ */
+int rsbac_ta_list_get_desc_ttl(rsbac_list_ta_number_t ta_number,
+			   rsbac_list_handle_t handle,
+			   rsbac_time_t * ttl_p,
+			   void *desc,
+			   void *data,
+			   rsbac_list_data_compare_function_t compare);
+
+static inline int rsbac_ta_list_get_desc(rsbac_list_ta_number_t ta_number,
+			   rsbac_list_handle_t handle,
+			   void *desc,
+			   void *data,
+			   rsbac_list_data_compare_function_t compare)
+{
+	return rsbac_ta_list_get_desc_ttl(ta_number, handle, NULL, desc, data, compare);
+}
+
+static inline int rsbac_list_get_desc(rsbac_list_handle_t handle,
+			void *desc,
+			void *data,
+			rsbac_list_data_compare_function_t compare)
+{
+	return rsbac_ta_list_get_desc_ttl(0, handle, NULL, desc, data, compare);
+}
+
+int rsbac_ta_list_get_desc_selector_ttl(
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	rsbac_time_t * ttl_p,
+	void *desc,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param);
+
+static inline int rsbac_ta_list_get_desc_selector(
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	void *desc,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	return rsbac_ta_list_get_desc_selector_ttl(ta_number, handle, NULL, desc, data, compare, selector, param);
+}
+
+int rsbac_ta_list_lol_get_desc_ttl(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle,
+			       rsbac_time_t * ttl_p,
+			       void *desc,
+			       void *data,
+			       rsbac_list_data_compare_function_t compare);
+
+static inline int rsbac_ta_list_lol_get_desc(rsbac_list_ta_number_t ta_number,
+			    rsbac_list_handle_t handle,
+			    void *desc,
+			    void *data,
+			    rsbac_list_data_compare_function_t compare)
+{
+	return rsbac_ta_list_lol_get_desc_ttl(ta_number, handle, NULL, desc, data, compare);
+}
+
+static inline int rsbac_list_lol_get_desc(rsbac_list_handle_t handle,
+			    void *desc,
+			    void *data,
+			    rsbac_list_data_compare_function_t compare)
+{
+	return rsbac_ta_list_lol_get_desc_ttl(0, handle, NULL, desc, data, compare);
+}
+
+int rsbac_ta_list_lol_get_desc_selector_ttl(
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	rsbac_time_t * ttl_p,
+	void *desc,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param);
+
+static inline int rsbac_ta_list_lol_get_desc_selector(
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	void *desc,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	return rsbac_ta_list_lol_get_desc_selector_ttl(ta_number, handle, NULL, desc, data, compare, selector, param);
+}
+
+/* get maximum desc (uses compare function) */
+int rsbac_ta_list_get_max_desc(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle, void *desc);
+
+static inline int rsbac_list_get_max_desc(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_get_max_desc(0, handle, desc);
+}
+
+int rsbac_ta_list_lol_get_max_subdesc(rsbac_list_ta_number_t ta_number,
+				      rsbac_list_handle_t handle,
+				      void *desc, void *subdesc);
+
+/* get next desc (uses compare function) */
+int rsbac_ta_list_get_next_desc(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle,
+				void *old_desc, void *next_desc);
+
+static inline int rsbac_list_get_next_desc(rsbac_list_handle_t handle, void *old_desc,
+			     void *next_desc)
+{
+	return rsbac_ta_list_get_next_desc(0, handle, old_desc, next_desc);
+}
+
+int rsbac_ta_list_get_next_desc_selector(
+		rsbac_list_ta_number_t ta_number,
+		rsbac_list_handle_t handle,
+		void *old_desc,
+		void *next_desc,
+		rsbac_list_desc_selector_function_t selector,
+		void * param);
+
+int rsbac_ta_list_lol_get_next_desc(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void *old_desc, void *next_desc);
+
+static inline int rsbac_list_lol_get_next_desc(rsbac_list_handle_t handle,
+				 void *old_desc, void *next_desc)
+{
+	return rsbac_ta_list_lol_get_next_desc(0, handle, old_desc,
+					       next_desc);
+}
+
+int rsbac_ta_list_lol_get_next_desc_selector(
+		rsbac_list_ta_number_t ta_number,
+		rsbac_list_handle_t handle,
+		void *old_desc,
+		void *next_desc,
+		rsbac_list_desc_selector_function_t selector,
+		void * param);
+
+/* does item exist? */
+/* returns TRUE, if item exists, FALSE, if not or error */
+int rsbac_ta_list_exist(rsbac_list_ta_number_t ta_number,
+			rsbac_list_handle_t handle, void *desc);
+
+static inline int rsbac_list_exist(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_exist(0, handle, desc);
+}
+
+int rsbac_ta_list_lol_subexist(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle,
+			       void *desc, void *subdesc);
+
+static inline int rsbac_list_lol_subexist(rsbac_list_handle_t handle,
+			    void *desc, void *subdesc)
+{
+	return rsbac_ta_list_lol_subexist(0, handle, desc, subdesc);
+}
+
+int rsbac_ta_list_lol_exist(rsbac_list_ta_number_t ta_number,
+			    rsbac_list_handle_t handle, void *desc);
+
+static inline int rsbac_list_lol_exist(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_lol_exist(0, handle, desc);
+}
+
+/*
+ * Note: The subdesc/data value given here is always used as second parameter to the
+ *       given subdesc compare function, so you can use different types for storage and
+ *       lookup. If compare is NULL, call is forwarded to rsbac_list_lol_subexist.
+ * Warning: This function does not use the list optimization when searching the sublist!
+ */
+int rsbac_ta_list_lol_subexist_compare(rsbac_list_ta_number_t ta_number,
+				       rsbac_list_handle_t handle,
+				       void *desc,
+				       void *subdesc,
+				       rsbac_list_compare_function_t
+				       compare);
+
+static inline int rsbac_list_lol_subexist_compare(rsbac_list_handle_t handle,
+				    void *desc,
+				    void *subdesc,
+				    rsbac_list_compare_function_t compare)
+{
+	return rsbac_ta_list_lol_subexist_compare(0, handle,
+						  desc, subdesc, compare);
+}
+
+/* count number of elements */
+/* returns number of elements or negative error code */
+long rsbac_ta_list_count(rsbac_list_ta_number_t ta_number,
+			 rsbac_list_handle_t handle);
+
+static inline long rsbac_list_count(rsbac_list_handle_t handle)
+{
+	return rsbac_ta_list_count(0, handle);
+}
+
+long rsbac_ta_list_lol_subcount(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle, void *desc);
+
+static inline long rsbac_list_lol_subcount(rsbac_list_handle_t handle, void *desc)
+{
+	return rsbac_ta_list_lol_subcount(0, handle, desc);
+}
+
+long rsbac_ta_list_lol_all_subcount(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle);
+
+static inline long rsbac_list_lol_all_subcount(rsbac_list_handle_t handle)
+{
+	return rsbac_ta_list_lol_all_subcount(0, handle);
+}
+
+long rsbac_ta_list_lol_count(rsbac_list_ta_number_t ta_number,
+			     rsbac_list_handle_t handle);
+
+static inline long rsbac_list_lol_count(rsbac_list_handle_t handle)
+{
+	return rsbac_ta_list_lol_count(0, handle);
+}
+
+
+/* Get array of all descriptors */
+/* Returns number of elements or negative error code */
+/* If return value > 0, *array_p contains a pointer to a rsbac_kmalloc'd array
+   of descs, otherwise *array_p is set to NULL. If *array_p has been set,
+   caller must call rsbac_kfree(*array_p) after use! */
+
+long rsbac_ta_list_get_all_desc(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle,
+				void **array_p);
+
+static inline long rsbac_list_get_all_desc(rsbac_list_handle_t handle, void **array_p)
+{
+	return rsbac_ta_list_get_all_desc(0, handle, array_p);
+}
+
+long rsbac_ta_list_get_all_desc_selector (
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle, void **array_p,
+	rsbac_list_desc_selector_function_t selector,
+	void * param);
+
+long rsbac_ta_list_lol_get_all_subdesc_ttl(rsbac_list_ta_number_t
+					   ta_number,
+					   rsbac_list_handle_t handle,
+					   void *desc, void **array_p,
+					   rsbac_time_t ** ttl_array_p);
+
+static inline long rsbac_list_lol_get_all_subdesc(rsbac_list_handle_t handle,
+				void *desc,
+				void **array_p)
+{
+	return rsbac_ta_list_lol_get_all_subdesc_ttl(0, handle,
+						     desc, array_p, NULL);
+}
+
+static inline long rsbac_list_lol_get_all_subdesc_ttl(rsbac_list_handle_t handle,
+					void *desc,
+					void **array_p,
+					rsbac_time_t ** ttl_array_p)
+{
+	return rsbac_ta_list_lol_get_all_subdesc_ttl(0,
+						     handle,
+						     desc,
+						     array_p, ttl_array_p);
+}
+
+long rsbac_ta_list_lol_get_all_desc(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void **array_p);
+
+static inline long rsbac_list_lol_get_all_desc(rsbac_list_handle_t handle,
+				 void **array_p)
+{
+	return rsbac_ta_list_lol_get_all_desc(0, handle, array_p);
+}
+
+long rsbac_ta_list_lol_get_all_desc_selector (
+        rsbac_list_ta_number_t ta_number,
+        rsbac_list_handle_t handle,
+        void **array_p,
+        rsbac_list_desc_selector_function_t selector,
+        void * param);
+
+/* Get array of all datas */
+/* Returns number of elements or negative error code */
+/* If return value > 0, *array_p contains a pointer to a rsbac_kmalloc'd array
+   of datas, otherwise *array_p is set to NULL. If *array_p has been set,
+   caller must call rsbac_kfree(*array_p) after use! */
+
+long rsbac_ta_list_get_all_data(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle,
+				void **array_p);
+
+static inline long rsbac_list_get_all_data(rsbac_list_handle_t handle, void **array_p)
+{
+	return rsbac_ta_list_get_all_data(0, handle, array_p);
+}
+
+long rsbac_ta_list_lol_get_all_subdata(rsbac_list_ta_number_t ta_number,
+				       rsbac_list_handle_t handle,
+				       void *desc, void **array_p);
+
+static inline long rsbac_list_lol_get_all_subdata(rsbac_list_handle_t handle,
+				    void *desc, void **array_p)
+{
+	return rsbac_ta_list_lol_get_all_subdata(0, handle, desc, array_p);
+}
+
+long rsbac_ta_list_lol_get_all_data(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void **array_p);
+
+static inline long rsbac_list_lol_get_all_data(rsbac_list_handle_t handle,
+				 void **array_p)
+{
+	return rsbac_ta_list_lol_get_all_data(0, handle, 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 */
+/* Returns number of items or negative error code */
+/* If return value > 0, *array_p contains a pointer to a rsbac_kmalloc'd array
+   of items, where desc and data are placed directly behind each other.
+   If *array_p has been set, caller must call rsbac_kfree(*array_p) after use! */
+
+long rsbac_ta_list_get_all_items_ttl(rsbac_list_ta_number_t ta_number,
+				     rsbac_list_handle_t handle,
+				     void **array_p,
+				     rsbac_time_t ** ttl_array_p);
+
+static inline long rsbac_list_get_all_items_ttl(rsbac_list_handle_t handle,
+				  void **array_p,
+				  rsbac_time_t ** ttl_array_p)
+{
+	return rsbac_ta_list_get_all_items_ttl(0, handle, array_p,
+					       ttl_array_p);
+}
+
+static inline long rsbac_list_get_all_items(rsbac_list_handle_t handle, void **array_p)
+{
+	return rsbac_ta_list_get_all_items_ttl(0, handle, array_p, NULL);
+}
+
+long rsbac_ta_list_lol_get_all_subitems_ttl(rsbac_list_ta_number_t
+					    ta_number,
+					    rsbac_list_handle_t handle,
+					    void *desc, void **array_p,
+					    rsbac_time_t ** ttl_array_p);
+
+static inline long rsbac_list_lol_get_all_subitems_ttl(rsbac_list_handle_t handle,
+					 void *desc,
+					 void **array_p,
+					 rsbac_time_t ** ttl_array_p)
+{
+	return rsbac_ta_list_lol_get_all_subitems_ttl(0, handle, desc,
+						      array_p,
+						      ttl_array_p);
+}
+
+static inline long rsbac_list_lol_get_all_subitems(rsbac_list_handle_t handle,
+				     void *desc, void **array_p)
+{
+	return rsbac_ta_list_lol_get_all_subitems_ttl(0, handle, desc,
+						      array_p, NULL);
+}
+
+long rsbac_ta_list_lol_get_all_items(rsbac_list_ta_number_t ta_number,
+				     rsbac_list_handle_t handle,
+				     void **array_p);
+
+static inline long rsbac_list_lol_get_all_items(rsbac_list_handle_t handle,
+				  void **array_p)
+{
+	return rsbac_ta_list_lol_get_all_items(0, handle, array_p);
+}
+
+/* Copy a complete list
+ * Both lists must have been registered with same desc and data sizes,
+ * hash_bits may differ. Old target list items are removed before copying.
+ * If ta_number is set and transactions are enabled, the complete
+ * target list content is in the same transaction. Forgetting the
+ * transaction will restore the old to_list.
+ */
+
+long rsbac_list_copy(rsbac_list_ta_number_t ta_number,
+			rsbac_list_handle_t from_handle,
+			rsbac_list_handle_t to_handle);
+
+long rsbac_list_lol_copy(rsbac_list_ta_number_t ta_number,
+			rsbac_list_handle_t from_handle,
+			rsbac_list_handle_t to_handle);
+
+/* Get the current number of hashes - may vary when resized */
+int rsbac_list_get_hash_bits(rsbac_list_handle_t handle);
+
+int rsbac_list_lol_get_hash_bits(rsbac_list_handle_t handle);
+
+#endif
+/* end of lists.h */
diff --git a/include/rsbac/log_cap.h b/include/rsbac/log_cap.h
new file mode 100644
index 0000000..82195bf
--- /dev/null
+++ b/include/rsbac/log_cap.h
@@ -0,0 +1,14 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 2005:             */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Missing Cap logging              */
+/* Last modified: 27/May/2005       */
+/********************************** */
+
+#ifndef __RSBAC_LOG_CAP_H
+#define __RSBAC_LOG_CAP_H
+
+void rsbac_log_missing_cap(int cap);
+
+#endif
diff --git a/include/rsbac/lsm.h b/include/rsbac/lsm.h
new file mode 100644
index 0000000..1136dc0
--- /dev/null
+++ b/include/rsbac/lsm.h
@@ -0,0 +1,16 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 2003: Amon Ott       */
+/* file system                         */
+/* Helper functions for all parts      */
+/* Last modified: 28/Jul/2003          */
+/************************************* */
+
+#ifndef __RSBAC_LSM_H
+#define __RSBAC_LSM_H
+
+#include <linux/security.h>
+
+int rsbac_lsm_register(void);
+
+#endif
diff --git a/include/rsbac/mac.h b/include/rsbac/mac.h
new file mode 100644
index 0000000..9598a6a
--- /dev/null
+++ b/include/rsbac/mac.h
@@ -0,0 +1,134 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2013:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* API: Data structures               */
+/* and functions for Access           */
+/* Control Information / MAC          */
+/* Last modified: 09/Aug/2013         */
+/************************************ */
+
+#ifndef __RSBAC_MAC_H
+#define __RSBAC_MAC_H
+
+#include <linux/init.h>
+#include <rsbac/types.h>
+
+/***************************************************/
+/*               General Prototypes                */
+/***************************************************/
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+/****************************************************************************/
+/* Initialization, including ACI restoration for all mounted devices from   */
+/* disk. After this call, all ACI is kept in memory for performance reasons,*/
+/* but user and file/dir object ACI are written to disk on every change.    */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern int rsbac_init_mac(void);
+#else
+extern int rsbac_init_mac(void) __init;
+#endif
+
+/* mounting and umounting */
+int rsbac_mount_mac(kdev_t kdev);
+int rsbac_umount_mac(kdev_t kdev);
+
+/* Some information about the current status is also available */
+extern int rsbac_stats_mac(void);
+
+/* Status checking */
+extern int rsbac_check_mac(int correct, int check_inode);
+
+/* RSBAC attribute saving to disk can be triggered from outside
+ * param: call lock_kernel() before writing?
+ */
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+extern int rsbac_write_mac(rsbac_boolean_t);
+#endif /* CONFIG_RSBAC_AUTO_WRITE */
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the semaphores to protect the targets during */
+/* access.                                                                  */
+/* Trying to access a never created or removed set returns an error!        */
+
+/* rsbac_mac_add_to_truset */
+/* Add a set member to a set sublist. Set behaviour: also returns success, */
+/* if member was already in set! */
+
+int rsbac_mac_add_to_p_truset(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t member,
+  rsbac_time_t ttl);
+
+int rsbac_mac_add_to_f_truset(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t member,
+  rsbac_time_t ttl);
+
+/* rsbac_mac_remove_from_truset */
+/* Remove a set member from a sublist. Set behaviour: Returns no error, if */
+/* member is not in list.                                                  */
+
+int rsbac_mac_remove_from_p_truset(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t member);
+
+int rsbac_mac_remove_from_f_truset(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t member);
+
+/* rsbac_mac_clear_truset */
+/* Remove all set members from a sublist. Set behaviour: Returns no error, */
+/* if list is empty.                                                       */
+
+int rsbac_mac_clear_p_truset(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid);
+
+int rsbac_mac_clear_f_truset(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file);
+
+/* rsbac_mac_truset_member */
+/* Return truth value, whether member is in set */
+
+rsbac_boolean_t  rsbac_mac_p_truset_member(rsbac_pid_t pid,
+                                   rsbac_uid_t member);
+
+/* rsbac_mac_remove_truset */
+/* Remove a full set. For cleanup, if object is deleted. */
+/* To empty an existing set use rsbac_mac_clear_truset. */
+
+int rsbac_mac_remove_p_trusets(rsbac_pid_t pid);
+
+int rsbac_mac_remove_f_trusets(rsbac_mac_file_t file);
+
+int rsbac_mac_copy_fp_truset(rsbac_mac_file_t    file,
+                              rsbac_pid_t p_tru_set_id);
+
+int rsbac_mac_copy_pp_truset(rsbac_pid_t old_p_set_id,
+                              rsbac_pid_t new_p_set_id);
+
+int rsbac_mac_get_f_trulist(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t **trulist_p,
+  rsbac_time_t **ttllist_p);
+
+int rsbac_mac_get_p_trulist(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t **trulist_p,
+  rsbac_time_t **ttllist_p);
+
+#endif
diff --git a/include/rsbac/mac_data_structures.h b/include/rsbac/mac_data_structures.h
new file mode 100644
index 0000000..4567a44
--- /dev/null
+++ b/include/rsbac/mac_data_structures.h
@@ -0,0 +1,54 @@
+/**************************************/
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016:          */
+/*   Amon Ott <ao@rsbac.org> */
+/* Data structures / MAC              */
+/* Last modified: 07/Jan/2016         */
+/**************************************/
+
+#ifndef __RSBAC_MAC_DATA_STRUC_H
+#define __RSBAC_MAC_DATA_STRUC_H
+
+#include <linux/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/types.h>
+
+/**********************************************/
+/* Capability lists                           */
+/**********************************************/
+
+#define RSBAC_MAC_LIST_KEY 626281
+
+#define RSBAC_MAC_P_LIST_VERSION 1
+#define RSBAC_MAC_P_LIST_NAME "macptru"
+
+#define RSBAC_MAC_FD_FILENAME "macfdtru"
+#define RSBAC_MAC_FD_OLD_FILENAME "macfdtru."
+#define RSBAC_MAC_NR_TRU_FD_LIST_HASH_BITS 2
+#define RSBAC_MAC_FD_LIST_VERSION 2
+#define RSBAC_MAC_FD_OLD_LIST_VERSION 1
+
+/* The list of devices is also a double linked list, so we define list    */
+/* items and a list head.                                                 */
+
+struct rsbac_mac_device_list_item_t {
+	kdev_t id;		/* set to 0 before deletion */
+	u_int mount_count;
+	rsbac_list_handle_t handle;
+	struct rsbac_mac_device_list_item_t *prev;
+	struct rsbac_mac_device_list_item_t *next;
+};
+
+/* To provide consistency we use spinlocks for all list accesses. The     */
+/* 'curr' entry is used to avoid repeated lookups for the same item.       */
+
+struct rsbac_mac_device_list_head_t {
+	struct rsbac_mac_device_list_item_t *head;
+	struct rsbac_mac_device_list_item_t *tail;
+	struct rsbac_mac_device_list_item_t *curr;
+	spinlock_t lock;
+	struct lock_class_key lock_class;
+	u_int count;
+};
+
+#endif
diff --git a/include/rsbac/net_getname.h b/include/rsbac/net_getname.h
new file mode 100644
index 0000000..e0c7a70
--- /dev/null
+++ b/include/rsbac/net_getname.h
@@ -0,0 +1,50 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 1999-2003:        */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for CAP module */
+/* Last modified: 22/Dec/2003       */
+/********************************** */
+
+#ifndef __RSBAC_NET_GETNAME_H
+#define __RSBAC_NET_GETNAME_H
+
+#include <rsbac/types.h>
+
+#define RSBAC_NET_PROTO_MAX 256
+#define RSBAC_NET_TYPE_MAX 11
+
+#ifdef __KERNEL__
+extern int rsbac_net_str_to_inet(char * str, __u32 * addr);
+#else
+#ifndef AF_MAX
+#define AF_MAX 32
+#endif
+#endif
+
+extern char * rsbac_get_net_temp_syscall_name(char * name,
+                                        enum rsbac_net_temp_syscall_t value);
+
+extern char * rsbac_get_net_family_name(char * name,
+                                  u_int value);
+
+extern char * rsbac_get_net_netlink_family_name(char * name,
+                                  u_int value);
+
+extern char * rsbac_get_net_protocol_name(char * name,
+                                    u_int value);
+
+extern char * rsbac_get_net_type_name(char * name,
+                                u_int value);
+
+#ifndef __KERNEL__
+enum rsbac_net_temp_syscall_t rsbac_get_net_temp_syscall_nr(const char * name);
+
+int rsbac_get_net_family_nr(const char * name);
+
+int rsbac_get_net_protocol_nr(const char * name);
+
+int rsbac_get_net_type_nr(const char * name);
+#endif
+
+#endif
diff --git a/include/rsbac/network.h b/include/rsbac/network.h
new file mode 100644
index 0000000..fbf3a89
--- /dev/null
+++ b/include/rsbac/network.h
@@ -0,0 +1,91 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2004:           */
+/*   Amon Ott <ao@rsbac.org>           */
+/* Network helper functions            */
+/* Last modified: 07/Dec/2004          */
+/************************************* */
+
+#ifndef __RSBAC_NETWORK_H
+#define __RSBAC_NETWORK_H
+
+#include <rsbac/types.h>
+#include <rsbac/network_types.h>
+#include <linux/net.h>
+#include <linux/in.h>
+#include <linux/un.h>
+#include <net/sock.h>
+#include <net/inet_sock.h>
+#include <net/af_unix.h>
+#include <net/route.h>
+
+/* functions */
+
+int rsbac_ta_net_list_all_netdev(rsbac_list_ta_number_t ta_number, rsbac_netdev_id_t ** id_pp);
+
+static inline int rsbac_net_list_all_netdev(rsbac_netdev_id_t ** id_pp)
+  {
+    return rsbac_ta_net_list_all_netdev(0, id_pp);
+  }
+
+//__u32 rsbac_net_make_mask_u32(__u8 valid_bits);
+
+int rsbac_net_compare_data(void * data1, void * data2);
+
+int rsbac_net_get_id(
+         rsbac_list_ta_number_t ta_number,
+  struct rsbac_net_description_t * desc_p,
+         rsbac_net_temp_id_t * id_p);
+
+// void rsbac_net_obj_cleanup(rsbac_net_obj_id_t netobj);
+
+int rsbac_ta_net_lookup_templates(
+         rsbac_list_ta_number_t ta_number,
+  struct rsbac_net_obj_desc_t * netobj_p,
+         rsbac_net_temp_id_t * local_temp_p,
+         rsbac_net_temp_id_t * remote_temp_p);
+
+static inline int rsbac_net_lookup_templates(
+  struct rsbac_net_obj_desc_t * netobj_p,
+         rsbac_net_temp_id_t * local_temp_p,
+         rsbac_net_temp_id_t * remote_temp_p)
+  {
+    return rsbac_ta_net_lookup_templates(0, netobj_p, local_temp_p, remote_temp_p);
+  }
+
+/* Does template exist? Returns TRUE if yes, FALSE if no */
+int rsbac_ta_net_template_exists(rsbac_list_ta_number_t ta_number,
+	rsbac_net_temp_id_t id);
+
+int rsbac_ta_net_template(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_net_temp_syscall_t call,
+  rsbac_net_temp_id_t id,
+  union rsbac_net_temp_syscall_data_t * data_p);
+
+static inline int rsbac_net_template(enum rsbac_net_temp_syscall_t call,
+                       rsbac_net_temp_id_t id,
+                       union rsbac_net_temp_syscall_data_t * data_p)
+  {
+    return rsbac_ta_net_template(0, call, id, data_p);
+  }
+
+int rsbac_ta_net_list_all_template(rsbac_list_ta_number_t ta_number,
+                                   rsbac_net_temp_id_t ** id_pp);
+
+static inline int rsbac_net_list_all_template(rsbac_net_temp_id_t ** id_pp)
+  {
+    return rsbac_ta_net_list_all_template(0, id_pp);
+  }
+
+int rsbac_ta_net_template_exist(rsbac_list_ta_number_t ta_number, rsbac_net_temp_id_t temp);
+
+static inline int rsbac_net_template_exist(rsbac_net_temp_id_t temp)
+  {
+    return rsbac_ta_net_template_exist(0, temp);
+  }
+
+/* Whether request should be checked for remote endpoint */
+int rsbac_net_remote_request(enum rsbac_adf_request_t request);
+
+#endif
diff --git a/include/rsbac/network_types.h b/include/rsbac/network_types.h
new file mode 100644
index 0000000..c8a0ab8
--- /dev/null
+++ b/include/rsbac/network_types.h
@@ -0,0 +1,154 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2009:           */
+/*   Amon Ott <ao@rsbac.org>           */
+/* Network access control data structs */
+/* Last modified: 03/Feb/2009          */
+/************************************* */
+
+#ifndef __RSBAC_NETWORK_TYPES_H
+#define __RSBAC_NETWORK_TYPES_H
+
+#define RSBAC_NET_ANY 0
+#define RSBAC_NET_NETLINK_PROTO_ANY 255
+
+#define RSBAC_NET_UNKNOWN 0
+
+#define RSBAC_NET_TEMP_VERSION 2
+#define RSBAC_NET_TEMP_OLD_VERSION 1
+#define RSBAC_NET_TEMP_KEY 0x815affe
+#define RSBAC_NET_TEMP_NAME "nettemp"
+
+typedef __u32 rsbac_net_temp_id_t;
+
+#define RSBAC_NET_MAX_ADDRESS_LEN 128
+#define RSBAC_NET_TEMP_NAMELEN 16
+
+#define RSBAC_NET_MAX_PORT 65535
+
+#define RSBAC_NET_NR_INET_ADDR 25
+#define RSBAC_NET_NR_PORTS 10
+
+struct rsbac_net_temp_port_range_t {
+	__u16 min;
+	__u16 max;
+};
+
+struct rsbac_net_temp_inet_addr_t {
+	__u32 addr[RSBAC_NET_NR_INET_ADDR];
+	__u8 valid_bits[RSBAC_NET_NR_INET_ADDR];
+	__u8 nr_addr;
+};
+
+struct rsbac_net_temp_other_addr_t {
+	char addr[RSBAC_NET_MAX_ADDRESS_LEN];
+	__u8 valid_len;
+};
+
+struct rsbac_net_temp_ports_t {
+	struct rsbac_net_temp_port_range_t ports[RSBAC_NET_NR_PORTS];
+	__u8 nr_ports;
+};
+
+union rsbac_net_temp_addr_t {
+	struct rsbac_net_temp_inet_addr_t inet;
+	struct rsbac_net_temp_other_addr_t other;
+};
+
+struct rsbac_net_temp_data_t {
+	/* must be first for alignment */
+	union rsbac_net_temp_addr_t address;
+	__u8 address_family;
+	__u8 type;
+	__u8 protocol;
+	rsbac_netdev_id_t netdev;
+	struct rsbac_net_temp_ports_t ports;	/* for those address families that support them */
+	char name[RSBAC_NET_TEMP_NAMELEN];
+};
+
+struct rsbac_net_temp_old_data_t {
+	/* must be first for alignment */
+	char address[RSBAC_NET_MAX_ADDRESS_LEN];
+	__u8 address_family;
+	__u8 valid_len;		/* Bytes for AF_UNIX, Bits for all others */
+	__u8 type;
+	__u8 protocol;
+	rsbac_netdev_id_t netdev;
+	__u16 min_port;		/* for those address families that support them */
+	__u16 max_port;
+	char name[RSBAC_NET_TEMP_NAMELEN];
+};
+
+#define RSBAC_NET_TEMP_LNET_ID 100101
+#define RSBAC_NET_TEMP_LNET_ADDRESS "127.0.0.0"
+#define RSBAC_NET_TEMP_LAN_ID 100102
+#define RSBAC_NET_TEMP_LAN_ADDRESS "192.168.0.0"
+#define RSBAC_NET_TEMP_AUTO_ID 100105
+#define RSBAC_NET_TEMP_AUTO_ADDRESS "0.0.0.0"
+#define RSBAC_NET_TEMP_INET_ID 100110
+#define RSBAC_NET_TEMP_ALL_ID ((rsbac_net_temp_id_t) -1)
+
+/* default templates moved into aci_data_structures.c */
+
+struct rsbac_net_description_t {
+	__u8 address_family;
+	void *address;
+	__u8 address_len;
+	__u8 type;
+	__u8 protocol;
+	rsbac_netdev_id_t netdev;
+	__u16 port;
+};
+
+enum rsbac_net_temp_syscall_t {
+	NTS_new_template,
+	NTS_copy_template,
+	NTS_delete_template,
+	NTS_check_id,
+	NTS_get_address,
+	NTS_get_address_family,
+	NTS_get_type,
+	NTS_get_protocol,
+	NTS_get_netdev,
+	NTS_get_ports,
+	NTS_get_name,
+	NTS_set_address,
+	NTS_set_address_family,
+	NTS_set_type,
+	NTS_set_protocol,
+	NTS_set_netdev,
+	NTS_set_ports,
+	NTS_set_name,
+	NTS_none
+};
+
+union rsbac_net_temp_syscall_data_t {
+	rsbac_net_temp_id_t id;
+	union rsbac_net_temp_addr_t address;
+	__u8 address_family;
+	__u8 type;
+	__u8 protocol;
+	rsbac_netdev_id_t netdev;
+	struct rsbac_net_temp_ports_t ports;	/* for those address families that support them */
+	char name[RSBAC_NET_TEMP_NAMELEN];
+};
+
+/*
+ *      Display an IP address in readable format.
+ */
+
+#ifndef NIPQUAD
+#define NIPQUAD(addr) \
+	((unsigned char *)&addr)[0], \
+	((unsigned char *)&addr)[1], \
+	((unsigned char *)&addr)[2], \
+	((unsigned char *)&addr)[3]
+
+#define HIPQUAD(addr) \
+	((unsigned char *)&addr)[3], \
+	((unsigned char *)&addr)[2], \
+	((unsigned char *)&addr)[1], \
+	((unsigned char *)&addr)[0]
+#endif
+
+#endif
diff --git a/include/rsbac/pax.h b/include/rsbac/pax.h
new file mode 100644
index 0000000..a4bacc7
--- /dev/null
+++ b/include/rsbac/pax.h
@@ -0,0 +1,21 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2004: Amon Ott */
+/* API:                               */
+/* Functions for Access               */
+/* Control Information / PAX          */
+/* Last modified: 12/Jan/2004         */
+/************************************ */
+
+#ifndef __RSBAC_PAX_H
+#define __RSBAC_PAX_H
+
+#include <rsbac/types.h>
+
+/***************************************************/
+/*               General Prototypes                */
+/***************************************************/
+
+void rsbac_pax_set_flags_func(struct linux_binprm * bprm);
+
+#endif
diff --git a/include/rsbac/pax_getname.h b/include/rsbac/pax_getname.h
new file mode 100644
index 0000000..e6611d7
--- /dev/null
+++ b/include/rsbac/pax_getname.h
@@ -0,0 +1,20 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 1999-2004:        */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for CAP module */
+/* Last modified: 06/Jan/2004       */
+/********************************** */
+
+#ifndef __RSBAC_PAX_GETNAME_H
+#define __RSBAC_PAX_GETNAME_H
+
+#include <rsbac/types.h>
+
+char * pax_print_flags(char * string, rsbac_pax_flags_t flags);
+
+#ifndef __KERNEL__
+rsbac_pax_flags_t pax_strtoflags(char * string, rsbac_pax_flags_t init_flags);
+#endif
+
+#endif
diff --git a/include/rsbac/proc_fs.h b/include/rsbac/proc_fs.h
new file mode 100644
index 0000000..8b1e39b
--- /dev/null
+++ b/include/rsbac/proc_fs.h
@@ -0,0 +1,20 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2001: Amon Ott  */
+/* proc fs functions                   */
+/* Last modified: 17/Jul/2001          */
+/************************************* */
+
+#ifndef __RSBAC_PROC_FS_H
+#define __RSBAC_PROC_FS_H
+
+#include <linux/proc_fs.h>
+
+#ifndef PROC_BLOCK_SIZE
+#define PROC_BLOCK_SIZE	(3*1024)  /* 4K page size but our output routines use some slack for overruns */
+#endif
+
+extern struct proc_dir_entry * proc_rsbac_root_p;
+extern struct proc_dir_entry * proc_rsbac_backup_p;
+
+#endif
diff --git a/include/rsbac/rc.h b/include/rsbac/rc.h
new file mode 100644
index 0000000..8efdbbb
--- /dev/null
+++ b/include/rsbac/rc.h
@@ -0,0 +1,104 @@
+/******************************* */
+/* Rule Set Based Access Control */
+/* Author and (c) 1999-2009:     */
+/*   Amon Ott <ao@rsbac.org>     */
+/* API: Data structures          */
+/* and functions for Access      */
+/* Control Information / RC      */
+/* Last modified: 15/Oct/2009    */
+/******************************* */
+
+#ifndef __RSBAC_RC_H
+#define __RSBAC_RC_H
+
+#include <linux/init.h>
+#include <rsbac/rc_types.h>
+
+/***************************************************/
+/*               General Prototypes                */
+/***************************************************/
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+/****************************************************************************/
+/* Initialization, including ACI restoration for all mounted devices from   */
+/* disk. After this call, all ACI is kept in memory for performance reasons.*/
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_rc(void);
+#else
+int rsbac_init_rc(void) __init;
+#endif
+
+/* Find the boot role */
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_rc_get_boot_role(rsbac_rc_role_id_t * role_p);
+#else
+int rsbac_rc_get_boot_role(rsbac_rc_role_id_t * role_p) __init;
+#endif
+
+/* Some information about the current status is also available              */
+
+int rsbac_stats_rc(void);
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the spinlocks to protect the targets during  */
+/* access.                                                                  */
+
+/* All roles are always there, so instead of creation, we supply a copy for */
+/* initialization. There is always the well-defined role general to copy    */
+int rsbac_rc_copy_role(rsbac_list_ta_number_t ta_number,
+		       rsbac_rc_role_id_t from_role,
+		       rsbac_rc_role_id_t to_role);
+
+int rsbac_rc_copy_type(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_rc_target_t target,
+		       rsbac_rc_type_id_t from_type,
+		       rsbac_rc_type_id_t to_type);
+
+/* Getting item values */
+int rsbac_rc_get_item(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_rc_target_t target,
+		      union rsbac_rc_target_id_t tid,
+		      union rsbac_rc_target_id_t subtid,
+		      enum rsbac_rc_item_t item,
+		      union rsbac_rc_item_value_t *value_p,
+		      rsbac_time_t * ttl_p);
+
+/* Setting item values */
+int rsbac_rc_set_item(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_rc_target_t target,
+		      union rsbac_rc_target_id_t tid,
+		      union rsbac_rc_target_id_t subtid,
+		      enum rsbac_rc_item_t item,
+		      union rsbac_rc_item_value_t value, rsbac_time_t ttl);
+
+/* Checking role's compatibility */
+rsbac_boolean_t rsbac_rc_check_comp(rsbac_rc_role_id_t role,
+				    union rsbac_rc_target_id_t subtid,
+				    enum rsbac_rc_item_t item,
+				    enum rsbac_rc_special_rights_t right);
+
+/* Checking whether role exists */
+rsbac_boolean_t rsbac_rc_role_exists(rsbac_list_ta_number_t ta_number,
+				     rsbac_rc_role_id_t role);
+
+rsbac_boolean_t rsbac_rc_type_exists(rsbac_list_ta_number_t ta_number,
+				     enum rsbac_target_t target,
+				     rsbac_rc_type_id_t type);
+
+/* Get list of defined items. Returns number or negative error.
+ * Allocates array via rsbac_kmalloc, if number > 0 - rsbac_kfree after use! */
+int rsbac_rc_get_list(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_rc_target_t target,
+		      union rsbac_rc_target_id_t tid,
+		      enum rsbac_rc_item_t item,
+		      __u32 ** array_pp, rsbac_time_t ** ttl_array_pp);
+
+int rsbac_rc_select_fd_create_type(rsbac_rc_type_id_t type);
+
+#endif
diff --git a/include/rsbac/rc_data_structures.h b/include/rsbac/rc_data_structures.h
new file mode 100644
index 0000000..022497d
--- /dev/null
+++ b/include/rsbac/rc_data_structures.h
@@ -0,0 +1,352 @@
+/*********************************/
+/* Rule Set Based Access Control */
+/* Author and (c) 1999-2016:     */
+/*   Amon Ott <ao@rsbac.org>     */
+/* Data structures for Role      */
+/* Compatibility module          */
+/* Last modified: 07/Jan/2016    */
+/*********************************/
+
+
+#ifndef __RSBAC_RC_DATA_STRUC_H
+#define __RSBAC_RC_DATA_STRUC_H
+
+#ifdef __KERNEL__		/* only include in kernel code */
+#include <linux/types.h>
+#include <rsbac/types.h>
+#endif				/* __KERNEL__ */
+
+/* First of all we define dirname and filenames for saving the roles to disk. */
+/* The path must be a valid single dir name! Each mounted device gets its    */
+/* own file set, residing in 'DEVICE_ROOT/RSBAC_ACI_PATH/'.                  */
+/* All user access to these files will be denied.                            */
+/* Backups are kept in FILENAMEb.                                            */
+
+#ifdef __KERNEL__
+#define RSBAC_RC_LIST_KEY 77788855
+
+#define RSBAC_RC_NR_ROLE_LIST_HASH_BITS 2
+#define RSBAC_RC_NR_TYPE_LIST_HASH_BITS 2
+
+/* roles */
+#define RSBAC_RC_ROLE_FILENAME "rc_r"
+
+/* roles we are compatible with ( = we can change to) */
+#define RSBAC_RC_ROLE_RC_FILENAME "rc_rc"
+
+/* roles we may administrate (replaces admin_type) */
+#define RSBAC_RC_ROLE_ADR_FILENAME "rc_adr"
+
+/* roles we may read and assign to users, if they were in one of these before. */
+#define RSBAC_RC_ROLE_ASR_FILENAME "rc_asr"
+
+/* file/dir/fifo/symlink types for new items, by parent efftype */
+/* If not found, use old global value def_fd_create_type */
+#define RSBAC_RC_ROLE_DFDC_FILENAME "rc_dfdc"
+
+/* file/dir/fifo/symlink types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCFD_FILENAME "rc_tcfd"
+
+/* dev types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCDV_FILENAME "rc_tcdv"
+
+/* user types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCUS_FILENAME "rc_tcus"
+
+/* process types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCPR_FILENAME "rc_tcpr"
+
+/* IPC types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCIP_FILENAME "rc_tcip"
+
+/* SCD types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCSC_FILENAME "rc_tcsc"
+
+/* group types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCGR_FILENAME "rc_tcgr"
+
+/* NETDEV types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCND_FILENAME "rc_tcnd"
+
+/* NETTEMP types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCNT_FILENAME "rc_tcnt"
+
+/* NETOBJ types and requests we are compatible with */
+#define RSBAC_RC_ROLE_TCNO_FILENAME "rc_tcno"
+
+#define RSBAC_RC_ROLE_LIST_VERSION 5
+#define RSBAC_RC_ROLE_OLD_LIST_VERSION 4
+#define RSBAC_RC_ROLE_OLD_OLD_LIST_VERSION 3
+#define RSBAC_RC_ROLE_OLD_OLD_OLD_LIST_VERSION 2
+#define RSBAC_RC_ROLE_OLD_OLD_OLD_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_RC_LIST_VERSION 1
+#define RSBAC_RC_ROLE_ADR_LIST_VERSION 1
+#define RSBAC_RC_ROLE_ASR_LIST_VERSION 1
+#define RSBAC_RC_ROLE_DFDC_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCFD_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCDV_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCUS_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCPR_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCIP_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCSC_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCGR_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCND_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCNT_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCNO_LIST_VERSION 2
+#define RSBAC_RC_ROLE_TCFD_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCDV_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCUS_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCPR_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCIP_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCSC_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCGR_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCND_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCNT_OLD_LIST_VERSION 1
+#define RSBAC_RC_ROLE_TCNO_OLD_LIST_VERSION 1
+
+#define RSBAC_RC_TYPE_FD_FILENAME "rc_tfd"
+#define RSBAC_RC_TYPE_DEV_FILENAME "rc_tdv"
+#define RSBAC_RC_TYPE_IPC_FILENAME "rc_tip"
+#define RSBAC_RC_TYPE_USER_FILENAME "rc_tus"
+#define RSBAC_RC_TYPE_PROCESS_FILENAME "rc_tpr"
+#define RSBAC_RC_TYPE_GROUP_FILENAME "rc_tgr"
+#define RSBAC_RC_TYPE_NETDEV_FILENAME "rc_tnd"
+#define RSBAC_RC_TYPE_NETTEMP_FILENAME "rc_tnt"
+#define RSBAC_RC_TYPE_NETOBJ_FILENAME "rc_tno"
+
+#define RSBAC_RC_TYPE_FD_LIST_VERSION 1
+#define RSBAC_RC_TYPE_DEV_LIST_VERSION 1
+#define RSBAC_RC_TYPE_IPC_LIST_VERSION 1
+#define RSBAC_RC_TYPE_USER_LIST_VERSION 1
+#define RSBAC_RC_TYPE_PROCESS_LIST_VERSION 1
+#define RSBAC_RC_TYPE_GROUP_LIST_VERSION 1
+#define RSBAC_RC_TYPE_NETDEV_LIST_VERSION 1
+#define RSBAC_RC_TYPE_NETTEMP_LIST_VERSION 1
+#define RSBAC_RC_TYPE_NETOBJ_LIST_VERSION 1
+#endif				/* __KERNEL__ */
+
+/*
+ * The following structures provide the role model data structures.
+ * All RSBAC_RC_NR_ROLES roles and RSBAC_RC_NR_TYPES x target-no. types
+ * and SCD-type definitions are kept in arrays and saved to disk as such.
+ */
+
+/***************************************
+ *               Roles                 *
+ ***************************************/
+
+/* Caution: whenever role struct changes, version and old_version must be increased! */
+
+struct rsbac_rc_role_entry_t {
+	rsbac_enum_t admin_type;	/* role admin: none, system or role admin? */
+	char name[RSBAC_RC_NAME_LEN];
+	rsbac_rc_type_id_t def_fd_create_type;
+	rsbac_rc_type_id_t def_user_create_type;
+	rsbac_rc_type_id_t def_process_create_type;
+	rsbac_rc_type_id_t def_process_chown_type;
+	rsbac_rc_type_id_t def_process_execute_type;
+	rsbac_rc_type_id_t def_ipc_create_type;
+	rsbac_rc_type_id_t def_group_create_type;
+	rsbac_rc_type_id_t def_unixsock_create_type;
+	rsbac_enum_t boot_role;
+	rsbac_enum_t req_reauth;
+};
+
+struct rsbac_rc_old_role_entry_t {
+	rsbac_enum_t admin_type;	/* role admin: none, system or role admin? */
+	char name[RSBAC_RC_NAME_LEN];
+	rsbac_rc_type_id_t def_fd_create_type;
+	rsbac_rc_type_id_t def_user_create_type;
+	rsbac_rc_type_id_t def_process_create_type;
+	rsbac_rc_type_id_t def_process_chown_type;
+	rsbac_rc_type_id_t def_process_execute_type;
+	rsbac_rc_type_id_t def_ipc_create_type;
+	rsbac_rc_type_id_t def_group_create_type;
+	rsbac_enum_t boot_role;
+	rsbac_enum_t req_reauth;
+};
+
+struct rsbac_rc_old_old_role_entry_t {
+	rsbac_enum_t admin_type;	/* role admin: none, system or role admin? */
+	char name[RSBAC_RC_NAME_LEN];
+	rsbac_rc_type_id_t def_fd_create_type;
+	rsbac_rc_type_id_t def_user_create_type;
+	rsbac_rc_type_id_t def_process_create_type;
+	rsbac_rc_type_id_t def_process_chown_type;
+	rsbac_rc_type_id_t def_process_execute_type;
+	rsbac_rc_type_id_t def_ipc_create_type;
+	rsbac_rc_type_id_t def_group_create_type;
+	rsbac_enum_t boot_role;
+};
+
+struct rsbac_rc_old_old_old_role_entry_t {
+	rsbac_enum_t admin_type;	/* role admin: none, system or role admin? */
+	char name[RSBAC_RC_NAME_LEN];
+	rsbac_rc_type_id_t def_fd_create_type;
+	rsbac_rc_type_id_t def_user_create_type;
+	rsbac_rc_type_id_t def_process_create_type;
+	rsbac_rc_type_id_t def_process_chown_type;
+	rsbac_rc_type_id_t def_process_execute_type;
+	rsbac_rc_type_id_t def_ipc_create_type;
+	rsbac_enum_t boot_role;
+};
+
+struct rsbac_rc_old_old_old_old_role_entry_t {
+	rsbac_enum_t admin_type;	/* role admin: none, system or role admin? */
+	char name[RSBAC_RC_NAME_LEN];
+	rsbac_rc_type_id_t def_fd_create_type;
+	rsbac_rc_type_id_t def_process_create_type;
+	rsbac_rc_type_id_t def_process_chown_type;
+	rsbac_rc_type_id_t def_process_execute_type;
+	rsbac_rc_type_id_t def_ipc_create_type;
+};
+
+#define RSBAC_RC_NR_ROLE_ENTRY_ITEMS 25
+#define RSBAC_RC_ROLE_ENTRY_ITEM_LIST { \
+      RI_role_comp, \
+      RI_admin_roles, \
+      RI_assign_roles, \
+      RI_type_comp_fd, \
+      RI_type_comp_dev, \
+      RI_type_comp_user, \
+      RI_type_comp_process, \
+      RI_type_comp_ipc, \
+      RI_type_comp_scd, \
+      RI_type_comp_group, \
+      RI_type_comp_netdev, \
+      RI_type_comp_nettemp, \
+      RI_type_comp_netobj, \
+      RI_admin_type, \
+      RI_name, \
+      RI_def_fd_create_type, \
+      RI_def_fd_ind_create_type, \
+      RI_def_user_create_type, \
+      RI_def_process_create_type, \
+      RI_def_process_chown_type, \
+      RI_def_process_execute_type, \
+      RI_def_ipc_create_type, \
+      RI_def_group_create_type, \
+      RI_boot_role, \
+      RI_req_reauth \
+      }
+
+/***************************************
+ *             Type names              *
+ ***************************************/
+
+/* Caution: whenever role struct changes, version and old_version must be increased! */
+
+/* #define RSBAC_RC_OLD_TYPE_VERSION 1 */
+#define RSBAC_RC_TYPE_VERSION 1
+
+struct rsbac_rc_type_fd_entry_t {
+	char name[RSBAC_RC_NAME_LEN];
+	__u8 need_secdel;	/* rsbac_boolean_t */
+};
+
+#define RSBAC_RC_NR_TYPE_ENTRY_ITEMS 10
+#define RSBAC_RC_TYPE_ENTRY_ITEM_LIST { \
+      RI_type_fd_name, \
+      RI_type_dev_name, \
+      RI_type_ipc_name, \
+      RI_type_scd_name, \
+      RI_type_process_name, \
+      RI_type_group_name, \
+      RI_type_netdev_name, \
+      RI_type_nettemp_name, \
+      RI_type_netobj_name, \
+      RI_type_fd_need_secdel \
+      }
+
+/**********************************************/
+/*              Default values                */
+/**********************************************/
+
+#define RSBAC_RC_GENERAL_ROLE_ENTRY \
+    { \
+      .admin_type = RC_no_admin, \
+      .name = "General User", \
+      .def_fd_create_type = RC_type_inherit_parent, \
+      .def_user_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_process_create_type = RC_type_inherit_parent, \
+      .def_process_chown_type = RC_type_use_new_role_def_create, \
+      .def_process_execute_type = RC_type_inherit_parent, \
+      .def_ipc_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_group_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_unixsock_create_type = RC_type_use_fd, \
+      .boot_role = FALSE, \
+      .req_reauth = FALSE, \
+    }
+
+#define RSBAC_RC_ROLE_ADMIN_ROLE_ENTRY \
+    { \
+      .admin_type = RC_role_admin, \
+      .name = "Role Admin", \
+      .def_fd_create_type = RC_type_inherit_parent, \
+      .def_user_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_process_create_type = RC_type_inherit_parent, \
+      .def_process_chown_type = RC_type_use_new_role_def_create, \
+      .def_process_execute_type = RC_type_inherit_parent, \
+      .def_ipc_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_group_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_unixsock_create_type = RC_type_use_fd, \
+      .boot_role = FALSE, \
+      .req_reauth = FALSE, \
+    }
+
+#define RSBAC_RC_SYSTEM_ADMIN_ROLE_ENTRY \
+    { \
+      .admin_type = RC_system_admin, \
+      .name = "System Admin", \
+      .def_fd_create_type = RC_type_inherit_parent, \
+      .def_user_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_process_create_type = RC_type_inherit_parent, \
+      .def_process_chown_type = RC_type_use_new_role_def_create, \
+      .def_process_execute_type = RC_type_inherit_parent, \
+      .def_ipc_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_group_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_unixsock_create_type = RC_type_use_fd, \
+      .boot_role = FALSE, \
+      .req_reauth = FALSE, \
+    }
+
+#define RSBAC_RC_BOOT_ROLE_ENTRY \
+    { \
+      .admin_type = RC_no_admin, \
+      .name = "System Boot", \
+      .def_fd_create_type = RC_type_inherit_parent, \
+      .def_user_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_process_create_type = RC_type_inherit_parent, \
+      .def_process_chown_type = RC_type_use_new_role_def_create, \
+      .def_process_execute_type = RC_type_inherit_parent, \
+      .def_ipc_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_group_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_unixsock_create_type = RC_type_use_fd, \
+      .boot_role = TRUE, \
+      .req_reauth = FALSE, \
+    }
+
+#define RSBAC_RC_AUDITOR_ROLE_ENTRY \
+    { \
+      .admin_type = RC_no_admin, \
+      .name = "Auditor", \
+      .def_fd_create_type = RC_type_inherit_parent, \
+      .def_user_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_process_create_type = RC_type_inherit_parent, \
+      .def_process_chown_type = RC_type_use_new_role_def_create, \
+      .def_process_execute_type = RC_type_inherit_parent, \
+      .def_ipc_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_group_create_type = RSBAC_RC_GENERAL_TYPE, \
+      .def_unixsock_create_type = RC_type_use_fd, \
+      .boot_role = FALSE, \
+      .req_reauth = FALSE, \
+    }
+
+/**********************************************/
+/*              Declarations                  */
+/**********************************************/
+
+#ifdef __KERNEL__
+#endif				/* __KERNEL__ */
+
+#endif				/* __RSBAC_RC_DATA_STRUC_H */
diff --git a/include/rsbac/rc_getname.h b/include/rsbac/rc_getname.h
new file mode 100644
index 0000000..562fa20
--- /dev/null
+++ b/include/rsbac/rc_getname.h
@@ -0,0 +1,44 @@
+/******************************** */
+/* Rule Set Based Access Control  */
+/* Author and (c) 1999: Amon Ott  */
+/* Getname functions for RC parts */
+/* Last modified: 18/Jan/99       */
+/******************************** */
+
+#ifndef __RSBAC_RC_GETNAME_H
+#define __RSBAC_RC_GETNAME_H
+
+#include <rsbac/rc_types.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+char *get_rc_target_name(char *name, enum rsbac_rc_target_t value);
+
+enum rsbac_rc_target_t get_rc_target_nr(const char *name);
+
+char *get_rc_admin_name(char *name, enum rsbac_rc_admin_type_t value);
+
+enum rsbac_rc_admin_type_t get_rc_admin_nr(const char *name);
+
+char *get_rc_scd_type_name(char *name, enum rsbac_rc_scd_type_t value);
+
+enum rsbac_rc_scd_type_t get_rc_scd_type_nr(const char *name);
+
+char *get_rc_item_name(char *name, enum rsbac_rc_item_t value);
+
+enum rsbac_rc_item_t get_rc_item_nr(const char *name);
+
+#ifndef __KERNEL__
+char *get_rc_item_param(char *name, enum rsbac_rc_item_t value);
+#endif
+
+char *get_rc_special_right_name(char *name,
+				enum rsbac_rc_special_rights_t value);
+
+#ifndef __KERNEL__
+enum rsbac_rc_special_rights_t get_rc_special_right_nr(const char *name);
+#endif
+
+#endif
diff --git a/include/rsbac/rc_types.h b/include/rsbac/rc_types.h
new file mode 100644
index 0000000..29b1855
--- /dev/null
+++ b/include/rsbac/rc_types.h
@@ -0,0 +1,387 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016: Amon Ott */
+/* API: Data types for                */
+/*    Role Compatibility Module       */
+/* Last modified: 17/Feb/2016         */
+/************************************ */
+
+#ifndef __RSBAC_RC_TYPES_H
+#define __RSBAC_RC_TYPES_H
+
+#include <linux/types.h>
+
+/***** RC *****/
+
+#define RSBAC_RC_GENERAL_ROLE 0
+#define RSBAC_RC_ROLE_ADMIN_ROLE 1
+#define RSBAC_RC_SYSTEM_ADMIN_ROLE 2
+#define RSBAC_RC_AUDITOR_ROLE 3
+#define RSBAC_RC_BOOT_ROLE 999999
+#define RSBAC_RC_GENERAL_TYPE 0
+#define RSBAC_RC_SEC_TYPE 1
+#define RSBAC_RC_SYS_TYPE 2
+#define RSBAC_RC_KERNEL_P_TYPE 999999
+
+#define RSBAC_RC_NAME_LEN 16
+#define RSBAC_RC_ALL_REQUESTS ((rsbac_rc_request_vector_t) -1)
+
+#define RSBAC_RC_OLD_SPECIAL_RIGHT_BASE 48
+#define RSBAC_RC_SPECIAL_RIGHT_BASE 56
+
+enum rsbac_rc_special_rights_t { RCR_ADMIN = RSBAC_RC_SPECIAL_RIGHT_BASE,
+	RCR_ASSIGN,
+	RCR_ACCESS_CONTROL,
+	RCR_SUPERVISOR,
+	RCR_MODIFY_AUTH,
+	RCR_CHANGE_AUTHED_OWNER,
+	RCR_SELECT,
+	RCR_MODIFY_UDF,
+	RCR_NONE
+};
+
+typedef __u64 rsbac_rc_rights_vector_t;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_rc_rights_vector_ia32_t;
+#endif
+
+/* backwards compatibility only! */
+typedef __u64 rsbac_rc_role_vector_t;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_rc_role_vector_ia32_t;
+#endif
+
+#define RSBAC_RC_RIGHTS_VECTOR(x) ((rsbac_rc_rights_vector_t) 1 << (x))
+#define RSBAC_RC_ROLE_VECTOR(x) ((rsbac_rc_role_vector_t) 1 << (x))
+#define RSBAC_RC_TYPE_VECTOR(x) ((rsbac_rc_type_vector_t) 1 << (x))
+
+#define RSBAC_RC_SPECIAL_RIGHTS_VECTOR (\
+  RSBAC_RC_RIGHTS_VECTOR(RCR_ADMIN) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_ASSIGN) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_ACCESS_CONTROL) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_SUPERVISOR) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_MODIFY_AUTH) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_CHANGE_AUTHED_OWNER) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_SELECT) | \
+  RSBAC_RC_RIGHTS_VECTOR(RCR_MODIFY_UDF) \
+  )
+
+#define RSBAC_RC_SUPERVISOR_RIGHT_VECTOR (\
+    RSBAC_RC_RIGHTS_VECTOR(RCR_SUPERVISOR) | \
+  )
+
+#define RSBAC_RC_ALL_RIGHTS_VECTOR (RSBAC_ALL_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR)
+
+#define RSBAC_RC_PROCESS_RIGHTS_VECTOR (RSBAC_PROCESS_REQUEST_VECTOR | \
+  RSBAC_RC_RIGHTS_VECTOR(R_CONNECT) | \
+  RSBAC_RC_RIGHTS_VECTOR(R_ACCEPT) | \
+  RSBAC_RC_RIGHTS_VECTOR(R_SEND) | \
+  RSBAC_RC_RIGHTS_VECTOR(R_RECEIVE) \
+)
+
+#define RSBAC_RC_DEFAULT_RIGHTS_VECTOR 0
+
+#define RSBAC_RC_GEN_RIGHTS_VECTOR RSBAC_RC_DEFAULT_RIGHTS_VECTOR
+
+typedef __u32 rsbac_rc_role_id_t;
+typedef __u32 rsbac_rc_type_id_t;
+typedef rsbac_request_vector_t rsbac_rc_request_vector_t;
+
+enum rsbac_rc_admin_type_t { RC_no_admin, RC_role_admin, RC_system_admin,
+	    RC_none };
+
+/*
+ * System Control Types, including general SCD types
+ * (start at 32 to allow future SCD types, max is 63)
+ */
+#define RST_min 32
+enum rsbac_rc_scd_type_t { RST_auth_administration = RST_min,
+	RST_udf_administration,
+	RST_none
+};
+
+/* what should always be there to keep system functional */
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+#define RSBAC_RC_GENERAL_COMP_SCD { \
+                          0, \
+                          0, \
+                          0, \
+                          0, \
+         /* ST_ioports */ ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA), \
+         /* ST_rlimit */ RSBAC_REQUEST_VECTOR(GET_STATUS_DATA) | RSBAC_REQUEST_VECTOR(MODIFY_SYSTEM_DATA), \
+         /* ST_swap */              0, \
+         /* ST_syslog */            0, \
+         /* ST_rsbac */             0, \
+         /* ST_rsbac_log */         0, \
+         /* ST_other */             ( \
+                                       ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+                                    ), \
+         /* ST_kmem */              0, \
+         /* ST_network */           ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA), \
+         /* 13 = ST_none */         0 \
+          }
+#else
+#define RSBAC_RC_GENERAL_COMP_SCD { \
+                          0, \
+                          0, \
+                          0, \
+                          0, \
+                          0, \
+         /* ST_rlimit */ RSBAC_REQUEST_VECTOR(GET_STATUS_DATA) | RSBAC_REQUEST_VECTOR(MODIFY_SYSTEM_DATA), \
+         /* ST_swap */              0, \
+         /* ST_syslog */            0, \
+         /* ST_rsbac */             0, \
+         /* ST_rsbac_log */         0, \
+         /* ST_other */             ( \
+                                       ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+                                    ), \
+         /* ST_kmem */              0, \
+         /* ST_network */           ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA), \
+         /* ST_firewall */          0, \
+         /* ST_priority */          0, \
+         /* 15 = ST_none */         0 \
+          }
+#endif
+
+#define RSBAC_RC_ROLEADM_COMP_SCD { \
+         /* 0 = ST_time_structs */  0, \
+         /* ST_clock */             0, \
+         /* ST_host_id */           0, \
+         /* ST_net_id */            0, \
+         /* ST_ioports */           0, \
+         /* ST_rlimit */            RSBAC_SCD_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* ST_swap */              0, \
+         /* ST_syslog */            0, \
+         /* ST_rsbac */             RSBAC_SCD_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* ST_rsbac_log */         RSBAC_SCD_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* ST_other */             ( \
+                                       ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+                                     | ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+                                     | ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) \
+                                     | ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) \
+                                     | ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) \
+                                    ) | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* ST_kmem */              0, \
+         /* ST_network */           ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* ST_firewall */          ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* ST_nice */              0, \
+         /* 15 = ST_none */         0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+         /* 20 */                   0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+         /* 30 */                   0, \
+                                    0, \
+         /* 32 = RST_auth_admin */  RSBAC_SCD_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* 33 = RST_udf_admin */   RSBAC_SCD_REQUEST_VECTOR | RSBAC_RC_SPECIAL_RIGHTS_VECTOR, \
+         /* 34 = RST_none */        0 \
+          }
+
+#define RSBAC_RC_SYSADM_COMP_SCD { \
+         /* 0 = ST_time_structs */  RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_clock */             RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_host_id */           RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_net_id */            RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_ioports */           RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_rlimit */            RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_swap */              RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_syslog */            RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_rsbac */             RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_rsbac_log */         0, \
+         /* ST_other */             ( \
+                                       ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) \
+                                     | ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) \
+                                     | ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+                                     | ((rsbac_request_vector_t) 1 << R_MOUNT) \
+                                     | ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) \
+                                     | ((rsbac_request_vector_t) 1 << R_UMOUNT) \
+                                     | ((rsbac_request_vector_t) 1 << R_SHUTDOWN) \
+                                    ), \
+         /* ST_kmem */              RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_network */           RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_firewall */          RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* ST_priority */          RSBAC_SCD_REQUEST_VECTOR & RSBAC_SYSTEM_REQUEST_VECTOR, \
+         /* 15 = ST_none */         0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+         /* 20 */                   0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+                                    0, \
+         /* 30 */                   0, \
+                                    0, \
+         /* 32 = RST_auth_admin */  0, \
+         /* 33 = RST_udf_admin */   0, \
+         /* 34 = RST_none */        0 \
+          }
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+#define RSBAC_RC_AUDITOR_COMP_SCD { \
+                          0, \
+                          0, \
+                          0, \
+                          0, \
+         /* ST_ioports */ ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA), \
+         /* ST_rlimit */  RSBAC_REQUEST_VECTOR(GET_STATUS_DATA) | RSBAC_REQUEST_VECTOR(MODIFY_SYSTEM_DATA), \
+         /* ST_swap */              0, \
+         /* ST_syslog */            0, \
+         /* ST_rsbac */             0, \
+         /* ST_rsbac_log */         ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA), \
+         /* ST_other */             ( \
+                                       ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+                                    ), \
+         /* ST_kmem */              0, \
+         /* ST_network */           ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA), \
+         /* ST_firewall */          0, \
+         /* ST_priority */          0, \
+         /* 15 = ST_none */         0 \
+          }
+#else
+#define RSBAC_RC_AUDITOR_COMP_SCD { \
+                          0, \
+                          0, \
+                          0, \
+                          0, \
+                          0, \
+         /* ST_rlimit */  RSBAC_REQUEST_VECTOR(GET_STATUS_DATA) | RSBAC_REQUEST_VECTOR(MODIFY_SYSTEM_DATA), \
+         /* ST_swap */              0, \
+         /* ST_syslog */            0, \
+         /* ST_rsbac */             0, \
+         /* ST_rsbac_log */         ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA), \
+         /* ST_other */             ( \
+                                       ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+                                    ), \
+         /* ST_kmem */              0, \
+         /* ST_network */           ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA), \
+         /* ST_firewall */          0, \
+         /* ST_priority */          0, \
+         /* 15 = ST_none */         0 \
+          }
+#endif
+
+
+#define RC_type_inherit_process ((rsbac_rc_type_id_t) -1)
+#define RC_type_inherit_parent ((rsbac_rc_type_id_t) -2)
+#define RC_type_no_create ((rsbac_rc_type_id_t) -3)
+#define RC_type_no_execute ((rsbac_rc_type_id_t) -4)
+#define RC_type_use_new_role_def_create ((rsbac_rc_type_id_t) -5)	/* for process chown (setuid) */
+#define RC_type_no_chown ((rsbac_rc_type_id_t) -6)
+#define RC_type_use_fd ((rsbac_rc_type_id_t) -7)
+#define RC_type_min_special ((rsbac_rc_type_id_t) -7)
+#define RC_type_max_value ((rsbac_rc_type_id_t) -32)
+
+#define RC_role_inherit_user ((rsbac_rc_role_id_t) -1)
+#define RC_role_inherit_process ((rsbac_rc_role_id_t) -2)
+#define RC_role_inherit_parent ((rsbac_rc_role_id_t) -3)
+#define RC_role_inherit_up_mixed ((rsbac_rc_role_id_t) -4)
+#define RC_role_use_force_role ((rsbac_rc_role_id_t) -5)
+#define RC_role_min_special ((rsbac_rc_role_id_t) -5)
+#define RC_role_max_value ((rsbac_rc_role_id_t) -32)
+
+#define RC_default_force_role RC_role_inherit_parent
+#define RC_default_root_dir_force_role RC_role_inherit_up_mixed
+#define RC_default_init_force_role RC_role_inherit_user
+#define RC_default_initial_role RC_role_inherit_parent
+#define RC_default_root_dir_initial_role RC_role_use_force_role
+
+/****************************************************************************/
+/* RC ACI types                                                             */
+/****************************************************************************/
+
+enum rsbac_rc_target_t { RT_ROLE, RT_TYPE, RT_NONE };
+
+union rsbac_rc_target_id_t {
+	rsbac_rc_role_id_t role;
+	rsbac_rc_type_id_t type;
+};
+
+enum rsbac_rc_item_t { RI_role_comp,
+	RI_admin_roles,
+	RI_assign_roles,
+	RI_type_comp_fd,
+	RI_type_comp_dev,
+	RI_type_comp_user,
+	RI_type_comp_process,
+	RI_type_comp_ipc,
+	RI_type_comp_scd,
+	RI_type_comp_group,
+	RI_type_comp_netdev,
+	RI_type_comp_nettemp,
+	RI_type_comp_netobj,
+	RI_admin_type,
+	RI_name,
+	RI_def_fd_create_type,
+	RI_def_fd_ind_create_type,
+	RI_def_user_create_type,
+	RI_def_process_create_type,
+	RI_def_process_chown_type,
+	RI_def_process_execute_type,
+	RI_def_ipc_create_type,
+	RI_def_group_create_type,
+	RI_def_unixsock_create_type,
+	RI_boot_role,
+	RI_req_reauth,
+	RI_type_fd_name,
+	RI_type_dev_name,
+	RI_type_ipc_name,
+	RI_type_user_name,
+	RI_type_process_name,
+	RI_type_group_name,
+	RI_type_netdev_name,
+	RI_type_nettemp_name,
+	RI_type_netobj_name,
+	RI_type_fd_need_secdel,
+	RI_type_scd_name,	/* Pseudo, using get_rc_scd_name() */
+	RI_remove_role,
+	RI_def_fd_ind_create_type_remove,
+	RI_type_fd_remove,
+	RI_type_dev_remove,
+	RI_type_ipc_remove,
+	RI_type_user_remove,
+	RI_type_process_remove,
+	RI_type_group_remove,
+	RI_type_netdev_remove,
+	RI_type_nettemp_remove,
+	RI_type_netobj_remove,
+#ifdef __KERNEL__
+#endif
+	RI_none
+};
+
+union rsbac_rc_item_value_t {
+	rsbac_rc_rights_vector_t rights;
+	enum rsbac_rc_admin_type_t admin_type;
+	char name[RSBAC_RC_NAME_LEN];
+	rsbac_rc_role_id_t role_id;
+	rsbac_rc_type_id_t type_id;
+	rsbac_boolean_t need_secdel;
+	rsbac_boolean_t comp;
+	rsbac_boolean_t boot_role;
+	rsbac_boolean_t req_reauth;
+#ifdef __KERNEL__
+#endif
+	u_char u_char_dummy;
+	int dummy;
+	u_int u_dummy;
+	long long_dummy;
+	long long long_long_dummy;
+};
+
+#endif
diff --git a/include/rsbac/reg.h b/include/rsbac/reg.h
new file mode 100644
index 0000000..cd276a5
--- /dev/null
+++ b/include/rsbac/reg.h
@@ -0,0 +1,152 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2012: Amon Ott */
+/* API: for REG                       */
+/*      Module Registration           */
+/* Last modified: 07/May/2012         */
+/************************************ */
+
+#ifndef __RSBAC_REG_H
+#define __RSBAC_REG_H
+
+#include <rsbac/types.h>
+#include <rsbac/debug.h>
+
+#define RSBAC_REG_VERSION 1
+
+/***************************************************/
+/*                   Types                         */
+/***************************************************/
+
+#define RSBAC_REG_NAME_LEN 30
+
+/* Decision function */
+typedef \
+  int rsbac_reg_request_func_t     ( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+/* Attribute setting / notification function */
+typedef \
+  int rsbac_reg_set_attr_func_t    ( enum  rsbac_adf_request_t,
+                                           rsbac_pid_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_target_t,
+                                     union rsbac_target_id_t,
+                                     enum  rsbac_attribute_t,
+                                     union rsbac_attribute_value_t,
+                                           rsbac_uid_t); /* process owner */
+
+/* Whether module wants this file to be overwritten on delete / truncate */
+typedef rsbac_boolean_t rsbac_reg_need_overwrite_func_t(struct dentry * dentry_p);
+
+/*
+ * rsbac_reg_write_func_t
+ *
+ * Called by rsbac_write function to save all dirty lists, must return number
+ * of files written or negative error. If auto_write is active, this function
+ * will be called regularly and allows for asynchronous data writing to disk.
+ *
+ * If need_lock is TRUE, a lock_kernel() / unlock_kernel() pair must be used
+ * around the write function.
+ */
+typedef int rsbac_reg_write_func_t(rsbac_boolean_t need_lock);
+
+/* Called on every mount, allows updating of fs based data */
+typedef int rsbac_reg_mount_func_t(kdev_t kdev);
+
+/* Called on every umount, allows updating of fs based data */
+typedef int rsbac_reg_umount_func_t(kdev_t kdev);
+
+/* Called on rsbac_reg syscalls for handle syscall_handle */
+/* Generic Syscall interface - note: data is a user space pointer! */
+typedef int rsbac_reg_syscall_func_t(void __user * data);
+
+/* Status and data structures integrity checking, called from sys_rsbac_check */
+/* correct: if TRUE, errors are corrected, else just report */
+/* check_inode: for inode number based data, check, if inode still exists */
+typedef int rsbac_reg_check_func_t(int correct, int check_inode);
+
+/*********/
+
+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;
+    rsbac_reg_check_func_t          * check_func;
+    rsbac_boolean_t                           switch_on; /* turned on initially? */
+  };
+
+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;
+  };
+
+/***************************************************/
+/*                   Prototypes                    */
+/***************************************************/
+
+/* See rsbac/types.h for types */
+
+/*
+ * Register an ADF decision module
+ * Returns given positive handle or negative error code from rsbac/error.h
+ * Errors: -RSBAC_EINVALIDVALUE    (all functions are empty or handle is not positive)
+ *         -RSBAC_EEXISTS          (handle exists - choose another one)
+ *         -RSBAC_ECOULDNOTADDITEM (no entry available)
+ *         -RSBAC_EINVALIDVERSION  (wrong REG version)
+ */
+
+rsbac_reg_handle_t rsbac_reg_register(        rsbac_version_t    version,
+                                       struct rsbac_reg_entry_t  entry);
+
+/*
+ * Switch module on or off - for 'normal' modules this is done by general
+ * function. This is a dummy, if module switching is disabled.
+ * Returns 0 on success or -EINVALIDTARGET, if handle is invalid.
+ */
+
+int rsbac_reg_switch (rsbac_reg_handle_t handle, rsbac_boolean_t value);
+
+/*
+ * Unregister an ADF decision module
+ * Returns 0 on success or -EINVALIDTARGET, if handle is invalid.
+ */
+
+int rsbac_reg_unregister(rsbac_reg_handle_t handle);
+
+
+/*
+ * Register a system call
+ * Returns given positive handle or negative error code from rsbac/error.h
+ * Errors: -RSBAC_EINVALIDVALUE    (function is empty or handle is not positive)
+ *         -RSBAC_EEXISTS          (handle exists - choose another one)
+ *         -RSBAC_ECOULDNOTADDITEM (no entry available)
+ *         -RSBAC_EINVALIDVERSION  (wrong REG version)
+ */
+
+rsbac_reg_handle_t rsbac_reg_register_syscall(       rsbac_version_t            version,
+                                              struct rsbac_reg_syscall_entry_t  entry);
+
+/*
+ * Unregister a system call
+ * Returns 0 on success or -EINVALIDTARGET, if handle is invalid.
+ */
+
+int rsbac_reg_unregister_syscall(rsbac_reg_handle_t handle);
+
+#endif
diff --git a/include/rsbac/reg_main.h b/include/rsbac/reg_main.h
new file mode 100644
index 0000000..c6fe1c4
--- /dev/null
+++ b/include/rsbac/reg_main.h
@@ -0,0 +1,70 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2005: Amon Ott */
+/* REG - Module Registration          */
+/* Internal declarations and types    */
+/* Last modified: 22/Jul/2005         */
+/************************************ */
+
+#ifndef __RSBAC_REG_MAIN_H
+#define __RSBAC_REG_MAIN_H
+
+#include <rsbac/types.h>
+#include <rsbac/debug.h>
+#include <rsbac/reg.h>
+
+#define RSBAC_REG_PROC_NAME "reg_entries"
+
+/***************************************************/
+/*                   Types                         */
+/***************************************************/
+
+#ifdef __KERNEL__
+
+/* Since all registrations will be organized in double linked lists, we must  */
+/* have list items and a list head.                                        */
+
+struct rsbac_reg_list_item_t
+    {
+      struct rsbac_reg_entry_t       entry;
+      struct rsbac_reg_list_item_t * prev;
+      struct rsbac_reg_list_item_t * next;
+    };
+    
+struct rsbac_reg_sc_list_item_t
+    {
+      struct rsbac_reg_syscall_entry_t  entry;
+      struct rsbac_reg_sc_list_item_t * prev;
+      struct rsbac_reg_sc_list_item_t * next;
+    };
+    
+/* To provide consistency we use spinlocks for all list accesses. The     */
+/* 'curr' entry is used to avoid repeated lookups for the same item.       */    
+    
+struct rsbac_reg_list_head_t
+    {
+      struct rsbac_reg_list_item_t * head;
+      struct rsbac_reg_list_item_t * tail;
+      struct rsbac_reg_list_item_t * curr;
+      spinlock_t                     lock;
+      int                            readers;
+      u_int                          count;
+    };
+
+struct rsbac_reg_sc_list_head_t
+    {
+      struct rsbac_reg_sc_list_item_t * head;
+      struct rsbac_reg_sc_list_item_t * tail;
+      struct rsbac_reg_sc_list_item_t * curr;
+      spinlock_t                        lock;
+      int                               readers;
+      u_int                             count;
+    };
+
+#endif /* __KERNEL__ */
+
+/***************************************************/
+/*                   Prototypes                    */
+/***************************************************/
+
+#endif
diff --git a/include/rsbac/repl_lists.h b/include/rsbac/repl_lists.h
new file mode 100644
index 0000000..a377685
--- /dev/null
+++ b/include/rsbac/repl_lists.h
@@ -0,0 +1,18 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Author and (c) 1999-2005: Amon Ott <ao@rsbac.org> */
+/* Generic lists - internal structures               */
+/* Last modified: 04/Apr/2005                        */
+/*************************************************** */
+
+#ifndef __RSBAC_REPL_LISTS_H
+#define __RSBAC_REPL_LISTS_H
+
+#include <rsbac/repl_types.h>
+
+#define RSBAC_LIST_REPL_PROC_NAME "repl_lists"
+#define RSBAC_LIST_REPL_PARTNER_VERSION 1
+#define RSBAC_LIST_REPL_PARTNER_KEY 0x3632f7ae
+#define RSBAC_LIST_REPL_PARTNER_FILENAME "replpar"
+
+#endif
diff --git a/include/rsbac/repl_types.h b/include/rsbac/repl_types.h
new file mode 100644
index 0000000..860d258
--- /dev/null
+++ b/include/rsbac/repl_types.h
@@ -0,0 +1,28 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Author and (c) 1999-2005: Amon Ott <ao@rsbac.org> */
+/* Generic lists - internal structures               */
+/* Last modified: 04/Apr/2005                        */
+/*************************************************** */
+
+#ifndef __RSBAC_REPL_TYPES_H
+#define __RSBAC_REPL_TYPES_H
+
+#include <rsbac/types.h>
+
+#define RSBAC_LIST_REPL_NAME_LEN 16
+#define RSBAC_LIST_REPL_CRYPTKEY_LEN 256
+#define RSBAC_LIST_REPL_CRYPTALGO_LEN 64
+
+typedef __u32 rsbac_list_repl_partner_number_t;
+
+struct rsbac_list_repl_partner_entry_t
+  {
+    char          name[RSBAC_LIST_REPL_NAME_LEN];
+    __u32         ip_addr;
+    char          crypt_algo[RSBAC_LIST_REPL_CRYPTALGO_LEN];
+    char          crypt_key[RSBAC_LIST_REPL_CRYPTKEY_LEN];
+    __u32         crypt_key_len;
+  };
+
+#endif
diff --git a/include/rsbac/request_groups.h b/include/rsbac/request_groups.h
new file mode 100644
index 0000000..3812f5e
--- /dev/null
+++ b/include/rsbac/request_groups.h
@@ -0,0 +1,426 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2010: Amon Ott */
+/* Groups of ADF request for          */
+/* administration                     */
+/* Last modified: 08/Apr/2010         */
+/************************************ */
+
+#ifndef __RSBAC_REQUEST_GROUPS_H
+#define __RSBAC_REQUEST_GROUPS_H
+
+#define RSBAC_READ_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_TERMINATE) | \
+  ((rsbac_request_vector_t) 1 << R_AUTHENTICATE) \
+  )
+
+#define RSBAC_WRITE_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) | \
+  ((rsbac_request_vector_t) 1 << R_LOCK) | \
+  ((rsbac_request_vector_t) 1 << R_MOVETO) \
+  )
+
+#define RSBAC_READ_WRITE_REQUEST_VECTOR (\
+  RSBAC_READ_REQUEST_VECTOR | \
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) | \
+  ((rsbac_request_vector_t) 1 << R_NET_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) | \
+  ((rsbac_request_vector_t) 1 << R_LOCK) | \
+  ((rsbac_request_vector_t) 1 << R_MOVETO) \
+  )
+
+#define RSBAC_READ_WRITE_OPEN_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) \
+  )
+
+#define RSBAC_EXECUTE_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+  )
+
+
+#define RSBAC_SYSTEM_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) \
+  )
+
+#define RSBAC_SECURITY_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) \
+  )
+
+#define RSBAC_FD_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) | \
+  ((rsbac_request_vector_t) 1 << R_NET_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) | \
+  ((rsbac_request_vector_t) 1 << R_LOCK) | \
+  ((rsbac_request_vector_t) 1 << R_MOVETO) \
+  )
+
+#define RSBAC_DEV_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) \
+  )
+
+#define RSBAC_IPC_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_NET_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) | \
+  ((rsbac_request_vector_t) 1 << R_LOCK) \
+  )
+
+#define RSBAC_SCD_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) \
+  )
+
+#define RSBAC_USER_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_AUTHENTICATE) \
+  )
+
+#define RSBAC_GROUP_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) \
+  )
+
+#define RSBAC_PROCESS_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_TERMINATE) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) \
+  )
+
+#define RSBAC_NETDEV_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) \
+  )
+
+#define RSBAC_NETTEMP_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) \
+  )
+
+#define RSBAC_NETOBJ_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_NET_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) \
+  )
+
+#define RSBAC_NONE_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) \
+  )
+
+#define RSBAC_ALL_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ADD_TO_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CLONE) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) | \
+  ((rsbac_request_vector_t) 1 << R_DELETE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_SYSTEM_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_READ_ATTRIBUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_READ_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_REMOVE_FROM_KERNEL) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) | \
+  ((rsbac_request_vector_t) 1 << R_SEND_SIGNAL) | \
+  ((rsbac_request_vector_t) 1 << R_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_LOG) | \
+  ((rsbac_request_vector_t) 1 << R_SWITCH_MODULE) | \
+  ((rsbac_request_vector_t) 1 << R_TERMINATE) | \
+  ((rsbac_request_vector_t) 1 << R_TRACE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_UMOUNT) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_MAP_EXEC) | \
+  ((rsbac_request_vector_t) 1 << R_BIND) | \
+  ((rsbac_request_vector_t) 1 << R_LISTEN) | \
+  ((rsbac_request_vector_t) 1 << R_ACCEPT) | \
+  ((rsbac_request_vector_t) 1 << R_CONNECT) | \
+  ((rsbac_request_vector_t) 1 << R_SEND) | \
+  ((rsbac_request_vector_t) 1 << R_RECEIVE) | \
+  ((rsbac_request_vector_t) 1 << R_NET_SHUTDOWN) | \
+  ((rsbac_request_vector_t) 1 << R_IOCTL) | \
+  ((rsbac_request_vector_t) 1 << R_LOCK) | \
+  ((rsbac_request_vector_t) 1 << R_MOVETO) \
+  )
+
+/* NW specials */
+
+/* NWS == RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR in ACL types */
+
+#define RSBAC_NWR_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_EXECUTE) | \
+  ((rsbac_request_vector_t) 1 << R_READ_OPEN) \
+  )
+
+#define RSBAC_NWW_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_ALTER) | \
+  ((rsbac_request_vector_t) 1 << R_APPEND_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_TRUNCATE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE) | \
+  ((rsbac_request_vector_t) 1 << R_WRITE_OPEN) | \
+  ((rsbac_request_vector_t) 1 << R_MOVETO) \
+  )
+
+#define RSBAC_NWC_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_CREATE) \
+  )
+
+#define RSBAC_NWE_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_DELETE) \
+  )
+
+/* NWA == RSBAC_ACL_ACCESS_CONTROL_RIGHT_VECTOR in ACL types */
+
+#define RSBAC_NWF_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHDIR) | \
+  ((rsbac_request_vector_t) 1 << R_CLOSE) | \
+  ((rsbac_request_vector_t) 1 << R_GET_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_GET_STATUS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_READ) | \
+  ((rsbac_request_vector_t) 1 << R_SEARCH) \
+  )
+
+#define RSBAC_NWM_REQUEST_VECTOR (\
+  ((rsbac_request_vector_t) 1 << R_CHANGE_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_GROUP) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_EFF_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_CHANGE_DAC_FS_OWNER) | \
+  ((rsbac_request_vector_t) 1 << R_LINK_HARD) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_ACCESS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_MODIFY_PERMISSIONS_DATA) | \
+  ((rsbac_request_vector_t) 1 << R_RENAME) \
+  )
+
+#endif
diff --git a/include/rsbac/res_getname.h b/include/rsbac/res_getname.h
new file mode 100644
index 0000000..37512ad
--- /dev/null
+++ b/include/rsbac/res_getname.h
@@ -0,0 +1,20 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 2002:             */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for RES module */
+/* Last modified: 22/Nov/2002       */
+/********************************** */
+
+#ifndef __RSBAC_RES_GETNAME_H
+#define __RSBAC_RES_GETNAME_H
+
+#include <rsbac/types.h>
+
+#ifndef __KERNEL__
+char * get_res_name(char * name,
+                    u_int value);
+int get_res_nr(const char * name);
+#endif
+
+#endif
diff --git a/include/rsbac/rkmem.h b/include/rsbac/rkmem.h
new file mode 100644
index 0000000..2aee7e0
--- /dev/null
+++ b/include/rsbac/rkmem.h
@@ -0,0 +1,76 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Author and (c) 1999-2015: Amon Ott <ao@rsbac.org> */
+/* Memory allocation                                 */
+/* Last modified: 19/Dec/2015                        */
+/*************************************************** */
+
+#ifndef __RSBAC_RKMEM_H
+#define __RSBAC_RKMEM_H
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+
+#define RSBAC_MAX_KMALLOC KMALLOC_MAX_SIZE
+#define RSBAC_MAX_SLABNAME 32
+
+/* alloc mem spinlock safe with GFP_ATOMIC */
+void * rsbac_kmalloc (size_t size);
+void * rsbac_kmalloc_clear (size_t size);
+
+/* alloc outside locks with GFP_KERNEL */
+void * rsbac_kmalloc_unlocked (size_t size);
+void * rsbac_kmalloc_clear_unlocked (size_t size);
+
+void rsbac_kfree (const void * objp);
+
+/* Separate slabs for RSBAC */
+
+/* name must stay available until after destroy, keep locally */
+static inline struct kmem_cache * rsbac_slab_create(
+	const char * name,
+	size_t size) {
+	return kmem_cache_create(name, size, 0, 0, NULL);
+}
+static inline struct kmem_cache * rsbac_slab_create_rcu(
+	const char * name,
+	size_t size) {
+	return kmem_cache_create(name, size, 0, SLAB_DESTROY_BY_RCU, NULL);
+}
+
+/* remember to free up name after calling, if it has been allocated */
+static inline void rsbac_slab_destroy(struct kmem_cache * cache)
+{
+	kmem_cache_destroy(cache);
+}
+
+static inline void * rsbac_smalloc(struct kmem_cache * cache)
+{
+	return kmem_cache_alloc(cache, GFP_ATOMIC);
+}
+
+static inline void * rsbac_smalloc_clear(struct kmem_cache * cache)
+{
+	return kmem_cache_alloc(cache, GFP_ATOMIC | __GFP_ZERO);
+}
+
+static inline void * rsbac_smalloc_unlocked(struct kmem_cache * cache)
+{
+	return kmem_cache_alloc(cache, GFP_KERNEL);
+}
+
+static inline void * rsbac_smalloc_clear_unlocked(struct kmem_cache * cache)
+{
+	return kmem_cache_alloc(cache, GFP_KERNEL | __GFP_ZERO);
+}
+
+static inline void rsbac_sfree(struct kmem_cache * cache, void * mem)
+{
+	if (cache)
+		kmem_cache_free(cache, mem);
+	else
+		rsbac_kfree(mem);
+}
+
+#endif
diff --git a/include/rsbac/syscall_rsbac.h b/include/rsbac/syscall_rsbac.h
new file mode 100644
index 0000000..8ceb81d
--- /dev/null
+++ b/include/rsbac/syscall_rsbac.h
@@ -0,0 +1,37 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/*                                    */
+/* Author and (c) 1999-2004:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/*                                    */
+/* System Calls                       */
+/*                                    */
+/* Last modified: 13/Apr/2004         */
+/************************************ */
+
+#ifndef __RSBAC_SYSCALL_RSBAC_H
+#define __RSBAC_SYSCALL_RSBAC_H
+
+/* to keep include/asm-alpha/unistd.h happy */
+//#define __LIBRARY__
+
+#include <linux/unistd.h>
+#include <rsbac/types.h>
+#include <rsbac/syscalls.h>
+
+#ifdef __PIC__
+#undef _syscall3
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+        type name(type1 arg1,type2 arg2,type3 arg3) \
+{\
+                return syscall(__NR_##name, arg1, arg2, arg3);\
+}
+#endif
+
+static inline _syscall3(int, rsbac,
+		rsbac_version_t, version,
+		enum rsbac_syscall_t, call,
+		union rsbac_syscall_arg_t *, arg_p);
+
+#define sys_rsbac(a,b,c) rsbac(a,b,c)
+#endif
diff --git a/include/rsbac/syscalls.h b/include/rsbac/syscalls.h
new file mode 100644
index 0000000..26dfe95
--- /dev/null
+++ b/include/rsbac/syscalls.h
@@ -0,0 +1,1858 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2016:           */
+/*   Amon Ott <ao@rsbac.org>           */
+/* Syscall wrapper functions for all   */
+/* parts                               */
+/* Last modified: 17/Feb/2016          */
+/************************************* */
+
+#ifndef __RSBAC_SYSCALLS_H
+#define __RSBAC_SYSCALLS_H
+
+#include <linux/unistd.h>
+#include <rsbac/types.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+#include <asm/compat.h>
+#endif
+
+enum rsbac_syscall_t
+  {
+    RSYS_version,
+    RSYS_stats,
+    RSYS_check,
+    RSYS_get_attr,
+    RSYS_get_attr_n,
+    RSYS_set_attr,
+    RSYS_set_attr_n,
+    RSYS_remove_target,
+    RSYS_remove_target_n,
+    RSYS_net_list_all_netdev,
+    RSYS_net_template,
+    RSYS_net_list_all_template,
+    RSYS_switch,
+    RSYS_get_switch,
+    RSYS_adf_log_switch,
+    RSYS_get_adf_log,
+    RSYS_write,
+    RSYS_log,
+    RSYS_mac_set_curr_level,
+    RSYS_mac_get_curr_level,
+    RSYS_mac_get_max_level,
+    RSYS_mac_get_min_level,
+    RSYS_mac_add_p_tru,
+    RSYS_mac_remove_p_tru,
+    RSYS_mac_add_f_tru,
+    RSYS_mac_remove_f_tru,
+    RSYS_mac_get_f_trulist,
+    RSYS_mac_get_p_trulist,
+    RSYS_stats_pm,
+    RSYS_pm,
+    RSYS_pm_change_current_task,
+    RSYS_pm_create_file,
+    RSYS_daz_flush_cache,
+    RSYS_rc_copy_role,
+    RSYS_rc_copy_type,
+    RSYS_rc_get_item,
+    RSYS_rc_set_item,
+    RSYS_rc_change_role,
+    RSYS_rc_get_eff_rights_n,
+    RSYS_rc_get_list,
+    RSYS_auth_add_p_cap,
+    RSYS_auth_remove_p_cap,
+    RSYS_auth_add_f_cap,
+    RSYS_auth_remove_f_cap,
+    RSYS_auth_get_f_caplist,
+    RSYS_auth_get_p_caplist,
+    RSYS_acl,
+    RSYS_acl_n,
+    RSYS_acl_get_rights,
+    RSYS_acl_get_rights_n,
+    RSYS_acl_get_tlist,
+    RSYS_acl_get_tlist_n,
+    RSYS_acl_get_mask,
+    RSYS_acl_get_mask_n,
+    RSYS_acl_group,
+    RSYS_reg,
+    RSYS_jail,
+    RSYS_init,
+    RSYS_rc_get_current_role,
+    RSYS_um_auth_name,
+    RSYS_um_auth_uid,
+    RSYS_um_add_user,
+    RSYS_um_add_group,
+    RSYS_um_add_gm,
+    RSYS_um_mod_user,
+    RSYS_um_mod_group,
+    RSYS_um_get_user_item,
+    RSYS_um_get_group_item,
+    RSYS_um_remove_user,
+    RSYS_um_remove_group,
+    RSYS_um_remove_gm,
+    RSYS_um_user_exists,
+    RSYS_um_group_exists,
+    RSYS_um_get_next_user,
+    RSYS_um_get_user_list,
+    RSYS_um_get_gm_list,
+    RSYS_um_get_gm_user_list,
+    RSYS_um_get_group_list,
+    RSYS_um_get_uid,
+    RSYS_um_get_gid,
+    RSYS_um_set_pass,
+    RSYS_um_set_pass_name,
+    RSYS_um_set_group_pass,
+    RSYS_um_check_account,
+    RSYS_um_check_account_name,
+    RSYS_list_ta_begin,
+    RSYS_list_ta_refresh,
+    RSYS_list_ta_commit,
+    RSYS_list_ta_forget,
+    RSYS_list_all_dev,
+    RSYS_acl_list_all_dev,
+    RSYS_list_all_user,
+    RSYS_acl_list_all_user,
+    RSYS_list_all_group,
+    RSYS_acl_list_all_group,
+    RSYS_list_all_ipc,
+    RSYS_rc_select_fd_create_type,
+    RSYS_um_select_vset,
+    RSYS_um_add_onetime,
+    RSYS_um_add_onetime_name,
+    RSYS_um_remove_all_onetime,
+    RSYS_um_remove_all_onetime_name,
+    RSYS_um_count_onetime,
+    RSYS_um_count_onetime_name,
+    RSYS_list_ta_begin_name,
+    RSYS_um_get_max_history,
+    RSYS_um_get_max_history_name,
+    RSYS_um_set_max_history,
+    RSYS_um_set_max_history_name,
+    RSYS_udf_flush_cache,
+    RSYS_none
+  };
+
+
+struct rsys_check_t
+  {
+    int correct;
+    int check_inode;
+  };
+
+struct rsys_get_attr_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+    union rsbac_target_id_t __user * tid;
+          rsbac_enum_t attr;
+    union rsbac_attribute_value_t __user * value;
+          int inherit;
+  };
+
+struct rsys_get_attr_n_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+          char __user * t_name;
+          rsbac_enum_t attr;
+    union rsbac_attribute_value_t __user * value;
+          int inherit;
+  };
+
+struct rsys_set_attr_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+    union rsbac_target_id_t __user * tid;
+          rsbac_enum_t attr;
+    union rsbac_attribute_value_t __user * value;
+  };
+
+struct rsys_set_attr_n_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+          char __user * t_name;
+          rsbac_enum_t attr;
+    union rsbac_attribute_value_t __user * value;
+  };
+
+struct rsys_remove_target_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+    union rsbac_target_id_t __user * tid;
+  };
+
+struct rsys_remove_target_n_t
+  {
+         rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+         char __user * t_name;
+  };
+
+struct rsys_net_list_all_netdev_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_netdev_id_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_net_template_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t call;
+          rsbac_net_temp_id_t id;
+    union rsbac_net_temp_syscall_data_t __user * data_p;
+  };
+
+struct rsys_net_list_all_template_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_net_temp_id_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_switch_t
+  {
+    rsbac_enum_t module;
+    int value;
+  };
+
+struct rsys_get_switch_t
+  {
+    rsbac_enum_t module;
+    int __user * value_p;
+    int __user * switchable_p;
+  };
+
+struct rsys_adf_log_switch_t
+  {
+    rsbac_enum_t request;
+    rsbac_enum_t target;
+    u_int        value;
+  };
+
+struct rsys_get_adf_log_t
+  {
+    rsbac_enum_t   request;
+    rsbac_enum_t   target;
+    u_int        __user * value_p;
+  };
+
+struct rsys_log_t
+  {
+    int type;
+    char __user * buf;
+    int len;
+  };
+
+struct rsys_mac_set_curr_level_t
+  {
+    rsbac_security_level_t level;
+    rsbac_mac_category_vector_t __user * categories_p;
+  };
+
+struct rsys_mac_get_curr_level_t
+  {
+    rsbac_security_level_t      __user * level_p;
+    rsbac_mac_category_vector_t __user * categories_p;
+  };
+
+struct rsys_mac_get_max_level_t
+  {
+    rsbac_security_level_t      __user * level_p;
+    rsbac_mac_category_vector_t __user * categories_p;
+  };
+
+struct rsys_mac_get_min_level_t
+  {
+    rsbac_security_level_t      __user * level_p;
+    rsbac_mac_category_vector_t __user * categories_p;
+  };
+
+struct rsys_mac_add_p_tru_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_upid_t pid;
+    rsbac_uid_t uid;
+    rsbac_time_t ttl;
+  };
+
+struct rsys_mac_remove_p_tru_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_upid_t pid;
+    rsbac_uid_t uid;
+  };
+
+struct rsys_mac_add_f_tru_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * filename;
+    rsbac_uid_t uid;
+    rsbac_time_t ttl;
+  };
+
+struct rsys_mac_remove_f_tru_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * filename;
+    rsbac_uid_t uid;
+  };
+
+struct rsys_mac_get_f_trulist_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * filename;
+    rsbac_uid_t __user * trulist;
+    rsbac_time_t __user * ttllist;
+    u_int maxnum;
+  };
+
+struct rsys_mac_get_p_trulist_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_upid_t pid;
+    rsbac_uid_t __user * trulist;
+    rsbac_time_t __user * ttllist;
+    u_int maxnum;
+  };
+
+struct rsys_rc_copy_role_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_rc_role_id_t from_role;
+    rsbac_rc_role_id_t to_role;
+  };
+
+struct rsys_rc_copy_type_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_enum_t target;
+    rsbac_rc_type_id_t from_type;
+    rsbac_rc_type_id_t to_type;
+  };
+
+struct rsys_rc_get_item_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+    union rsbac_rc_target_id_t __user * tid_p;
+    union rsbac_rc_target_id_t __user * subtid_p;
+          rsbac_enum_t item;
+    union rsbac_rc_item_value_t __user * value_p;
+          rsbac_time_t __user * ttl_p;
+  };
+
+struct rsys_rc_set_item_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+    union rsbac_rc_target_id_t __user * tid_p;
+    union rsbac_rc_target_id_t __user * subtid_p;
+          rsbac_enum_t item;
+    union rsbac_rc_item_value_t __user * value_p;
+          rsbac_time_t ttl;
+  };
+
+struct rsys_rc_get_list_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+    union rsbac_rc_target_id_t __user * tid_p;
+          rsbac_enum_t item;
+          u_int maxnum;
+          __u32 __user * array_p;
+          rsbac_time_t __user * ttl_array_p;
+  };
+
+struct rsys_rc_change_role_t
+  {
+    rsbac_rc_role_id_t role;
+    char __user * pass;
+  };
+
+struct rsys_rc_get_eff_rights_n_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_enum_t target;
+    char __user * t_name;
+    rsbac_rc_request_vector_t __user * request_vector_p;
+    rsbac_time_t __user * ttl_p;
+  };
+
+struct rsys_rc_get_current_role_t
+  {
+    rsbac_rc_role_id_t __user * role_p;
+  };
+
+struct rsys_auth_add_p_cap_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_upid_t pid;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_t cap_range;
+           rsbac_time_t ttl;
+  };
+
+struct rsys_auth_remove_p_cap_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_upid_t pid;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_t cap_range;
+  };
+
+struct rsys_auth_add_f_cap_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           char __user * filename;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_t cap_range;
+           rsbac_time_t ttl;
+  };
+
+struct rsys_auth_remove_f_cap_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           char __user * filename;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_t cap_range;
+  };
+
+struct rsys_auth_get_f_caplist_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           char __user * filename;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_t __user * caplist;
+           rsbac_time_t __user * ttllist;
+           u_int maxnum;
+  };
+
+struct rsys_auth_get_p_caplist_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_upid_t pid;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_t __user * caplist;
+           rsbac_time_t __user * ttllist;
+           u_int maxnum;
+  };
+
+struct rsys_acl_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t call;
+    struct rsbac_acl_syscall_arg_t __user * arg;
+  };
+
+struct rsys_acl_n_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t call;
+    struct rsbac_acl_syscall_n_arg_t __user * arg;
+  };
+
+struct rsys_acl_get_rights_t
+  {
+           rsbac_list_ta_number_t ta_number;
+    struct rsbac_acl_syscall_arg_t __user * arg;
+           rsbac_acl_rights_vector_t __user * rights_p;
+           u_int effective;
+  };
+
+struct rsys_acl_get_rights_n_t
+  {
+           rsbac_list_ta_number_t ta_number;
+    struct rsbac_acl_syscall_n_arg_t __user * arg;
+           rsbac_acl_rights_vector_t __user * rights_p;
+           u_int effective;
+  };
+
+struct rsys_acl_get_tlist_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+    union  rsbac_target_id_t __user * tid;
+    struct rsbac_acl_entry_t __user * entry_array;
+           rsbac_time_t __user * ttl_array;
+           u_int maxnum;
+  };
+
+struct rsys_acl_get_tlist_n_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+           char __user * t_name;
+    struct rsbac_acl_entry_t __user * entry_array;
+           rsbac_time_t __user * ttl_array;
+           u_int maxnum;
+  };
+
+struct rsys_acl_get_mask_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+    union  rsbac_target_id_t __user * tid;
+           rsbac_acl_rights_vector_t __user * mask_p;
+  };
+
+struct rsys_acl_get_mask_n_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+           char __user * t_name;
+           rsbac_acl_rights_vector_t __user * mask_p;
+  };
+
+struct rsys_acl_group_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t call;
+    union rsbac_acl_group_syscall_arg_t __user * arg_p;
+  };
+
+struct rsys_reg_t
+  {
+    long handle;
+    void __user * arg;
+  };
+
+struct rsys_jail_t
+  {
+    rsbac_version_t      version;
+    char               __user * path;
+    rsbac_jail_ip_t      ip;
+    rsbac_jail_flags_t   flags;
+    rsbac_cap_vector_t   max_caps;
+    rsbac_jail_scd_vector_t scd_get;
+    rsbac_jail_scd_vector_t scd_modify;
+  };
+
+struct rsys_init_t
+  {
+    char __user * root_dev;
+  };
+
+struct rsys_um_auth_name_t
+  {
+    char __user * name;
+    char __user * pass;
+  };
+
+struct rsys_um_auth_uid_t
+  {
+    rsbac_uid_t   uid;
+    char        __user * pass;
+  };
+
+struct rsys_um_add_user_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_uid_t             uid;
+    struct rsbac_um_user_entry_t __user * entry_p;
+           char                  __user * pass;
+           rsbac_time_t            ttl;
+  };
+
+struct rsys_um_add_group_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_gid_t              gid;
+    struct rsbac_um_group_entry_t __user * entry_p;
+           char                   __user * pass;
+           rsbac_time_t             ttl;
+  };
+
+struct rsys_um_add_gm_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_uid_t  uid;
+           rsbac_gid_num_t  gid;
+           rsbac_time_t ttl;
+  };
+
+struct rsys_um_mod_user_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t           uid;
+          rsbac_enum_t          mod;
+    union rsbac_um_mod_data_t __user * data_p;
+  };
+
+struct rsys_um_mod_group_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_t           gid;
+          rsbac_enum_t          mod;
+    union rsbac_um_mod_data_t __user * data_p;
+  };
+
+struct rsys_um_get_user_item_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t           uid;
+          rsbac_enum_t          mod;
+    union rsbac_um_mod_data_t __user * data_p;
+  };
+
+struct rsys_um_get_group_item_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_t           gid;
+          rsbac_enum_t          mod;
+    union rsbac_um_mod_data_t __user * data_p;
+  };
+
+struct rsys_um_remove_user_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t           uid;
+  };
+
+struct rsys_um_remove_group_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_t           gid;
+  };
+
+struct rsys_um_remove_gm_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t  uid;
+          rsbac_gid_num_t  gid;
+  };
+
+struct rsys_um_user_exists_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t uid;
+  };
+
+struct rsys_um_group_exists_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_t gid;
+  };
+
+struct rsys_um_get_next_user_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t   old_user;
+          rsbac_uid_t __user * next_user_p;
+  };
+
+struct rsys_um_get_user_list_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_um_set_t vset;
+          rsbac_uid_t __user * user_array;
+          u_int         maxnum;
+  };
+
+struct rsys_um_get_gm_list_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_t   user;
+          rsbac_gid_num_t __user * group_array;
+          u_int         maxnum;
+  };
+
+struct rsys_um_get_gm_user_list_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_t   group;
+          rsbac_uid_num_t __user * user_array;
+          u_int         maxnum;
+  };
+
+struct rsys_um_get_group_list_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_um_set_t vset;
+          rsbac_gid_t __user * group_array;
+          u_int         maxnum;
+  };
+
+struct rsys_um_get_uid_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char        __user * name;
+    rsbac_uid_t __user * uid_p;
+  };
+
+struct rsys_um_get_gid_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char        __user * name;
+    rsbac_gid_t __user * gid_p;
+  };
+
+struct rsys_um_set_pass_t
+  {
+    rsbac_uid_t   uid;
+    char        __user * old_pass;
+    char        __user * new_pass;
+  };
+
+struct rsys_um_set_pass_name_t
+  {
+    char __user * name;
+    char __user * old_pass;
+    char __user * new_pass;
+  };
+
+struct rsys_um_add_onetime_t
+  {
+    rsbac_uid_t   uid;
+    char        __user * old_pass;
+    char        __user * new_pass;
+    rsbac_time_t  ttl;
+  };
+
+struct rsys_um_add_onetime_name_t
+  {
+    char __user * name;
+    char __user * old_pass;
+    char __user * new_pass;
+    rsbac_time_t ttl;
+  };
+
+struct rsys_um_remove_all_onetime_t
+  {
+    rsbac_uid_t   uid;
+    char        __user * old_pass;
+  };
+
+struct rsys_um_remove_all_onetime_name_t
+  {
+    char __user * name;
+    char __user * old_pass;
+  };
+
+struct rsys_um_count_onetime_t
+  {
+    rsbac_uid_t   uid;
+    char        __user * old_pass;
+  };
+
+struct rsys_um_count_onetime_name_t
+  {
+    char __user * name;
+    char __user * old_pass;
+  };
+
+struct rsys_um_set_group_pass_t
+  {
+    rsbac_gid_t   gid;
+    char        __user * new_pass;
+  };
+
+struct rsys_um_check_account_t
+  {
+    rsbac_uid_t   uid;
+  };
+
+struct rsys_um_check_account_name_t
+  {
+    char __user * name;
+  };
+
+struct rsys_um_get_max_history_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_uid_t   uid;
+  };
+
+struct rsys_um_get_max_history_name_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * name;
+  };
+
+struct rsys_um_set_max_history_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_uid_t   uid;
+    __u8          max_history;
+  };
+
+struct rsys_um_set_max_history_name_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * name;
+    __u8   max_history;
+  };
+
+struct rsys_um_select_vset_t
+  {
+    rsbac_um_set_t vset;
+  };
+
+struct rsys_list_ta_begin_t
+  {
+    rsbac_time_t ttl;
+    rsbac_list_ta_number_t __user * ta_number_p;
+    rsbac_uid_t commit_uid;
+    char __user * password;
+  };
+
+struct rsys_list_ta_begin_name_t
+  {
+    rsbac_time_t ttl;
+    rsbac_list_ta_number_t __user * ta_number_p;
+    rsbac_uid_t commit_uid;
+    char __user * name;
+    char __user * password;
+  };
+
+struct rsys_list_ta_refresh_t
+  {
+    rsbac_time_t ttl;
+    rsbac_list_ta_number_t ta_number;
+    char __user * password;
+  };
+
+struct rsys_list_ta_commit_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * password;
+  };
+
+struct rsys_list_ta_forget_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    char __user * password;
+  };
+
+struct rsys_list_all_dev_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    struct rsbac_dev_desc_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_acl_list_all_dev_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    struct rsbac_dev_desc_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_list_all_user_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_uid_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_acl_list_all_user_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_uid_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_list_all_group_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_gid_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_acl_list_all_group_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_gid_t __user * id_p;
+    u_long maxnum;
+  };
+
+struct rsys_list_all_ipc_t {
+       rsbac_list_ta_number_t ta_number;
+       struct rsbac_ipc_t __user *id_p;
+       u_long maxnum;
+};
+
+struct rsys_rc_select_fd_create_type_t {
+	rsbac_rc_type_id_t type;
+};
+
+union rsbac_syscall_arg_t
+  {
+    struct rsys_check_t check;
+    struct rsys_get_attr_t get_attr;
+    struct rsys_get_attr_n_t get_attr_n;
+    struct rsys_set_attr_t set_attr;
+    struct rsys_set_attr_n_t set_attr_n;
+    struct rsys_remove_target_t remove_target;
+    struct rsys_remove_target_n_t remove_target_n;
+    struct rsys_net_list_all_netdev_t net_list_all_netdev;
+    struct rsys_net_template_t net_template;
+    struct rsys_net_list_all_template_t net_list_all_template;
+    struct rsys_switch_t switch_module;
+    struct rsys_get_switch_t get_switch_module;
+    struct rsys_adf_log_switch_t adf_log_switch;
+    struct rsys_get_adf_log_t get_adf_log;
+    struct rsys_log_t log;
+    struct rsys_mac_set_curr_level_t mac_set_curr_level;
+    struct rsys_mac_get_curr_level_t mac_get_curr_level;
+    struct rsys_mac_get_max_level_t mac_get_max_level;
+    struct rsys_mac_get_min_level_t mac_get_min_level;
+    struct rsys_mac_add_p_tru_t mac_add_p_tru;
+    struct rsys_mac_remove_p_tru_t mac_remove_p_tru;
+    struct rsys_mac_add_f_tru_t mac_add_f_tru;
+    struct rsys_mac_remove_f_tru_t mac_remove_f_tru;
+    struct rsys_mac_get_f_trulist_t mac_get_f_trulist;
+    struct rsys_mac_get_p_trulist_t mac_get_p_trulist;
+    struct rsys_rc_copy_role_t rc_copy_role;
+    struct rsys_rc_copy_type_t rc_copy_type;
+    struct rsys_rc_get_item_t rc_get_item;
+    struct rsys_rc_set_item_t rc_set_item;
+    struct rsys_rc_get_list_t rc_get_list;
+    struct rsys_rc_change_role_t rc_change_role;
+    struct rsys_rc_get_eff_rights_n_t rc_get_eff_rights_n;
+    struct rsys_rc_get_current_role_t rc_get_current_role;
+    struct rsys_auth_add_p_cap_t auth_add_p_cap;
+    struct rsys_auth_remove_p_cap_t auth_remove_p_cap;
+    struct rsys_auth_add_f_cap_t auth_add_f_cap;
+    struct rsys_auth_remove_f_cap_t auth_remove_f_cap;
+    struct rsys_auth_get_f_caplist_t auth_get_f_caplist;
+    struct rsys_auth_get_p_caplist_t auth_get_p_caplist;
+    struct rsys_acl_t acl;
+    struct rsys_acl_n_t acl_n;
+    struct rsys_acl_get_rights_t acl_get_rights;
+    struct rsys_acl_get_rights_n_t acl_get_rights_n;
+    struct rsys_acl_get_tlist_t acl_get_tlist;
+    struct rsys_acl_get_tlist_n_t acl_get_tlist_n;
+    struct rsys_acl_get_mask_t acl_get_mask;
+    struct rsys_acl_get_mask_n_t acl_get_mask_n;
+    struct rsys_acl_group_t acl_group;
+    struct rsys_reg_t reg;
+    struct rsys_jail_t jail;
+    struct rsys_init_t init;
+    struct rsys_um_auth_name_t um_auth_name;
+    struct rsys_um_auth_uid_t um_auth_uid;
+    struct rsys_um_add_user_t um_add_user;
+    struct rsys_um_add_group_t um_add_group;
+    struct rsys_um_add_gm_t um_add_gm;
+    struct rsys_um_mod_user_t um_mod_user;
+    struct rsys_um_mod_group_t um_mod_group;
+    struct rsys_um_get_user_item_t um_get_user_item;
+    struct rsys_um_get_group_item_t um_get_group_item;
+    struct rsys_um_remove_user_t um_remove_user;
+    struct rsys_um_remove_group_t um_remove_group;
+    struct rsys_um_remove_gm_t um_remove_gm;
+    struct rsys_um_user_exists_t um_user_exists;
+    struct rsys_um_group_exists_t um_group_exists;
+    struct rsys_um_get_next_user_t um_get_next_user;
+    struct rsys_um_get_user_list_t um_get_user_list;
+    struct rsys_um_get_gm_list_t um_get_gm_list;
+    struct rsys_um_get_gm_user_list_t um_get_gm_user_list;
+    struct rsys_um_get_group_list_t um_get_group_list;
+    struct rsys_um_get_uid_t um_get_uid;
+    struct rsys_um_get_gid_t um_get_gid;
+    struct rsys_um_set_pass_t um_set_pass;
+    struct rsys_um_set_pass_name_t um_set_pass_name;
+    struct rsys_um_add_onetime_t um_add_onetime;
+    struct rsys_um_add_onetime_name_t um_add_onetime_name;
+    struct rsys_um_remove_all_onetime_t um_remove_all_onetime;
+    struct rsys_um_remove_all_onetime_name_t um_remove_all_onetime_name;
+    struct rsys_um_count_onetime_t um_count_onetime;
+    struct rsys_um_count_onetime_name_t um_count_onetime_name;
+    struct rsys_um_set_group_pass_t um_set_group_pass;
+    struct rsys_um_check_account_t um_check_account;
+    struct rsys_um_check_account_name_t um_check_account_name;
+    struct rsys_um_get_max_history_t um_get_max_history;
+    struct rsys_um_get_max_history_name_t um_get_max_history_name;
+    struct rsys_um_set_max_history_t um_set_max_history;
+    struct rsys_um_set_max_history_name_t um_set_max_history_name;
+    struct rsys_list_ta_begin_t list_ta_begin;
+    struct rsys_list_ta_begin_name_t list_ta_begin_name;
+    struct rsys_list_ta_refresh_t list_ta_refresh;
+    struct rsys_list_ta_commit_t list_ta_commit;
+    struct rsys_list_ta_forget_t list_ta_forget;
+    struct rsys_list_all_dev_t list_all_dev;
+    struct rsys_acl_list_all_dev_t acl_list_all_dev;
+    struct rsys_list_all_user_t list_all_user;
+    struct rsys_acl_list_all_user_t acl_list_all_user;
+    struct rsys_list_all_group_t list_all_group;
+    struct rsys_acl_list_all_group_t acl_list_all_group;
+    struct rsys_list_all_ipc_t list_all_ipc;
+    struct rsys_rc_select_fd_create_type_t rc_select_fd_create_type;
+    struct rsys_um_select_vset_t um_select_vset;
+           int dummy;
+  };
+
+/*
+ * 32 Bit emulation support on x86_64 system
+ */
+
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+struct rsys_check_ia32_t
+  {
+    __s32 correct;
+    __s32 check_inode;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_get_attr_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+          __u32 tid;
+          rsbac_enum_t attr;
+          __u32 value;
+          __s32 inherit;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_get_attr_n_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+          __u32 t_name;
+          rsbac_enum_t attr;
+          __u32 value;
+          __s32 inherit;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_set_attr_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+          __u32 tid;
+          rsbac_enum_t attr;
+          __u32 value;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_set_attr_n_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t module;
+          rsbac_enum_t target;
+          __u32 t_name;
+          rsbac_enum_t attr;
+          __u32 value;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_remove_target_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+          __u32 tid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_remove_target_n_ia32_t
+  {
+         rsbac_list_ta_number_t ta_number;
+         rsbac_enum_t target;
+         __u32 t_name;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_net_list_all_netdev_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_net_template_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t call;
+          rsbac_net_temp_id_t id;
+          __u32 data_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_net_list_all_template_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_switch_ia32_t
+  {
+    rsbac_enum_t module;
+    __s32 value;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_get_switch_ia32_t
+  {
+    rsbac_enum_t module;
+    __u32 value_p;
+    __u32 switchable_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_adf_log_switch_ia32_t
+  {
+    rsbac_enum_t request;
+    rsbac_enum_t target;
+    __u32        value;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_get_adf_log_ia32_t
+  {
+    rsbac_enum_t   request;
+    rsbac_enum_t   target;
+    __u32 value_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_log_ia32_t
+  {
+    __u32 type;
+    __u32 buf;
+    __u32 len;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_set_curr_level_ia32_t
+  {
+    rsbac_security_level_t level;
+    __u32 categories_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_get_curr_level_ia32_t
+  {
+    __u32 level_p;
+    __u32 categories_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_get_max_level_ia32_t
+  {
+    __u32 level_p;
+    __u32 categories_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_get_min_level_ia32_t
+  {
+    __u32 level_p;
+    __u32 categories_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_add_p_tru_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    compat_pid_t pid;
+    rsbac_uid_ia32_t uid;
+    rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_remove_p_tru_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    compat_pid_t pid;
+    rsbac_uid_ia32_t uid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_add_f_tru_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 filename;
+    rsbac_uid_ia32_t uid;
+    rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_remove_f_tru_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 filename;
+    rsbac_uid_ia32_t uid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_get_f_trulist_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 filename;
+    __u32 trulist;
+    __u32 ttllist;
+    __u32 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_mac_get_p_trulist_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    compat_pid_t pid;
+    __u32 trulist;
+    __u32 ttllist;
+    __u32 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_copy_role_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_rc_role_id_t from_role;
+    rsbac_rc_role_id_t to_role;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_copy_type_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_enum_t target;
+    rsbac_rc_type_id_t from_type;
+    rsbac_rc_type_id_t to_type;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_get_item_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+          __u32 tid_p;
+          __u32 subtid_p;
+          rsbac_enum_t item;
+          __u32 value_p;
+          __u32 ttl_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_set_item_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+          __u32 tid_p;
+          __u32 subtid_p;
+          rsbac_enum_t item;
+          __u32 value_p;
+          rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_get_list_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t target;
+          __u32 tid_p;
+          rsbac_enum_t item;
+          __u32 maxnum;
+          __u32 array_p;
+          __u32 ttl_array_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_change_role_ia32_t
+  {
+    rsbac_rc_role_id_t role;
+    __u32 pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_get_eff_rights_n_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_enum_t target;
+    __u32 t_name;
+    __u32 request_vector_p;
+    __u32 ttl_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_rc_get_current_role_ia32_t
+  {
+    __u32 role_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_auth_add_p_cap_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           compat_pid_t pid;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_ia32_t cap_range;
+           rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_auth_remove_p_cap_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           compat_pid_t pid;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_ia32_t cap_range;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_auth_add_f_cap_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           __u32 filename;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_ia32_t cap_range;
+           rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_auth_remove_f_cap_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           __u32 filename;
+           rsbac_enum_t cap_type;
+    struct rsbac_auth_cap_range_ia32_t cap_range;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_auth_get_f_caplist_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           __u32 filename;
+           rsbac_enum_t cap_type;
+           __u32 caplist;
+           __u32 ttllist;
+           __u32 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_auth_get_p_caplist_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           compat_pid_t pid;
+           rsbac_enum_t cap_type;
+           __u32 caplist;
+           __u32 ttllist;
+           __u32 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t call;
+           __u32 arg;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_n_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t call;
+           __u32 arg;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_get_rights_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           __u32 arg;
+           __u32 rights_p;
+           __u32 effective;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_get_rights_n_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           __u32 arg;
+           __u32 rights_p;
+           __u32 effective;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_get_tlist_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+           __u32 tid;
+           __u32 entry_array;
+           __u32 ttl_array;
+           __u32 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_get_tlist_n_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+           __u32 t_name;
+           __u32 entry_array;
+           __u32 ttl_array;
+           __u32 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_get_mask_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+           __u32 tid;
+           __u32 mask_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_get_mask_n_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_enum_t target;
+           __u32 t_name;
+           __u32 mask_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_group_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_enum_t call;
+          __u32 arg_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_reg_ia32_t
+  {
+    compat_s64 handle;
+    __u32 arg;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_jail_ia32_t
+  {
+    rsbac_version_t      version;
+    __u32                path;
+    rsbac_jail_ip_t      ip;
+    rsbac_jail_flags_t   flags;
+    rsbac_cap_vector_t   max_caps;
+    rsbac_jail_scd_vector_t scd_get;
+    rsbac_jail_scd_vector_t scd_modify;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_init_ia32_t
+  {
+    __u32 root_dev;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_auth_name_ia32_t
+  {
+    __u32 name;
+    __u32 pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_auth_uid_ia32_t
+  {
+    rsbac_uid_ia32_t uid;
+    __u32       pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_add_user_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_uid_ia32_t             uid;
+           __u32                   entry_p;
+           __u32                   pass;
+           rsbac_time_t            ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_add_group_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_gid_ia32_t              gid;
+           __u32                    entry_p;
+           __u32                    pass;
+           rsbac_time_t             ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_add_gm_ia32_t
+  {
+           rsbac_list_ta_number_t ta_number;
+           rsbac_uid_ia32_t  uid;
+           rsbac_gid_num_t  gid;
+           rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_mod_user_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t           uid;
+          rsbac_enum_t          mod;
+          __u32                 data_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_mod_group_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_ia32_t            gid;
+          rsbac_enum_t           mod;
+          __u32                  data_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_user_item_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t            uid;
+          rsbac_enum_t           mod;
+          __u32                  data_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_group_item_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_ia32_t            gid;
+          rsbac_enum_t           mod;
+          __u32                  data_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_remove_user_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t           uid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_remove_group_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_ia32_t           gid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_remove_gm_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t  uid;
+          rsbac_gid_num_t  gid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_user_exists_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t uid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_group_exists_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_ia32_t gid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_next_user_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t   old_user;
+          __u32         next_user_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_user_list_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_um_set_t vset;
+          __u32          user_array;
+          u_int          maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_gm_list_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_uid_ia32_t   user;
+          __u32         group_array;
+          u_int         maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_gm_user_list_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_gid_ia32_t   group;
+          __u32         user_array;
+          u_int         maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_group_list_ia32_t
+  {
+          rsbac_list_ta_number_t ta_number;
+          rsbac_um_set_t vset;
+          __u32          group_array;
+          u_int          maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_uid_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32                  name;
+    __u32                  uid_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_gid_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32                  name;
+    __u32                  gid_p;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_set_pass_ia32_t
+  {
+    rsbac_uid_ia32_t uid;
+    __u32       old_pass;
+    __u32       new_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_set_pass_name_ia32_t
+  {
+    __u32 name;
+    __u32 old_pass;
+    __u32 new_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_add_onetime_ia32_t
+  {
+    rsbac_uid_ia32_t  uid;
+    __u32        old_pass;
+    __u32        new_pass;
+    rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_add_onetime_name_ia32_t
+  {
+    __u32 name;
+    __u32 old_pass;
+    __u32 new_pass;
+    rsbac_time_t ttl;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_remove_all_onetime_ia32_t
+  {
+    rsbac_uid_ia32_t uid;
+    __u32       old_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_remove_all_onetime_name_ia32_t
+  {
+    __u32 name;
+    __u32 old_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_count_onetime_ia32_t
+  {
+    rsbac_uid_ia32_t uid;
+    __u32       old_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_count_onetime_name_ia32_t
+  {
+    __u32 name;
+    __u32 old_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_set_group_pass_ia32_t
+  {
+    rsbac_gid_ia32_t gid;
+    __u32       new_pass;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_check_account_ia32_t
+  {
+    rsbac_uid_ia32_t   uid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_check_account_name_ia32_t
+  {
+    __u32 name;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_max_history_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_uid_ia32_t   uid;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_get_max_history_name_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 name;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_set_max_history_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    rsbac_uid_ia32_t   uid;
+    __u8          max_history;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_set_max_history_name_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 name;
+    __u8   max_history;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_um_select_vset_ia32_t
+  {
+    rsbac_um_set_t vset;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_ta_begin_ia32_t
+  {
+    rsbac_time_t ttl;
+    __u32        ta_number_p;
+    rsbac_uid_ia32_t  commit_uid;
+    __u32        password;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_ta_begin_name_ia32_t
+  {
+    rsbac_time_t ttl;
+    __u32 ta_number_p;
+    rsbac_uid_ia32_t commit_uid;
+    __u32 name;
+    __u32 password;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_ta_refresh_ia32_t
+  {
+    rsbac_time_t ttl;
+    rsbac_list_ta_number_t ta_number;
+    __u32 password;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_ta_commit_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 password;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_ta_forget_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 password;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_all_dev_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_list_all_dev_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_all_user_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_list_all_user_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_all_group_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_acl_list_all_group_ia32_t
+  {
+    rsbac_list_ta_number_t ta_number;
+    __u32 id_p;
+    compat_u64 maxnum;
+  } __attribute__ ((aligned (4)));
+
+struct rsys_list_all_ipc_ia32_t
+{
+       rsbac_list_ta_number_t ta_number;
+       __u32 id_p;
+       compat_u64 maxnum;
+} __attribute__ ((aligned (4)));
+
+struct rsys_rc_select_fd_create_type_ia32_t
+{
+	rsbac_rc_type_id_t type;
+} __attribute__ ((aligned (4)));
+
+union rsbac_syscall_arg_ia32_t
+  {
+    struct rsys_check_ia32_t check;
+    struct rsys_get_attr_ia32_t get_attr;
+    struct rsys_get_attr_n_ia32_t get_attr_n;
+    struct rsys_set_attr_ia32_t set_attr;
+    struct rsys_set_attr_n_ia32_t set_attr_n;
+    struct rsys_remove_target_ia32_t remove_target;
+    struct rsys_remove_target_n_ia32_t remove_target_n;
+    struct rsys_net_list_all_netdev_ia32_t net_list_all_netdev;
+    struct rsys_net_template_ia32_t net_template;
+    struct rsys_net_list_all_template_ia32_t net_list_all_template;
+    struct rsys_switch_ia32_t switch_module;
+    struct rsys_get_switch_ia32_t get_switch_module;
+    struct rsys_adf_log_switch_ia32_t adf_log_switch;
+    struct rsys_get_adf_log_ia32_t get_adf_log;
+    struct rsys_log_ia32_t log;
+    struct rsys_mac_set_curr_level_ia32_t mac_set_curr_level;
+    struct rsys_mac_get_curr_level_ia32_t mac_get_curr_level;
+    struct rsys_mac_get_max_level_ia32_t mac_get_max_level;
+    struct rsys_mac_get_min_level_ia32_t mac_get_min_level;
+    struct rsys_mac_add_p_tru_ia32_t mac_add_p_tru;
+    struct rsys_mac_remove_p_tru_ia32_t mac_remove_p_tru;
+    struct rsys_mac_add_f_tru_ia32_t mac_add_f_tru;
+    struct rsys_mac_remove_f_tru_ia32_t mac_remove_f_tru;
+    struct rsys_mac_get_f_trulist_ia32_t mac_get_f_trulist;
+    struct rsys_mac_get_p_trulist_ia32_t mac_get_p_trulist;
+    struct rsys_rc_copy_role_ia32_t rc_copy_role;
+    struct rsys_rc_copy_type_ia32_t rc_copy_type;
+    struct rsys_rc_get_item_ia32_t rc_get_item;
+    struct rsys_rc_set_item_ia32_t rc_set_item;
+    struct rsys_rc_get_list_ia32_t rc_get_list;
+    struct rsys_rc_change_role_ia32_t rc_change_role;
+    struct rsys_rc_get_eff_rights_n_ia32_t rc_get_eff_rights_n;
+    struct rsys_rc_get_current_role_ia32_t rc_get_current_role;
+    struct rsys_auth_add_p_cap_ia32_t auth_add_p_cap;
+    struct rsys_auth_remove_p_cap_ia32_t auth_remove_p_cap;
+    struct rsys_auth_add_f_cap_ia32_t auth_add_f_cap;
+    struct rsys_auth_remove_f_cap_ia32_t auth_remove_f_cap;
+    struct rsys_auth_get_f_caplist_ia32_t auth_get_f_caplist;
+    struct rsys_auth_get_p_caplist_ia32_t auth_get_p_caplist;
+    struct rsys_acl_ia32_t acl;
+    struct rsys_acl_n_ia32_t acl_n;
+    struct rsys_acl_get_rights_ia32_t acl_get_rights;
+    struct rsys_acl_get_rights_n_ia32_t acl_get_rights_n;
+    struct rsys_acl_get_tlist_ia32_t acl_get_tlist;
+    struct rsys_acl_get_tlist_n_ia32_t acl_get_tlist_n;
+    struct rsys_acl_get_mask_ia32_t acl_get_mask;
+    struct rsys_acl_get_mask_n_ia32_t acl_get_mask_n;
+    struct rsys_acl_group_ia32_t acl_group;
+    struct rsys_reg_ia32_t reg;
+    struct rsys_jail_ia32_t jail;
+    struct rsys_init_ia32_t init;
+    struct rsys_um_auth_name_ia32_t um_auth_name;
+    struct rsys_um_auth_uid_ia32_t um_auth_uid;
+    struct rsys_um_add_user_ia32_t um_add_user;
+    struct rsys_um_add_group_ia32_t um_add_group;
+    struct rsys_um_add_gm_ia32_t um_add_gm;
+    struct rsys_um_mod_user_ia32_t um_mod_user;
+    struct rsys_um_mod_group_ia32_t um_mod_group;
+    struct rsys_um_get_user_item_ia32_t um_get_user_item;
+    struct rsys_um_get_group_item_ia32_t um_get_group_item;
+    struct rsys_um_remove_user_ia32_t um_remove_user;
+    struct rsys_um_remove_group_ia32_t um_remove_group;
+    struct rsys_um_remove_gm_ia32_t um_remove_gm;
+    struct rsys_um_user_exists_ia32_t um_user_exists;
+    struct rsys_um_group_exists_ia32_t um_group_exists;
+    struct rsys_um_get_next_user_ia32_t um_get_next_user;
+    struct rsys_um_get_user_list_ia32_t um_get_user_list;
+    struct rsys_um_get_gm_list_ia32_t um_get_gm_list;
+    struct rsys_um_get_gm_user_list_ia32_t um_get_gm_user_list;
+    struct rsys_um_get_group_list_ia32_t um_get_group_list;
+    struct rsys_um_get_uid_ia32_t um_get_uid;
+    struct rsys_um_get_gid_ia32_t um_get_gid;
+    struct rsys_um_set_pass_ia32_t um_set_pass;
+    struct rsys_um_set_pass_name_ia32_t um_set_pass_name;
+    struct rsys_um_add_onetime_ia32_t um_add_onetime;
+    struct rsys_um_add_onetime_name_ia32_t um_add_onetime_name;
+    struct rsys_um_remove_all_onetime_ia32_t um_remove_all_onetime;
+    struct rsys_um_remove_all_onetime_name_ia32_t um_remove_all_onetime_name;
+    struct rsys_um_count_onetime_ia32_t um_count_onetime;
+    struct rsys_um_count_onetime_name_ia32_t um_count_onetime_name;
+    struct rsys_um_set_group_pass_ia32_t um_set_group_pass;
+    struct rsys_um_check_account_ia32_t um_check_account;
+    struct rsys_um_check_account_name_ia32_t um_check_account_name;
+    struct rsys_um_get_max_history_ia32_t um_get_max_history;
+    struct rsys_um_get_max_history_name_ia32_t um_get_max_history_name;
+    struct rsys_um_set_max_history_ia32_t um_set_max_history;
+    struct rsys_um_set_max_history_name_ia32_t um_set_max_history_name;
+    struct rsys_list_ta_begin_ia32_t list_ta_begin;
+    struct rsys_list_ta_begin_name_ia32_t list_ta_begin_name;
+    struct rsys_list_ta_refresh_ia32_t list_ta_refresh;
+    struct rsys_list_ta_commit_ia32_t list_ta_commit;
+    struct rsys_list_ta_forget_ia32_t list_ta_forget;
+    struct rsys_list_all_dev_ia32_t list_all_dev;
+    struct rsys_acl_list_all_dev_ia32_t acl_list_all_dev;
+    struct rsys_list_all_user_ia32_t list_all_user;
+    struct rsys_acl_list_all_user_ia32_t acl_list_all_user;
+    struct rsys_list_all_group_ia32_t list_all_group;
+    struct rsys_acl_list_all_group_ia32_t acl_list_all_group;
+    struct rsys_list_all_ipc_ia32_t list_all_ipc;
+    struct rsys_rc_select_fd_create_type_ia32_t rc_select_fd_create_type;
+    struct rsys_um_select_vset_ia32_t um_select_vset;
+    __u32 dummy;
+  } __attribute__ ((aligned (4)));
+
+#endif /* CONFIG_IA32_EMULATION || CONFIG_X86_X32 */
+
+#endif
diff --git a/include/rsbac/types.h b/include/rsbac/types.h
new file mode 100644
index 0000000..0bdbe5d
--- /dev/null
+++ b/include/rsbac/types.h
@@ -0,0 +1,1056 @@
+/*********************************** */
+/* Rule Set Based Access Control     */
+/* Author and (c)1999-2016:          */
+/*   Amon Ott <ao@rsbac.org>         */
+/* API: Data types for attributes    */
+/*      and standard module calls    */
+/* Last modified: 17/Feb/2016        */
+/*********************************** */
+
+#ifndef __RSBAC_TYPES_H
+#define __RSBAC_TYPES_H
+
+
+/* trigger module dependency for EXPORT_SYMBOL */
+#ifdef CONFIG_MODULES
+#endif
+
+#define RSBAC_VERSION "1.4.9"
+#define RSBAC_VERSION_MAJOR 1
+#define RSBAC_VERSION_MID 4
+#define RSBAC_VERSION_MINOR 9
+#define RSBAC_VERSION_NR \
+ ((RSBAC_VERSION_MAJOR << 16) | (RSBAC_VERSION_MID << 8) | RSBAC_VERSION_MINOR)
+#define RSBAC_VERSION_MAKE_NR(x,y,z) \
+ ((x << 16) | (y << 8) | z)
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/resource.h>
+#else
+#include <asm/types.h>
+#include <sys/types.h>
+#endif
+
+typedef __u32 rsbac_version_t;
+typedef __u64 rsbac_uid_t;           /* High 32 Bit virtual set, low uid */
+typedef __u64 rsbac_gid_t;           /* High 32 Bit virtual set, low gid */
+typedef __u32 rsbac_old_uid_t;       /* Same as user in Linux kernel */
+typedef __u32 rsbac_uid_num_t;       /* Same as user in Linux kernel */
+typedef __u32 rsbac_old_gid_t;       /* Same as group in Linux kernel */
+typedef __u32 rsbac_gid_num_t;       /* Same as user in Linux kernel */
+typedef __u32 rsbac_um_set_t;
+typedef __u32 rsbac_time_t;          /* Same as time_t in Linux kernel */
+typedef kernel_cap_t rsbac_cap_vector_t;    /* Same as kernel_cap_t in Linux kernel */
+typedef __u32 rsbac_cap_old_vector_t;    /* Same as kernel_cap_t in Linux kernel */
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_uid_ia32_t;           /* High 32 Bit virtual set, low uid */
+typedef __u64 __attribute__((aligned(4))) rsbac_gid_ia32_t;           /* High 32 Bit virtual set, low gid */
+#endif
+
+#define RSBAC_UID_SET(x) ((rsbac_um_set_t) (x >> 32))
+#define RSBAC_UID_NUM(x) ((rsbac_uid_num_t) (x & (rsbac_uid_num_t) -1))
+#define RSBAC_GEN_UID(x,y) ((rsbac_uid_t) x << 32 | RSBAC_UID_NUM(y))
+#define RSBAC_GID_SET(x) ((rsbac_um_set_t) (x >> 32))
+#define RSBAC_GID_NUM(x) ((rsbac_gid_num_t) (x & (rsbac_gid_num_t) -1))
+#define RSBAC_GEN_GID(x,y) ((rsbac_gid_t) x << 32 | RSBAC_GID_NUM(y))
+#define RSBAC_UM_VIRTUAL_KEEP ((rsbac_um_set_t) -1)
+#define RSBAC_UM_VIRTUAL_ALL ((rsbac_um_set_t) -2)
+#define RSBAC_UM_VIRTUAL_MAX ((rsbac_um_set_t) -10)
+
+typedef __u32 rsbac_list_ta_number_t;
+
+struct rsbac_nanotime_t
+    {
+      rsbac_time_t sec;
+      __u32 nsec;
+    };
+
+#ifdef __KERNEL__
+#include <linux/fs.h>
+#include <linux/socket.h>
+#include <linux/pipe_fs_i.h>
+#include <linux/kdev_t.h>
+
+/* version checks */
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#error "RSBAC: unsupported kernel version"
+#endif
+
+#include <linux/pid.h>
+#define RSBAC_MAJOR MAJOR
+#define RSBAC_MINOR MINOR
+#define RSBAC_MKDEV(major,minor) MKDEV(major,minor)
+static inline rsbac_time_t rsbac_current_time(void)
+  {
+    struct timespec ts = CURRENT_TIME;
+    return ts.tv_sec;
+  }
+static inline void rsbac_get_current_nanotime(struct rsbac_nanotime_t * nanotime)
+  {
+    struct timespec ts = CURRENT_TIME;
+    nanotime->sec = ts.tv_sec;
+    nanotime->nsec = ts.tv_nsec;
+  }
+#ifndef kdev_t
+#define kdev_t dev_t
+#endif
+#define RSBAC_CURRENT_TIME (rsbac_current_time())
+
+
+#define RSBAC_ZERO_DEV RSBAC_MKDEV(0,0)
+#define RSBAC_AUTO_DEV RSBAC_MKDEV(99,99)
+#define RSBAC_IS_ZERO_DEV(kdev) (!RSBAC_MAJOR(kdev) && !RSBAC_MINOR(kdev))
+#define RSBAC_IS_AUTO_DEV(kdev) ((RSBAC_MAJOR(kdev) == 99) && (RSBAC_MINOR(kdev) == 99))
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+#define R_INIT
+#else
+#define R_INIT __init
+#endif
+
+#endif
+
+/* General */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+#define rsbac_min(a,b) (((a)<(b))?(a):(b))
+#define rsbac_max(a,b) (((a)>(b))?(a):(b))
+
+#define RSBAC_OLD_NO_USER 65533
+#define RSBAC_OLD_ALL_USERS 65532
+#define RSBAC_NO_USER ((rsbac_uid_num_t) -3)
+#define RSBAC_ALL_USERS ((rsbac_uid_num_t) -4)
+#define RSBAC_NO_GROUP ((rsbac_gid_num_t) -3)
+#define RSBAC_ALL_GROUPS ((rsbac_gid_num_t) -4)
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+typedef u_int rsbac_boolean_t;
+
+typedef __u8 rsbac_boolean_int_t;
+
+#define RSBAC_IFNAMSIZ 16
+typedef u_char rsbac_netdev_id_t[RSBAC_IFNAMSIZ + 1];
+
+#define RSBAC_SEC_DEL_CHUNK_SIZE 65536
+
+/* Adjust these, if you have to, but if you do, adjust them all! */
+/* Note: no / allowed, file must be exactly in second level! */
+#define RSBAC_AUTH_LOGIN_PATH "/bin/login"
+#define RSBAC_AUTH_LOGIN_PATH_DIR "bin"
+#define RSBAC_AUTH_LOGIN_PATH_FILE "login"
+
+/* These data structures work parallel to the Linux data structures, */
+/* so all data for RSBAC decisions is maintained seperately.         */
+/* Any change to RSBAC data will NOT modify any other linux data,    */
+/* e.g. userlists, process lists or inodes.                          */
+
+/* Special generic lists time-to-live (ttl) value to keep old setting */
+#define RSBAC_LIST_TTL_KEEP ((rsbac_time_t) -1)
+
+typedef __u8 rsbac_enum_t; /* internally used for all enums */
+
+#define RSBAC_SYSADM_UID   0
+#define RSBAC_BIN_UID      1
+#ifdef CONFIG_RSBAC_SECOFF_UID
+#define RSBAC_SECOFF_UID   CONFIG_RSBAC_SECOFF_UID
+#else
+#define RSBAC_SECOFF_UID 400
+#endif
+#define RSBAC_AUDITOR_UID  (RSBAC_SECOFF_UID+4)
+
+typedef __u32 rsbac_pseudo_t;               /* For Pseudonymic Logging */
+typedef __kernel_pid_t rsbac_upid_t;         /* Same as pid in Linux < 2.6.24 */
+
+typedef struct pid * rsbac_pid_t;         /* use new pid struct */
+
+typedef __u32 rsbac_ta_number_t;
+
+typedef __u8 rsbac_security_level_t;
+#define SL_max            252
+#define SL_min            0
+// #define SL_rsbac_internal 253
+#define SL_inherit        254
+#define SL_none           255
+enum    rsbac_old_security_level_t {SL_unclassified, SL_confidential, SL_secret,
+                                    SL_top_secret, SL_old_rsbac_internal,
+                                    SL_old_inherit, SL_old_none};
+                                             /* MAC security levels   */
+typedef __u64 rsbac_mac_category_vector_t;   /* MAC category sets */
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_mac_category_vector_ia32_t;   /* MAC category sets */
+#endif
+#define RSBAC_MAC_GENERAL_CATEGORY 0
+#define RSBAC_MAC_DEF_CAT_VECTOR ((rsbac_mac_category_vector_t) 1)
+  /* 1 << GENERAL_CAT */
+#define RSBAC_MAC_MAX_CAT_VECTOR ((rsbac_mac_category_vector_t) -1)
+  /* all bits set */
+#define RSBAC_MAC_MIN_CAT_VECTOR ((rsbac_mac_category_vector_t) 0)
+  /* no bits set */
+#define RSBAC_MAC_INHERIT_CAT_VECTOR ((rsbac_mac_category_vector_t) 0)
+  /* for fd: no bits set */
+#define RSBAC_MAC_NR_CATS 64
+#define RSBAC_MAC_MAX_CAT 63
+
+#define RSBAC_MAC_CAT_VECTOR(x) ((rsbac_mac_category_vector_t) 1 << (x))
+
+typedef u_int rsbac_cwi_relation_id_t;
+
+/* For MAC, FF, AUTH */
+enum    rsbac_system_role_t {SR_user, SR_security_officer, SR_administrator,
+                             SR_auditor, SR_none};
+typedef rsbac_enum_t rsbac_system_role_int_t;
+
+/* For all models */
+enum    rsbac_fake_root_uid_t {FR_off, FR_uid_only, FR_euid_only, FR_both,
+                              FR_none};
+typedef rsbac_enum_t rsbac_fake_root_uid_int_t;
+
+enum    rsbac_scd_type_t {ST_time_strucs, ST_clock, ST_host_id,
+                          ST_net_id, ST_ioports, ST_rlimit,
+                          ST_swap, ST_syslog, ST_rsbac, ST_rsbac_log,
+                          ST_other, ST_kmem, ST_network, ST_firewall,
+                          ST_priority, ST_sysfs, ST_rsbac_remote_log,
+                          ST_quota, ST_sysctl, ST_nfsd, ST_ksyms,
+                          ST_mlock, ST_capability, ST_kexec, ST_videomem,
+                          ST_none};
+
+typedef __u32 rsbac_scd_vector_t;
+#define RSBAC_SCD_VECTOR(x) ((rsbac_scd_vector_t) 1 << (x))
+
+enum    rsbac_dev_type_t {D_block, D_char, D_block_major, D_char_major, D_none};
+
+
+enum    rsbac_ipc_type_t {I_sem, I_msg, I_shm, I_anonpipe, I_mqueue,
+				I_anonunix, I_none};
+union   rsbac_ipc_id_t
+  {
+    u_long id_nr;
+  };
+
+typedef __u64 rsbac_inode_nr_t;
+typedef __u32 rsbac_old_inode_nr_t;
+
+enum    rsbac_linux_dac_disable_t {LDD_false, LDD_true, LDD_inherit, LDD_none};
+typedef rsbac_enum_t rsbac_linux_dac_disable_int_t;
+
+#ifdef __KERNEL__
+/* We need unique identifiers for each file/dir. inode means inode in */
+/* the file system.                                                   */
+struct rsbac_fs_file_t
+    {
+      kdev_t               device;
+      rsbac_inode_nr_t     inode;
+      struct dentry      * dentry_p;  /* used for inheritance recursion */
+    };
+
+struct rsbac_dev_t
+    {
+      enum  rsbac_dev_type_t     type;
+            kdev_t               id;
+    };
+#endif /* __KERNEL */
+
+/* We need unique ids for dev objects */
+struct rsbac_dev_desc_t
+    {
+      __u32 type;
+      __u32 major;
+      __u32 minor;
+    };
+
+static inline struct rsbac_dev_desc_t
+  rsbac_mkdev_desc(__u32 type, __u32 major, __u32 minor)
+  {
+    struct rsbac_dev_desc_t dev_desc;
+
+    dev_desc.type = type;
+    dev_desc.major = major;
+    dev_desc.minor = minor;
+    return dev_desc;
+  }
+
+#define RSBAC_ZERO_DEV_DESC rsbac_mkdev_desc(D_none, 0, 0)
+#define RSBAC_AUTO_DEV_DESC rsbac_mkdev_desc(D_none, 99, 99)
+#define RSBAC_IS_ZERO_DEV_DESC(dev) ((dev.type == D_none) && !dev.major && !dev.minor)
+#define RSBAC_IS_AUTO_DEV_DESC(dev) ((dev.type == D_none) && (dev.major == 99) && (dev.minor == 99))
+
+/* And we need unique ids for ipc objects */
+struct rsbac_ipc_t
+    {
+      enum  rsbac_ipc_type_t     type;
+      union rsbac_ipc_id_t       id;
+    };
+
+/* log levels: nothing, denied requests only, all, refer to request log level */
+enum    rsbac_log_level_t {LL_none, LL_denied, LL_full, LL_request, LL_invalid};
+typedef __u64 rsbac_log_array_t;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_log_array_ia32_t;
+#endif
+
+/* request bitvectors */
+typedef __u64 rsbac_request_vector_t;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+typedef __u64 __attribute__((aligned(4))) rsbac_request_vector_ia32_t;
+#endif
+#define RSBAC_REQUEST_VECTOR(x) ((rsbac_request_vector_t) 1 << (x))
+
+/* The max length of each filename is kept in a macro */
+#define RSBAC_MAXNAMELEN     256
+
+#define RSBAC_LIST_TA_MAX_NAMELEN 32
+#define RSBAC_LIST_TA_MAX_PASSLEN 36
+
+/* MAC */
+
+typedef __u8 rsbac_mac_user_flags_t;
+typedef __u16 rsbac_mac_process_flags_t;
+typedef __u8 rsbac_mac_file_flags_t;
+typedef struct rsbac_fs_file_t rsbac_mac_file_t;
+#define RSBAC_MAC_MAX_MAXNUM 1000000
+
+#define MAC_override		1
+#define MAC_auto		2
+#define MAC_trusted     	4
+#define MAC_write_up		8
+#define MAC_read_up		16
+#define MAC_write_down		32
+#define MAC_allow_auto		64
+#define MAC_prop_trusted	128
+#define MAC_program_auto	256
+
+#define RSBAC_MAC_U_FLAGS (MAC_override | MAC_trusted | MAC_write_up | MAC_read_up | MAC_write_down | MAC_allow_auto)
+#define RSBAC_MAC_P_FLAGS (MAC_override | MAC_auto | MAC_trusted | MAC_write_up | MAC_read_up | MAC_write_down | MAC_prop_trusted | MAC_program_auto)
+#define RSBAC_MAC_F_FLAGS (MAC_auto | MAC_trusted | MAC_write_up | MAC_read_up | MAC_write_down)
+
+#define RSBAC_MAC_DEF_U_FLAGS 0
+#define RSBAC_MAC_DEF_SYSADM_U_FLAGS MAC_allow_auto
+#define RSBAC_MAC_DEF_SECOFF_U_FLAGS MAC_override
+
+#define RSBAC_MAC_DEF_P_FLAGS 0
+#define RSBAC_MAC_DEF_INIT_P_FLAGS MAC_auto
+
+typedef rsbac_enum_t rsbac_mac_auto_int_t;
+enum    rsbac_mac_auto_t {MA_no, MA_yes, MA_inherit};
+
+/* DAZ */
+typedef __u8 rsbac_daz_scanned_t;
+#define DAZ_unscanned 0
+#define DAZ_infected 1
+#define DAZ_clean 2
+#define DAZ_max 2
+#define DEFAULT_DAZ_FD_SCANNED DAZ_unscanned
+typedef __u8 rsbac_daz_scanner_t;
+typedef __u8 rsbac_daz_do_scan_t;
+#define DAZ_never 0
+#define DAZ_registered 1
+#define DAZ_always 2
+#define DAZ_inherit 3
+#define DAZ_max_do_scan 3
+#define DEFAULT_DAZ_FD_DO_SCAN DAZ_inherit
+#define DEFAULT_DAZ_FD_ROOT_DO_SCAN DAZ_registered
+
+/* FF */
+
+typedef __u16 rsbac_ff_flags_t;
+#define FF_read_only       1
+#define FF_execute_only    2
+#define FF_search_only     4
+#define FF_write_only      8
+#define FF_secure_delete  16
+#define FF_no_execute     32
+#define FF_no_delete_or_rename 64
+#define FF_append_only   256
+#define FF_no_mount      512
+#define FF_no_search     1024
+
+#define FF_add_inherited 128
+
+#define RSBAC_FF_DEF FF_add_inherited
+#define RSBAC_FF_ROOT_DEF 0
+
+/***** RC *****/
+
+#include <rsbac/rc_types.h>
+
+/**** AUTH ****/
+/* special cap value, replaced by process owner at execute time */
+#define RSBAC_AUTH_MAX_MAXNUM 1000000
+#define RSBAC_AUTH_OWNER_F_CAP ((rsbac_uid_num_t) -3)
+#define RSBAC_AUTH_DAC_OWNER_F_CAP ((rsbac_uid_num_t) -4)
+#define RSBAC_AUTH_MAX_RANGE_UID ((rsbac_uid_num_t) -10)
+#define RSBAC_AUTH_GROUP_F_CAP ((rsbac_uid_num_t) -3)
+#define RSBAC_AUTH_DAC_GROUP_F_CAP ((rsbac_uid_num_t) -4)
+#define RSBAC_AUTH_MAX_RANGE_GID ((rsbac_uid_num_t) -10)
+typedef struct rsbac_fs_file_t rsbac_auth_file_t;
+struct rsbac_auth_cap_range_t
+  {
+    rsbac_uid_t first;
+    rsbac_uid_t last;
+  };
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+struct rsbac_auth_cap_range_ia32_t
+  {
+    rsbac_uid_ia32_t first;
+    rsbac_uid_ia32_t last;
+  } __attribute__ ((aligned (4)));
+#endif
+struct rsbac_auth_old_cap_range_t
+  {
+    rsbac_old_uid_t first;
+    rsbac_old_uid_t last;
+  };
+enum    rsbac_auth_cap_type_t {ACT_real, ACT_eff, ACT_fs, 
+                               ACT_group_real, ACT_group_eff, ACT_group_fs,
+                               ACT_none};
+typedef rsbac_enum_t rsbac_auth_cap_type_int_t;
+
+enum    rsbac_auth_may_setuid_t {AMS_off, AMS_full, AMS_last_auth_only, 
+                               AMS_last_auth_and_gid, AMS_none};
+
+typedef rsbac_enum_t rsbac_auth_may_setuid_int_t;
+
+/**** ACL ****/
+/* include at end of types.h */
+
+/**** CAP ****/
+enum    rsbac_cap_process_hiding_t {PH_off, PH_from_other_users, PH_full,
+                              PH_none};
+typedef rsbac_enum_t rsbac_cap_process_hiding_int_t;
+
+enum rsbac_cap_ld_env_t { LD_deny, LD_allow, LD_keep, LD_inherit };
+typedef rsbac_enum_t rsbac_cap_ld_env_int_t;
+
+#define RSBAC_CAP_DEFAULT_MIN (__u32) 0
+#define RSBAC_CAP_DEFAULT_MAX (__u32) -1
+
+#include <linux/capability.h>
+#define CAP_NONE 34
+#define RSBAC_CAP_MAX CAP_NONE
+
+/**** JAIL ****/
+
+#define RSBAC_JAIL_VERSION 1
+
+typedef __u32 rsbac_jail_id_t;
+#define RSBAC_JAIL_DEF_ID 0
+typedef __u32 rsbac_jail_ip_t;
+typedef __u32 rsbac_jail_scd_vector_t;
+
+typedef __u32 rsbac_jail_flags_t;
+#define JAIL_allow_external_ipc 1
+#define JAIL_allow_all_net_family 2
+#define JAIL_allow_inet_raw 8
+#define JAIL_auto_adjust_inet_any 16
+#define JAIL_allow_inet_localhost 32
+#define JAIL_allow_dev_get_status 128
+#define JAIL_allow_dev_mod_system 256
+#define JAIL_allow_dev_read 512
+#define JAIL_allow_dev_write 1024
+#define JAIL_allow_tty_open 2048
+#define JAIL_allow_parent_ipc 4096
+#define JAIL_allow_suid_files 8192
+#define JAIL_allow_mount 16384
+#define JAIL_this_is_syslog 32768
+#define JAIL_allow_ipc_to_syslog 65536
+#define JAIL_allow_netlink 131072
+#define JAIL_allow_netdev_mod_system 262144
+
+#define RSBAC_JAIL_LOCALHOST ((1 << 24) | 127)
+
+/**** PAX ****/
+
+typedef unsigned long rsbac_pax_flags_t;
+
+/* for PaX defines */
+#ifdef __KERNEL__
+#include <linux/elf.h>
+#include <linux/random.h>
+#endif
+#ifndef PF_PAX_PAGEEXEC
+#define PF_PAX_PAGEEXEC	0x01000000	/* Paging based non-executable pages */
+#define PF_PAX_EMUTRAMP	0x02000000	/* Emulate trampolines */
+#define PF_PAX_MPROTECT	0x04000000	/* Restrict mprotect() */
+#define PF_PAX_RANDMMAP	0x08000000	/* Randomize mmap() base */
+#define PF_PAX_RANDEXEC	0x10000000	/* Randomize ET_EXEC base */
+#define PF_PAX_SEGMEXEC	0x20000000	/* Segmentation based non-executable pages */
+#endif
+
+#define RSBAC_PAX_DEF_FLAGS (PF_PAX_SEGMEXEC | PF_PAX_PAGEEXEC | PF_PAX_MPROTECT | PF_PAX_RANDMMAP)
+#define RSBAC_PAX_ALL_FLAGS ((rsbac_pax_flags_t) 255 << 24)
+
+/**** UM User management ****/
+/* Included from um_types.h */
+
+/**** RES ****/
+
+typedef __u32 rsbac_res_limit_t;
+#define RSBAC_RES_UNSET 0
+
+#define RSBAC_RES_MAX 10 /* RLIMIT_LOCKS in 2.4.x kernels */
+#define RSBAC_RES_NONE 11
+
+typedef rsbac_res_limit_t rsbac_res_array_t[RSBAC_RES_MAX + 1];
+
+/**** REG ****/
+typedef __s32 rsbac_reg_handle_t;
+
+/* UDF */
+typedef __u8 rsbac_udf_checked_t;
+#define UDF_unchecked 0
+#define UDF_denied 1
+#define UDF_allowed 2
+#define UDF_max 2
+#define DEFAULT_UDF_FD_CHECKED UDF_unchecked
+typedef __u8 rsbac_udf_checker_t;
+typedef __u8 rsbac_udf_do_check_t;
+#define UDF_never 0
+#define UDF_always 1
+#define UDF_inherit 2
+#define UDF_max_do_check 2
+#define DEFAULT_UDF_FD_DO_CHECK UDF_inherit
+#define DEFAULT_UDF_FD_ROOT_DO_CHECK UDF_never
+#define RSBAC_UDF_PATH_MAX 4096
+#define UDF_res_allow 0
+#define UDF_res_deny 1
+#define UDF_res_temp_fail_allow 254
+#define UDF_res_temp_fail_deny 255
+
+
+/****************************************************************************/
+/* ADF types                                                                */
+/****************************************************************************/
+
+#include <rsbac/network_types.h>
+
+#ifdef __KERNEL__
+    typedef struct socket * rsbac_net_obj_id_t;
+#else
+    typedef void * rsbac_net_obj_id_t;
+#endif
+
+struct rsbac_net_obj_desc_t
+  {
+    rsbac_net_obj_id_t sock_p;
+    void * local_addr;
+    u_int  local_len;
+    void * remote_addr;
+    u_int  remote_len;
+    rsbac_net_temp_id_t local_temp;
+    rsbac_net_temp_id_t remote_temp;
+  };
+
+#define RSBAC_ADF_REQUEST_ARRAY_VERSION 2
+
+enum  rsbac_adf_request_t {
+                        R_ADD_TO_KERNEL,
+                        R_ALTER,
+                        R_APPEND_OPEN,
+                        R_CHANGE_GROUP,
+                        R_CHANGE_OWNER,
+                        R_CHDIR,
+                        R_CLONE,
+                        R_CLOSE,
+                        R_CREATE,
+                        R_DELETE,
+                        R_EXECUTE,
+                        R_GET_PERMISSIONS_DATA,
+                        R_GET_STATUS_DATA,
+                        R_LINK_HARD,
+                        R_MODIFY_ACCESS_DATA,
+                        R_MODIFY_ATTRIBUTE,
+                        R_MODIFY_PERMISSIONS_DATA,
+                        R_MODIFY_SYSTEM_DATA,
+                        R_MOUNT,
+                        R_READ,
+                        R_READ_ATTRIBUTE,
+                        R_READ_WRITE_OPEN,
+                        R_READ_OPEN,
+                        R_REMOVE_FROM_KERNEL,
+                        R_RENAME,
+                        R_SEARCH,
+                        R_SEND_SIGNAL,
+                        R_SHUTDOWN,
+                        R_SWITCH_LOG,
+                        R_SWITCH_MODULE,
+                        R_TERMINATE,
+                        R_TRACE,
+                        R_TRUNCATE,
+                        R_UMOUNT,
+                        R_WRITE,
+                        R_WRITE_OPEN,
+                        R_MAP_EXEC,
+                        R_BIND,
+                        R_LISTEN,
+                        R_ACCEPT,
+                        R_CONNECT,
+                        R_SEND,
+                        R_RECEIVE,
+                        R_NET_SHUTDOWN,
+                        R_CHANGE_DAC_EFF_OWNER,
+                        R_CHANGE_DAC_FS_OWNER,
+                        R_CHANGE_DAC_EFF_GROUP,
+                        R_CHANGE_DAC_FS_GROUP,
+                        R_IOCTL,
+                        R_LOCK,
+                        R_AUTHENTICATE,
+                        R_MOVETO,
+                        R_NONE
+                      };
+
+typedef rsbac_enum_t rsbac_adf_request_int_t;
+
+#include <rsbac/request_groups.h>
+
+/* This type is returned from the rsbac_adf_request() function. Since a */
+/* decision of undefined means an error, it is never returned.          */
+
+enum  rsbac_adf_req_ret_t {NOT_GRANTED,GRANTED,DO_NOT_CARE,UNDEFINED};
+
+/****************************************************************************/
+/* ACI types                                                                */
+/****************************************************************************/
+
+/* For switching adf-modules */
+enum  rsbac_switch_target_t {SW_GEN,SW_MAC,SW_UDF,SW_DAZ,SW_FF,SW_RC,SW_AUTH,
+			SW_REG,SW_ACL,SW_CAP,SW_JAIL,SW_RES,SW_PAX,SW_SOFTMODE,
+			SW_DAC_DISABLE,SW_UM,SW_FREEZE,SW_NONE};
+#define RSBAC_MAX_MOD (SW_SOFTMODE - 1)
+typedef rsbac_enum_t rsbac_switch_target_int_t;
+
+/****************************************************************************/
+/* For objects, users and processes all manipulation is encapsulated by the */
+/* function calls rsbac_set_attr, rsbac_get_attr and rsbac_remove_target.   */
+
+/* For those, we declare some extra types to specify target and attribute.  */
+
+enum   rsbac_target_t {T_FILE, T_DIR, T_FIFO, T_SYMLINK, T_DEV, T_IPC, T_SCD, T_USER, T_PROCESS,
+                       T_NETDEV, T_NETTEMP, T_NETOBJ, T_NETTEMP_NT, T_GROUP,
+                       T_FD, T_UNIXSOCK,
+                       T_NONE};
+
+union  rsbac_target_id_t
+       {
+#ifdef __KERNEL__
+          struct rsbac_fs_file_t    file;
+          struct rsbac_fs_file_t    dir;
+          struct rsbac_fs_file_t    fifo;
+          struct rsbac_fs_file_t    symlink;
+          struct rsbac_fs_file_t    unixsock;
+#endif
+          struct rsbac_dev_desc_t   dev;
+          struct rsbac_ipc_t        ipc;
+          rsbac_enum_t              scd;
+          rsbac_uid_t               user;
+          rsbac_gid_t               group;
+          rsbac_pid_t               process; /* new struct pid * */
+          rsbac_upid_t              uprocess; /* old fashioned pid from user space */
+          rsbac_netdev_id_t         netdev;
+          rsbac_net_temp_id_t       nettemp;
+          struct rsbac_net_obj_desc_t netobj;
+          int                       dummy;
+       };
+
+#ifdef __KERNEL__
+typedef rsbac_enum_t rsbac_log_entry_t[T_NONE+1];
+typedef rsbac_enum_t rsbac_old_log_entry_t[T_NONE];
+
+struct rsbac_create_data_t
+  {
+    enum   rsbac_target_t   target;
+    struct dentry         * dentry_p;
+           int              mode;
+           kdev_t           device; /* for mknod etc. */
+  };
+
+struct rsbac_rlimit_t
+  {
+           u_int            resource;
+    struct rlimit           limit;
+  };
+#endif
+
+enum rsbac_attribute_t
+  {
+    A_pseudo,
+    A_security_level,
+    A_initial_security_level,
+    A_local_sec_level,
+    A_remote_sec_level,
+    A_min_security_level,
+    A_mac_categories,
+    A_mac_initial_categories,
+    A_local_mac_categories,
+    A_remote_mac_categories,
+    A_mac_min_categories,
+    A_mac_user_flags,
+    A_mac_process_flags,
+    A_mac_file_flags,
+    A_system_role,
+    A_mac_role,
+    A_daz_role,
+    A_ff_role,
+    A_auth_role,
+    A_cap_role,
+    A_jail_role,
+    A_pax_role,
+    A_current_sec_level,
+    A_mac_curr_categories,
+    A_min_write_open,
+    A_min_write_categories,
+    A_max_read_open,
+    A_max_read_categories,
+    A_mac_auto,
+    A_mac_check,
+    A_mac_prop_trusted,
+    A_pm_role,
+    A_pm_process_type,
+    A_pm_current_task,
+    A_pm_object_class,
+    A_local_pm_object_class,
+    A_remote_pm_object_class,
+    A_pm_ipc_purpose,
+    A_local_pm_ipc_purpose,
+    A_remote_pm_ipc_purpose,
+    A_pm_object_type,
+    A_local_pm_object_type,
+    A_remote_pm_object_type,
+    A_pm_program_type,
+    A_pm_tp,
+    A_pm_task_set,
+    A_daz_scanned,
+    A_daz_scanner,
+    A_ff_flags,
+    A_rc_type,
+    A_rc_select_type,
+    A_local_rc_type,
+    A_remote_rc_type,
+    A_rc_type_fd,
+    A_rc_type_nt,
+    A_rc_force_role,
+    A_rc_initial_role,
+    A_rc_role,
+    A_rc_def_role,
+    A_auth_may_setuid,
+    A_auth_may_set_cap,
+    A_auth_learn,
+    A_min_caps,
+    A_max_caps,
+    A_max_caps_user,
+    A_max_caps_program,
+    A_jail_id,
+    A_jail_parent,
+    A_jail_ip,
+    A_jail_flags,
+    A_jail_max_caps,
+    A_jail_scd_get,
+    A_jail_scd_modify,
+    A_pax_flags,
+    A_res_role,
+    A_res_min,
+    A_res_max,
+    A_log_array_low,
+    A_local_log_array_low,
+    A_remote_log_array_low,
+    A_log_array_high,
+    A_local_log_array_high,
+    A_remote_log_array_high,
+    A_log_program_based,
+    A_log_user_based,
+    A_symlink_add_remote_ip,
+    A_symlink_add_uid,
+    A_symlink_add_mac_level,
+    A_symlink_add_rc_role,
+    A_linux_dac_disable,
+    A_cap_process_hiding,
+    A_fake_root_uid,
+    A_audit_uid,
+    A_auid_exempt,
+    A_auth_last_auth,
+    A_remote_ip,
+    A_cap_ld_env,
+    A_daz_do_scan,
+    A_vset,
+    A_udf_role,
+    A_udf_checked,
+    A_udf_checker,
+    A_udf_do_check,
+#ifdef __KERNEL__
+    /* adf-request helpers */
+    A_owner,
+    A_group,
+    A_signal,
+    A_mode,
+    A_nlink,
+    A_switch_target,
+    A_mod_name,
+    A_request,
+    A_trace_request,
+    A_auth_add_f_cap,
+    A_auth_remove_f_cap,
+    A_auth_get_caplist,
+    A_prot_bits,
+    A_internal,
+    /* used with CREATE on DIR */
+    A_create_data,
+    A_new_object,
+    A_rlimit,
+    A_new_dir_dentry_p,
+    A_program_file,
+    A_auth_start_uid,
+    A_auth_start_euid,
+    A_auth_start_gid,
+    A_auth_start_egid,
+    A_acl_learn,
+    A_priority,
+    A_pgid,
+    A_kernel_thread,
+    A_open_flag,
+    A_reboot_cmd,
+    A_setsockopt_level,
+    A_ioctl_cmd,
+    A_f_mode,
+    A_process,
+    A_sock_type,
+    A_pagenr,
+    A_cap_learn,
+    A_rc_learn,
+    A_old_dir_inode_p,
+#endif
+    A_none};
+
+union rsbac_attribute_value_t
+  {
+         rsbac_uid_t                 owner;           /* process owner */
+         rsbac_pseudo_t              pseudo;
+         rsbac_system_role_int_t     system_role;
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_MAC)
+         rsbac_security_level_t      security_level;
+         rsbac_mac_category_vector_t mac_categories;
+         rsbac_security_level_t      current_sec_level;
+         rsbac_security_level_t      min_write_open;
+         rsbac_security_level_t      max_read_open;
+         rsbac_mac_user_flags_t      mac_user_flags;
+         rsbac_mac_process_flags_t   mac_process_flags;
+         rsbac_mac_file_flags_t      mac_file_flags;
+         rsbac_mac_auto_int_t        mac_auto;
+         rsbac_boolean_t             mac_check;
+         rsbac_boolean_t             mac_prop_trusted;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_DAZ)
+         rsbac_daz_scanned_t         daz_scanned;
+         rsbac_daz_scanner_t         daz_scanner;
+         rsbac_daz_do_scan_t         daz_do_scan;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_FF)
+         rsbac_ff_flags_t            ff_flags;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_RC)
+         rsbac_rc_type_id_t          rc_type;
+         rsbac_rc_type_id_t          rc_type_fd;
+         rsbac_rc_role_id_t          rc_force_role;
+         rsbac_rc_role_id_t          rc_initial_role;
+         rsbac_rc_role_id_t          rc_role;
+         rsbac_rc_role_id_t          rc_def_role;
+         rsbac_rc_type_id_t          rc_select_type;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_AUTH)
+         rsbac_auth_may_setuid_int_t auth_may_setuid;
+         rsbac_boolean_t             auth_may_set_cap;
+         rsbac_pid_t                 auth_p_capset;
+         rsbac_inode_nr_t            auth_f_capset;
+         rsbac_boolean_t             auth_learn;
+         rsbac_uid_t                 auth_last_auth;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_CAP)
+         rsbac_cap_vector_t          min_caps;
+         rsbac_cap_vector_t          max_caps;
+         rsbac_cap_vector_t          max_caps_user;
+         rsbac_cap_vector_t          max_caps_program;
+         rsbac_cap_process_hiding_int_t cap_process_hiding;
+         rsbac_cap_ld_env_int_t      cap_ld_env;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_JAIL)
+         rsbac_jail_id_t             jail_id;
+         rsbac_jail_id_t             jail_parent;
+         rsbac_jail_ip_t             jail_ip;
+         rsbac_jail_flags_t          jail_flags;
+         rsbac_jail_scd_vector_t     jail_scd_get;
+         rsbac_jail_scd_vector_t     jail_scd_modify;
+         rsbac_cap_vector_t          jail_max_caps;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_PAX)
+         rsbac_pax_flags_t           pax_flags;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_RES)
+         rsbac_res_array_t           res_array;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_UDF)
+         rsbac_udf_checked_t         udf_checked;
+         rsbac_udf_checker_t         udf_checker;
+         rsbac_udf_do_check_t        udf_do_check;
+#endif
+         rsbac_log_array_t           log_array_low;
+         rsbac_log_array_t           log_array_high;
+         rsbac_request_vector_t      log_program_based;
+         rsbac_request_vector_t      log_user_based;
+         rsbac_enum_t                symlink_add_remote_ip;
+         rsbac_boolean_t             symlink_add_uid;
+         rsbac_boolean_t             symlink_add_mac_level;
+         rsbac_boolean_t             symlink_add_rc_role;
+         rsbac_linux_dac_disable_int_t linux_dac_disable;
+//         rsbac_net_temp_id_t         net_temp;
+         rsbac_fake_root_uid_int_t   fake_root_uid;
+         rsbac_uid_t                 audit_uid;
+         rsbac_uid_t                 auid_exempt;
+         __u32                       remote_ip;
+         rsbac_um_set_t              vset;
+#ifdef __KERNEL__
+         rsbac_gid_t     	     group;        /* process/fd group */
+    struct sockaddr                * sockaddr_p; /* socket address */
+         int                         signal;        /* signal for kill */
+         int                         mode;    /* mode for create/mount */
+         int                         nlink;       /* for DELETE/unlink */
+    enum rsbac_switch_target_t       switch_target; /* for SWITCH_MODULE */
+         char                      * mod_name;    /* for ADD_TO_KERNEL */
+    enum rsbac_adf_request_t         request;        /* for SWITCH_LOG */
+         long                        trace_request; /* request for sys_trace */
+    struct rsbac_auth_cap_range_t    auth_cap_range;
+    	 int                         prot_bits;/* prot bits for mmap()/mprotect() */
+         rsbac_boolean_t             internal;
+    /* used with CREATE on DIR */
+    struct rsbac_create_data_t       create_data;
+    /* newly created object in OPEN requests? */
+         rsbac_boolean_t             new_object;
+    struct rsbac_rlimit_t            rlimit;
+         struct dentry             * new_dir_dentry_p;
+         struct rsbac_fs_file_t      program_file; /* for logging and learning mode */
+         rsbac_uid_t                 auth_start_uid;
+         rsbac_uid_t                 auth_start_euid;
+         rsbac_gid_t                 auth_start_gid;
+         rsbac_gid_t                 auth_start_egid;
+         rsbac_boolean_t             acl_learn;
+         int                         priority;
+         rsbac_pid_t                 pgid;
+         rsbac_boolean_t             kernel_thread;
+         u_int                       open_flag;
+         u_int                       reboot_cmd;
+         int                         setsockopt_level;
+         u_int                       ioctl_cmd;
+         mode_t                      f_mode;
+         rsbac_pid_t                 process;
+         short                       sock_type;
+         u_int                       pagenr;
+         rsbac_boolean_t             cap_learn;
+         rsbac_boolean_t             rc_learn;
+         struct inode              * old_dir_inode_p;
+#endif
+         u_char                      u_char_dummy;
+         u_short                     u_short_dummy;
+         int                         dummy;
+         u_int                       u_dummy;
+         long                        long_dummy;
+         u_long                      u_long_dummy;
+       };
+
+/* List all values possibly used in FD Cache to find data size */
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+union rsbac_attribute_value_cache_t
+  {
+         rsbac_uid_t                 owner;           /* process owner */
+         rsbac_pseudo_t              pseudo;
+         rsbac_system_role_int_t     system_role;
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_MAC)
+         rsbac_security_level_t      security_level;
+         rsbac_mac_category_vector_t mac_categories;
+         rsbac_security_level_t      current_sec_level;
+         rsbac_security_level_t      min_write_open;
+         rsbac_security_level_t      max_read_open;
+         rsbac_mac_user_flags_t      mac_user_flags;
+         rsbac_mac_process_flags_t   mac_process_flags;
+         rsbac_mac_file_flags_t      mac_file_flags;
+         rsbac_mac_auto_int_t        mac_auto;
+         rsbac_boolean_t             mac_check;
+         rsbac_boolean_t             mac_prop_trusted;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_DAZ)
+         rsbac_daz_scanned_t         daz_scanned;
+         rsbac_daz_scanner_t         daz_scanner;
+         rsbac_daz_do_scan_t         daz_do_scan;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_FF)
+         rsbac_ff_flags_t            ff_flags;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_RC)
+         rsbac_rc_type_id_t          rc_type;
+         rsbac_rc_type_id_t          rc_type_fd;
+         rsbac_rc_role_id_t          rc_force_role;
+         rsbac_rc_role_id_t          rc_initial_role;
+         rsbac_rc_role_id_t          rc_role;
+         rsbac_rc_role_id_t          rc_def_role;
+         rsbac_rc_type_id_t          rc_select_type;
+#endif
+#if !defined(__KERNEL__) || defined(CONFIG_RSBAC_UDF)
+         rsbac_udf_checked_t         udf_checked;
+         rsbac_udf_checker_t         udf_checker;
+         rsbac_udf_do_check_t        udf_do_check;
+#endif
+         rsbac_log_array_t           log_array_low;
+         rsbac_log_array_t           log_array_high;
+         rsbac_request_vector_t      log_program_based;
+         rsbac_request_vector_t      log_user_based;
+         rsbac_enum_t                symlink_add_remote_ip;
+         rsbac_boolean_t             symlink_add_uid;
+         rsbac_boolean_t             symlink_add_mac_level;
+         rsbac_boolean_t             symlink_add_rc_role;
+         rsbac_linux_dac_disable_int_t linux_dac_disable;
+//         rsbac_net_temp_id_t         net_temp;
+         rsbac_fake_root_uid_int_t   fake_root_uid;
+         rsbac_uid_t                 audit_uid;
+         rsbac_uid_t                 auid_exempt;
+         __u32                       remote_ip;
+         rsbac_um_set_t              vset;
+         u_char                      u_char_dummy;
+         u_short                     u_short_dummy;
+         int                         dummy;
+         u_int                       u_dummy;
+         long                        long_dummy;
+         u_long                      u_long_dummy;
+       };
+#endif
+
+/**** ACL + UM ****/
+
+#include <rsbac/acl_types.h>
+#include <rsbac/um_types.h>
+
+/* not aligned, yet */
+struct rsbac_rw_req {
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	enum rsbac_adf_request_t rsbac_request;
+};
+
+int rsbac_handle_rw_req(const struct file *file, struct rsbac_rw_req *rsbac_rw_req_obj);
+int rsbac_handle_rw_up(struct rsbac_rw_req *rsbac_rw_req_obj);
+
+#endif
+
diff --git a/include/rsbac/udf.h b/include/rsbac/udf.h
new file mode 100644
index 0000000..67be094
--- /dev/null
+++ b/include/rsbac/udf.h
@@ -0,0 +1,27 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2013: Amon Ott */
+/* API:                               */
+/* Functions for Access               */
+/* Control Information / UDF          */
+/* Last modified: 18/Nov/2013         */
+/************************************ */
+
+#ifndef __RSBAC_UDF_H
+#define __RSBAC_UDF_H
+
+#include <rsbac/types.h>
+
+/* Get ttl for new cache items in seconds */
+/* This function returns 0, if no cache is available, and the ttl value
+   otherwise */
+rsbac_time_t rsbac_udf_get_ttl(void);
+
+/* Set ttl for new cache items in seconds */
+/* ttl must be positive, values bigger than 10 years in seconds
+   (RSBAC_LIST_MAX_AGE_LIMIT in lists.h) are reduced to this limit */
+void rsbac_udf_set_ttl(rsbac_time_t ttl);
+
+/* Flush DAZuko cache lists */
+int rsbac_udf_flush_cache(void);
+#endif
diff --git a/include/rsbac/um.h b/include/rsbac/um.h
new file mode 100644
index 0000000..b7b6e6e
--- /dev/null
+++ b/include/rsbac/um.h
@@ -0,0 +1,178 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2011:          */
+/*   Amon Ott <ao@rsbac.org>          */
+/* API: Data structures               */
+/* and functions for User Management  */
+/* Last modified: 19/Apt/2011         */
+/************************************ */
+
+#ifndef __RSBAC_UM_H
+#define __RSBAC_UM_H
+
+#include <linux/init.h>
+#include <rsbac/types.h>
+#include <rsbac/um_types.h>
+
+/***************************************************/
+/*               General Prototypes                */
+/***************************************************/
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+/****************************************************************************/
+/* Initialization, including ACI restoration for all mounted devices from   */
+/* disk. After this call, all ACI is kept in memory for performance reasons,*/
+/* but user and file/dir object ACI are written to disk on every change.    */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+extern int rsbac_init_um(void);
+#else
+extern int rsbac_init_um(void) __init;
+#endif
+
+/* Some information about the current status is also available */
+extern int rsbac_stats_um(void);
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* Trying to access a never created or removed user entry returns an error! */
+
+/* rsbac_um_add_user (fills *user_p with new uid) */
+
+int rsbac_um_add_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t * user_p,
+  struct rsbac_um_user_entry_t * entry_p,
+  char * pass,
+  rsbac_time_t ttl);
+
+int rsbac_um_add_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t * group_p,
+  struct rsbac_um_group_entry_t * entry_p,
+  char * pass,
+  rsbac_time_t ttl);
+
+int rsbac_um_add_gm(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  rsbac_gid_num_t group,
+  rsbac_time_t ttl);
+
+int rsbac_um_mod_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t * data_p);
+
+int rsbac_um_mod_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t group,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t * data_p);
+
+int rsbac_um_get_user_item(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t * data_p);
+
+int rsbac_um_get_group_item(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t group,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t * data_p);
+
+int rsbac_um_user_exists(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user);
+
+int rsbac_um_group_exists(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t group);
+
+int rsbac_um_remove_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user);
+
+int rsbac_um_remove_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t group);
+
+int rsbac_um_remove_gm(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  rsbac_gid_num_t group);
+
+int rsbac_um_get_next_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t old_user,
+  rsbac_uid_t * next_user_p);
+
+int rsbac_um_get_user_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_um_set_t vset,
+  rsbac_uid_t ** list_pp);
+
+int rsbac_um_get_gm_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  rsbac_gid_num_t ** list_pp);
+
+int rsbac_um_get_gm_user_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t group,
+  rsbac_uid_num_t ** list_pp);
+
+int rsbac_um_get_group_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_um_set_t vset,
+  rsbac_gid_t ** list_pp);
+
+int rsbac_um_get_user_entry(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  struct rsbac_um_user_entry_t * entry_p,
+  rsbac_time_t * ttl_p);
+
+int rsbac_um_get_uid(
+  rsbac_list_ta_number_t ta_number,
+  char * name,
+  rsbac_uid_t * uid_p);
+
+int rsbac_um_get_gid(
+  rsbac_list_ta_number_t ta_number,
+  char * name,
+  rsbac_gid_t * gid_p);
+
+int rsbac_um_check_pass(rsbac_uid_t uid,
+                        char * pass);
+
+/* Check for good password (min length etc.) */
+int rsbac_um_good_pass(rsbac_uid_t uid, char * pass);
+
+#ifdef CONFIG_RSBAC_UM_ONETIME
+int rsbac_um_add_onetime(rsbac_uid_t uid, char * pass, rsbac_time_t ttl);
+
+int rsbac_um_remove_all_onetime(rsbac_uid_t uid);
+
+int rsbac_um_count_onetime(rsbac_uid_t uid);
+#endif
+
+int rsbac_um_set_pass(rsbac_uid_t uid,
+                      char * pass);
+
+int rsbac_um_set_group_pass(rsbac_gid_t gid,
+                            char * pass);
+
+int rsbac_um_check_account(rsbac_uid_t user);
+
+int rsbac_um_get_max_history(rsbac_list_ta_number_t ta_number, rsbac_uid_t uid);
+
+int rsbac_um_set_max_history(rsbac_list_ta_number_t ta_number, rsbac_uid_t uid, __u8 max_history);
+
+#endif
diff --git a/include/rsbac/um_types.h b/include/rsbac/um_types.h
new file mode 100644
index 0000000..b5e575b
--- /dev/null
+++ b/include/rsbac/um_types.h
@@ -0,0 +1,154 @@
+/**************************************/
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2016: Amon Ott */
+/* User Management Data structures    */
+/* Last modified: 17/Feb/2016         */
+/**************************************/
+
+#ifndef __RSBAC_UM_TYPES_H
+#define __RSBAC_UM_TYPES_H
+
+//#include <rsbac/types.h>
+
+#define RSBAC_UM_MAX_MAXNUM 1000000
+
+#define RSBAC_UM_USER_LIST_NAME  "um_user"
+#define RSBAC_UM_GROUP_LIST_NAME  "um_grp"
+#define RSBAC_UM_USER_PWHISTORY_LIST_NAME "um_pwh"
+#define RSBAC_UM_ONETIME_LIST_NAME "um_pwot"
+#define RSBAC_UM_UID_CACHE_LIST_NAME "um_uch"
+#define RSBAC_UM_GID_CACHE_LIST_NAME "um_gch"
+#define RSBAC_UM_OLD_USER_LIST_NAME  "um_u."
+#define RSBAC_UM_OLD_GROUP_LIST_NAME  "um_g."
+#define RSBAC_UM_OLD_USER_PWHISTORY_LIST_NAME "um_pwh."
+
+#define RSBAC_UM_NR_USER_LIST_HASH_BITS 3
+#define RSBAC_UM_NR_GROUP_LIST_HASH_BITS 3
+#define RSBAC_UM_NR_USER_PWHISTORY_LIST_HASH_BITS 3
+#define RSBAC_UM_NR_NAME_CACHE_LIST_HASH_BITS 2
+
+#define RSBAC_UM_USER_LIST_VERSION 3
+#define RSBAC_UM_GROUP_LIST_VERSION 3
+#define RSBAC_UM_USER_PWHISTORY_LIST_VERSION 2
+#define RSBAC_UM_ONETIME_LIST_VERSION 1
+#define RSBAC_UM_NAME_CACHE_LIST_VERSION 1
+
+#define RSBAC_UM_USER_OLD_LIST_VERSION 2
+#define RSBAC_UM_USER_OLD_OLD_LIST_VERSION 1
+#define RSBAC_UM_GROUP_OLD_LIST_VERSION 2
+#define RSBAC_UM_GROUP_OLD_OLD_LIST_VERSION 1
+#define RSBAC_UM_USER_PWHISTORY_OLD_LIST_VERSION 1
+
+#define RSBAC_UM_USER_LIST_KEY 6363636
+#define RSBAC_UM_GROUP_LIST_KEY 9847298
+#define RSBAC_UM_USER_PWHISTORY_LIST_KEY 8854687
+#define RSBAC_UM_ONETIME_LIST_KEY 63273279
+#define RSBAC_UM_UID_CACHE_LIST_KEY 129871376
+#define RSBAC_UM_GID_CACHE_LIST_KEY 129876363
+
+#define RSBAC_UM_NAME_LEN 65
+#define RSBAC_UM_OLD_NAME_LEN 16
+#define RSBAC_UM_PASS_LEN 24
+#define RSBAC_UM_FULLNAME_LEN 65
+#define RSBAC_UM_OLD_FULLNAME_LEN 30
+#define RSBAC_UM_HOMEDIR_LEN 101
+#define RSBAC_UM_OLD_HOMEDIR_LEN 50
+#define RSBAC_UM_SHELL_LEN 45
+#define RSBAC_UM_OLD_SHELL_LEN 24
+
+typedef __s32 rsbac_um_days_t;
+
+typedef char rsbac_um_password_t[RSBAC_UM_PASS_LEN];
+
+enum rsbac_um_mod_t { UM_name, UM_pass, UM_fullname, UM_homedir, UM_shell,
+	UM_group, UM_lastchange, UM_minchange, UM_maxchange,
+	UM_warnchange, UM_inactive, UM_expire, UM_ttl,
+	UM_cryptpass, UM_none
+};
+
+union rsbac_um_mod_data_t {
+	char string[RSBAC_MAXNAMELEN];
+	rsbac_gid_num_t group;
+	rsbac_um_days_t days;
+	rsbac_time_t ttl;
+};
+
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+union rsbac_um_mod_data_ia32_t {
+	char string[RSBAC_MAXNAMELEN];
+	rsbac_gid_num_t group;
+	rsbac_um_days_t days;
+	rsbac_time_t ttl;
+}__attribute__ ((aligned (4)));
+#endif
+
+struct rsbac_um_user_entry_t {
+	rsbac_gid_num_t group;
+	rsbac_um_days_t lastchange;
+	rsbac_um_days_t minchange;
+	rsbac_um_days_t maxchange;
+	rsbac_um_days_t warnchange;
+	rsbac_um_days_t inactive;
+	rsbac_um_days_t expire;
+	char name[RSBAC_UM_NAME_LEN];
+	char pass[RSBAC_UM_PASS_LEN];
+	char fullname[RSBAC_UM_FULLNAME_LEN];
+	char homedir[RSBAC_UM_HOMEDIR_LEN];
+	char shell[RSBAC_UM_SHELL_LEN];
+};
+
+struct rsbac_um_old_user_entry_t {
+	char name[RSBAC_UM_OLD_NAME_LEN];
+	char pass[RSBAC_UM_PASS_LEN];
+	char fullname[RSBAC_UM_OLD_FULLNAME_LEN];
+	char homedir[RSBAC_UM_OLD_HOMEDIR_LEN];
+	char shell[RSBAC_UM_OLD_SHELL_LEN];
+	rsbac_gid_num_t group;
+	rsbac_um_days_t lastchange;
+	rsbac_um_days_t minchange;
+	rsbac_um_days_t maxchange;
+	rsbac_um_days_t warnchange;
+	rsbac_um_days_t inactive;
+	rsbac_um_days_t expire;
+};
+
+#define DEFAULT_UM_U_ENTRY \
+    { \
+      65534,  /* group */ \
+      100000,  /* lastchange */ \
+      0,  /* minchange */ \
+      365,  /* maxchange */ \
+      10,  /* warnchange */ \
+      3,  /* inactive */ \
+      100000,   /* expire */ \
+      "", /* name */ \
+      "", /* pass */ \
+      "", /* fullname */ \
+      "/home", /* homedir */ \
+      "/bin/sh" /* shell */ \
+    }
+
+struct rsbac_um_group_entry_t {
+	char name[RSBAC_UM_NAME_LEN];
+	char pass[RSBAC_UM_PASS_LEN];
+};
+
+struct rsbac_um_old_group_entry_t {
+	char name[RSBAC_UM_OLD_NAME_LEN];
+	char pass[RSBAC_UM_PASS_LEN];
+};
+
+#if defined(CONFIG_RSBAC_UM_NAME_CACHE) && defined(CONFIG_RSBAC_UM_VIRTUAL)
+struct rsbac_um_name_cache_desc_t {
+	char name[RSBAC_UM_NAME_LEN];
+	rsbac_um_set_t vset;
+};
+#endif
+
+#define DEFAULT_UM_G_ENTRY \
+    { \
+      "", /* name */ \
+      ""  /* pass */ \
+    }
+
+#endif
diff --git a/include/rsbac/unistd-alpha.h b/include/rsbac/unistd-alpha.h
new file mode 100644
index 0000000..d6014f2
--- /dev/null
+++ b/include/rsbac/unistd-alpha.h
@@ -0,0 +1,16 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2002: Amon Ott */
+/* System Call definitions - alpha    */
+/* Last modified: 20/Mar/2002         */
+/************************************ */
+
+#ifndef __RSBAC_UNISTD_ALPHA_H
+#define __RSBAC_UNISTD_ALPHA_H
+
+#ifndef __NR_security
+#define __NR_security 380
+#endif
+#define __NR_rsbac __NR_security
+
+#endif
diff --git a/include/rsbac/unistd-i386.h b/include/rsbac/unistd-i386.h
new file mode 100644
index 0000000..5d600fb
--- /dev/null
+++ b/include/rsbac/unistd-i386.h
@@ -0,0 +1,16 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2002: Amon Ott */
+/* System Call definitions - i386     */
+/* Last modified: 20/Mar/2002         */
+/************************************ */
+
+#ifndef __RSBAC_UNISTD_I386_H
+#define __RSBAC_UNISTD_I386_H
+
+#ifndef __NR_security
+#define __NR_security 223
+#endif
+#define __NR_rsbac __NR_security
+
+#endif
diff --git a/include/rsbac/unistd-ppc.h b/include/rsbac/unistd-ppc.h
new file mode 100644
index 0000000..cab4714
--- /dev/null
+++ b/include/rsbac/unistd-ppc.h
@@ -0,0 +1,16 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/* Author and (c) 1999-2002: Amon Ott */
+/* System Call definitions - i386     */
+/* Last modified: 07/Apr/2002         */
+/************************************ */
+
+#ifndef __RSBAC_UNISTD_PPC_H
+#define __RSBAC_UNISTD_PPC_H
+
+#ifndef __NR_security
+#define __NR_security 220
+#endif
+#define __NR_rsbac __NR_security
+
+#endif
diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h
index cc89dde..b4c4e8a 100644
--- a/include/uapi/linux/sched.h
+++ b/include/uapi/linux/sched.h
@@ -29,6 +29,9 @@
 #define CLONE_NEWPID		0x20000000	/* New pid namespace */
 #define CLONE_NEWNET		0x40000000	/* New network namespace */
 #define CLONE_IO		0x80000000	/* Clone io context */
+#ifdef CONFIG_RSBAC
+#define CLONE_KTHREAD           0x100000000ULL  /* clone a kernel thread */
+#endif
 
 /*
  * Scheduling policies
diff --git a/init/do_mounts.c b/init/do_mounts.c
index a95bbdb..c3a367a 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -35,6 +35,14 @@
 
 #include "do_mounts.h"
 
+#ifdef CONFIG_RSBAC
+#include <rsbac/aci.h>
+#include <rsbac/debug.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/initrd.h>
+#endif
+#endif
+
 int __initdata rd_doload;	/* 1 = load RAM disk, 0 = don't load */
 
 int root_mountflags = MS_RDONLY | MS_SILENT;
@@ -597,6 +605,14 @@ out:
 	devtmpfs_mount("dev");
 	sys_mount(".", "/", NULL, MS_MOVE, NULL);
 	sys_chroot(".");
+
+#ifdef CONFIG_RSBAC
+#ifdef CONFIG_RSBAC_INIT_DELAY
+        if(rsbac_no_delay_init)
+#endif
+        rsbac_init(ROOT_DEV);
+#endif
+
 }
 
 static bool is_tmpfs;
diff --git a/init/main.c b/init/main.c
index 2a89545..a96c9d0 100644
--- a/init/main.c
+++ b/init/main.c
@@ -88,6 +88,8 @@
 #include <asm/sections.h>
 #include <asm/cacheflush.h>
 
+#include <rsbac/hooks.h>
+
 static int kernel_init(void *);
 
 extern void init_IRQ(void);
@@ -651,6 +653,9 @@ asmlinkage __visible void __init start_kernel(void)
 	key_init();
 	security_init();
 	dbg_late_init();
+#ifdef CONFIG_RSBAC
+	rsbac_kthreads_init();
+#endif
 	vfs_caches_init(totalram_pages);
 	signals_init();
 	/* rootfs populating might need page-writeback */
diff --git a/ipc/msg.c b/ipc/msg.c
index 55730c7..8ee1c70 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -41,6 +41,7 @@
 #include <asm/current.h>
 #include <linux/uaccess.h>
 #include "util.h"
+#include <rsbac/hooks.h>
 
 /* one msg_receiver structure for each sleeping receiver */
 struct msg_receiver {
@@ -123,6 +124,27 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
 	key_t key = params->key;
 	int msgflg = params->flg;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_msgget()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_msg;
+	rsbac_target_id.ipc.id.id_nr = 0;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	msq = ipc_rcu_alloc(sizeof(*msq));
 	if (!msq)
 		return -ENOMEM;
@@ -153,6 +175,24 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
 		return id;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.ipc.type = I_msg;
+	rsbac_target_id.ipc.id.id_nr = msq->q_perm.id;
+	rsbac_new_target_id.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_none,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"newque() [sys_msgget()]: rsbac_adf_set_attr() returned error");
+	}
+#endif
+
+
 	ipc_unlock_object(&msq->q_perm);
 	rcu_read_unlock();
 
@@ -343,6 +383,11 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
 	struct msqid64_ds uninitialized_var(msqid64);
 	struct msg_queue *msq;
 	int err;
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	if (cmd == IPC_SET) {
 		if (copy_msqid_from_user(&msqid64, buf, version))
@@ -367,9 +412,40 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
 
 	switch (cmd) {
 	case IPC_RMID:
+#ifdef CONFIG_RSBAC
+		rsbac_target_id.ipc.type = I_msg;
+		rsbac_target_id.ipc.id.id_nr = msqid;
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_DELETE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			err = -EPERM;
+			goto out_unlock1;
+		}
+#endif
+
 		ipc_lock_object(&msq->q_perm);
 		/* freeque unlocks the ipc object and rcu */
 		freeque(ns, ipcp);
+
+#ifdef CONFIG_RSBAC
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_DELETE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_msgctl(): rsbac_adf_set_attr() returned error");
+		}
+#endif
 		goto out_up;
 	case IPC_SET:
 		if (msqid64.msg_qbytes > ns->msg_ctlmnb &&
@@ -378,6 +454,50 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
 			goto out_unlock1;
 		}
 
+#ifdef CONFIG_RSBAC
+		rsbac_target_id.ipc.type = I_msg;
+		rsbac_target_id.ipc.id.id_nr = msqid;
+		if (__kuid_val(ipcp->uid) != msqid64.msg_perm.uid) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.owner = msqid64.msg_perm.uid;
+			if (!rsbac_adf_request(R_CHANGE_OWNER,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						A_owner,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+				goto out_unlock1;
+			}
+		}
+		if (__kgid_val(ipcp->gid) != msqid64.msg_perm.gid) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.group = msqid64.msg_perm.gid;
+			if (!rsbac_adf_request(R_CHANGE_GROUP,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						A_group,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+				goto out_unlock1;
+			}
+		}
+		if (ipcp->mode != ((ipcp->mode & ~S_IRWXUGO) | (S_IRWXUGO & msqid64.msg_perm.mode))) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.mode = (S_IRWXUGO & msqid64.msg_perm.mode);
+			if (!rsbac_adf_request(R_ALTER,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						A_mode,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+				goto out_unlock1;
+			}
+		}
+#endif
+
 		ipc_lock_object(&msq->q_perm);
 		err = ipc_update_perm(&msqid64.msg_perm, ipcp);
 		if (err)
@@ -612,6 +732,12 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
 	int err;
 	struct ipc_namespace *ns;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	ns = current->nsproxy->ipc_ns;
 
 	if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
@@ -619,6 +745,21 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
 	if (mtype < 1)
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.ipc.type   = I_msg;
+	rsbac_target_id.ipc.id.id_nr  = msqid;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_SEND,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	msg = load_msg(mtext, msgsz);
 	if (IS_ERR(msg))
 		return PTR_ERR(msg);
@@ -705,6 +846,21 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
 		atomic_inc(&ns->msg_hdrs);
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_new_target_id.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_SEND,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_none,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"sys_msgsnd(): rsbac_adf_set_attr() returned error");
+	}
+#endif
+
 	err = 0;
 	msg = NULL;
 
@@ -831,11 +987,32 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
 	struct ipc_namespace *ns;
 	struct msg_msg *msg, *copy = NULL;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	ns = current->nsproxy->ipc_ns;
 
 	if (msqid < 0 || (long) bufsz < 0)
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.ipc.type   = I_msg;
+	rsbac_target_id.ipc.id.id_nr  = msqid;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_RECEIVE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	if (msgflg & MSG_COPY) {
 		if ((msgflg & MSG_EXCEPT) || !(msgflg & IPC_NOWAIT))
 			return -EINVAL;
@@ -878,6 +1055,23 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
 				msg = ERR_PTR(-E2BIG);
 				goto out_unlock0;
 			}
+
+	                /* RSBAC: notify ADF of opened ipc */
+#ifdef CONFIG_RSBAC
+			rsbac_new_target_id.dummy = 0;
+			if (unlikely(rsbac_adf_set_attr(R_RECEIVE,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_none,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_msgrcv(): rsbac_adf_set_attr() returned error");
+			}
+#endif
+
 			/*
 			 * If we are copying, then do not unlink message and do
 			 * not update queue parameters.
diff --git a/ipc/sem.c b/ipc/sem.c
index 534caee..8a93a9f 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -88,6 +88,7 @@
 
 #include <linux/uaccess.h>
 #include "util.h"
+#include <rsbac/hooks.h>
 
 /* One semaphore structure for each semaphore in the system. */
 struct sem {
@@ -502,11 +503,32 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 	int semflg = params->flg;
 	int i;
 
+#ifdef CONFIG_RSBAC_IPC_SEM
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!nsems)
 		return -EINVAL;
 	if (ns->used_sems + nsems > ns->sc_semmns)
 		return -ENOSPC;
 
+#ifdef CONFIG_RSBAC_IPC_SEM
+	rsbac_pr_debug(aef, "[sys_semget()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_sem;
+	rsbac_target_id.ipc.id.id_nr = 0;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	size = sizeof(*sma) + nsems * sizeof(struct sem);
 	sma = ipc_rcu_alloc(size);
 	if (!sma)
@@ -546,6 +568,22 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
 	}
 	ns->used_sems += nsems;
 
+/* RSBAC: notify ADF of new shm */
+#ifdef CONFIG_RSBAC_IPC_SEM
+	rsbac_target_id.ipc.id.id_nr = sma->sem_perm.id;
+	rsbac_new_target_id.dummy = 0;
+	if (rsbac_adf_set_attr(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_none,
+				rsbac_attribute_value))
+		rsbac_printk(KERN_WARNING
+		"newary() [sys_semget()]: rsbac_adf_set_attr() returned error\n");
+#endif
+
 	sem_unlock(sma, -1);
 	rcu_read_unlock();
 
@@ -1273,6 +1311,12 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
 	int err;
 	struct list_head tasks;
 	int val;
+
+#ifdef CONFIG_RSBAC_IPC_SEM
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 #if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
 	/* big-endian 64bit */
 	val = arg >> 32;
@@ -1310,6 +1354,22 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
 		return -EACCES;
 	}
 
+#ifdef CONFIG_RSBAC_IPC_SEM
+	rsbac_target_id.ipc.type = I_sem;
+	rsbac_target_id.ipc.id.id_nr = semid;
+	rsbac_pr_debug(aef, "[sys_semctl()]: calling ADF\n");
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_WRITE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		rcu_read_unlock();
+		return -EPERM;
+	}
+#endif
+
 	sem_lock(sma, NULL, -1);
 
 	if (!ipc_valid_object(&sma->sem_perm)) {
@@ -1345,6 +1405,12 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 	ushort *sem_io = fast_sem_io;
 	struct list_head tasks;
 
+#ifdef CONFIG_RSBAC_IPC_SEM
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	INIT_LIST_HEAD(&tasks);
 
 	rcu_read_lock();
@@ -1396,6 +1462,22 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 				goto out_unlock;
 			}
 		}
+#ifdef CONFIG_RSBAC_IPC_SEM
+		rsbac_target_id.ipc.type = I_sem;
+		rsbac_target_id.ipc.id.id_nr = semid;
+		rsbac_pr_debug(aef, "[sys_semctl()]: calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_READ,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			err = -EPERM;
+			goto out_unlock;
+		}
+#endif
+
 		for (i = 0; i < sma->sem_nsems; i++)
 			sem_io[i] = sma->sem_base[i].semval;
 		sem_unlock(sma, -1);
@@ -1403,6 +1485,25 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 		err = 0;
 		if (copy_to_user(array, sem_io, nsems*sizeof(ushort)))
 			err = -EFAULT;
+
+		/* RSBAC: notify ADF of read sem */
+#ifdef CONFIG_RSBAC_IPC_SEM
+		if(!err) {
+			rsbac_new_target_id.dummy = 0;
+			if (rsbac_adf_set_attr(R_READ,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				rsbac_printk(KERN_WARNING
+						"semctl_main() [sys_semctl()]: rsbac_adf_set_attr() returned error");
+			}
+		}
+#endif
+
 		goto out_free;
 	}
 	case SETALL:
@@ -1430,6 +1531,23 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 			goto out_free;
 		}
 
+#ifdef CONFIG_RSBAC_IPC_SEM
+		rsbac_target_id.ipc.type = I_sem;
+		rsbac_target_id.ipc.id.id_nr = semid;
+		rsbac_pr_debug(aef, "[sys_semctl()]: calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_WRITE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			err = -EPERM;
+			ipc_rcu_putref(sma, ipc_rcu_free);
+			goto out_free;
+		}
+#endif
+
 		for (i = 0; i < nsems; i++) {
 			if (sem_io[i] > SEMVMX) {
 				ipc_rcu_putref(sma, sem_rcu_free);
@@ -1453,6 +1571,23 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
 				un->semadj[i] = 0;
 		}
 		sma->sem_ctime = get_seconds();
+
+                /* RSBAC: notify ADF of written sem */
+#ifdef CONFIG_RSBAC_IPC_SEM
+		rsbac_new_target_id.dummy = 0;
+		if (rsbac_adf_set_attr(R_WRITE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			rsbac_printk(KERN_WARNING
+					"semctl_main() [sys_semctl()]: rsbac_adf_set_attr() returned error");
+		}
+#endif
+
 		/* maybe some queued-up processes were waiting for this */
 		do_smart_update(sma, NULL, 0, 0, &tasks);
 		err = 0;
@@ -1536,6 +1671,12 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
 	struct semid64_ds semid64;
 	struct kern_ipc_perm *ipcp;
 
+#ifdef CONFIG_RSBAC_IPC_SEM
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (cmd == IPC_SET) {
 		if (copy_semid_from_user(&semid64, p, version))
 			return -EFAULT;
@@ -1559,11 +1700,88 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
 
 	switch (cmd) {
 	case IPC_RMID:
+#ifdef CONFIG_RSBAC_IPC_SEM
+		rsbac_target_id.ipc.type = I_sem;
+		rsbac_target_id.ipc.id.id_nr = semid;
+		rsbac_pr_debug(aef, "[sys_semctl()]: calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_DELETE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			err = -EPERM;
+			goto out_unlock1;
+		}
+#endif
+
 		sem_lock(sma, NULL, -1);
 		/* freeary unlocks the ipc object and rcu */
 		freeary(ns, ipcp);
+
+                /* RSBAC: notify ADF of deleted sem */
+#ifdef CONFIG_RSBAC_IPC_SEM
+		rsbac_new_target_id.dummy = 0;
+		if (rsbac_adf_set_attr(R_DELETE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			rsbac_printk(KERN_WARNING
+					"semctl_down() [sys_semctl()]: rsbac_adf_set_attr() returned error");
+		}
+#endif
+
 		goto out_up;
 	case IPC_SET:
+#ifdef CONFIG_RSBAC_IPC_SEM
+		rsbac_target_id.ipc.type = I_sem;
+		rsbac_target_id.ipc.id.id_nr = semid;
+		if (__kuid_val(ipcp->uid) != semid64.sem_perm.uid) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.owner = semid64.sem_perm.uid;
+			if (!rsbac_adf_request(R_CHANGE_OWNER,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						A_owner,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+				goto out_unlock1;
+			}
+		}
+		if (__kgid_val(ipcp->gid) != semid64.sem_perm.gid) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.group = semid64.sem_perm.gid;
+			if (!rsbac_adf_request(R_CHANGE_GROUP,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						A_group,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+				goto out_unlock1;
+			}
+		}
+		if (ipcp->mode != ((ipcp->mode & ~S_IRWXUGO) | (S_IRWXUGO & semid64.sem_perm.mode))) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.mode = (S_IRWXUGO & semid64.sem_perm.mode);
+			if (!rsbac_adf_request(R_ALTER,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						A_mode,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+				goto out_unlock1;
+			}
+		}
+#endif
+
 		sem_lock(sma, NULL, -1);
 		err = ipc_update_perm(&semid64.sem_perm, ipcp);
 		if (err)
diff --git a/ipc/shm.c b/ipc/shm.c
index aa3090dd..4f2e561 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -47,6 +47,8 @@
 
 #include "util.h"
 
+#include <rsbac/hooks.h>
+
 struct shm_file_data {
 	int id;
 	struct ipc_namespace *ns;
@@ -235,6 +237,10 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
 {
 	struct file *shm_file;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+#endif
+
 	shm_file = shp->shm_file;
 	shp->shm_file = NULL;
 	ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -246,6 +252,14 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
 		user_shm_unlock(i_size_read(file_inode(shm_file)),
 				shp->mlock_user);
 	fput(shm_file);
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ACI remove_target()\n");
+	rsbac_target_id.ipc.type   = I_shm;
+	rsbac_target_id.ipc.id.id_nr  = shp->shm_perm.id;
+	rsbac_remove_target(T_IPC, rsbac_target_id);
+#endif
+
 	ipc_rcu_putref(shp, shm_rcu_free);
 }
 
@@ -279,6 +293,27 @@ static void shm_close(struct vm_area_struct *vma)
 	struct shmid_kernel *shp;
 	struct ipc_namespace *ns = sfd->ns;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_shmdt() et al.]: calling ADF\n");
+	rsbac_target_id.ipc.type   = I_shm;
+	rsbac_target_id.ipc.id.id_nr  = sfd->id;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CLOSE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		rsbac_printk(KERN_WARNING
+				"shm_close() [sys_shmdt() et al.]: rsbac_adf_request() for CLOSE returned NOT_GRANTED\n");
+	}
+#endif
+
 	down_write(&shm_ids(ns).rwsem);
 	/* remove from the list of attaches of the shm segment */
 	shp = shm_lock(ns, sfd->id);
@@ -535,6 +570,12 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 	int id;
 	vm_flags_t acctflag = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (size < SHMMIN || size > ns->shm_ctlmax)
 		return -EINVAL;
 
@@ -545,6 +586,21 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 			ns->shm_tot + numpages > ns->shm_ctlall)
 		return -ENOSPC;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_shmget()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_shm;
+	rsbac_target_id.ipc.id.id_nr = 0;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	shp = ipc_rcu_alloc(sizeof(*shp));
 	if (!shp)
 		return -ENOMEM;
@@ -620,6 +676,24 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 
 	ipc_unlock_object(&shp->shm_perm);
 	rcu_read_unlock();
+
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.ipc.id.id_nr = file->f_path.dentry->d_inode->i_ino;
+	rsbac_new_target_id.ipc.type = I_shm;
+	rsbac_new_target_id.ipc.id.id_nr = file->f_path.dentry->d_inode->i_ino;
+	if (rsbac_adf_set_attr(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_IPC,
+				rsbac_new_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		rsbac_printk(KERN_WARNING
+				"newseg() [sys_shmget()]: rsbac_adf_set_attr() returned error");
+	}
+#endif
+
 	return error;
 
 no_id:
@@ -992,6 +1066,12 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 	int err, version;
 	struct ipc_namespace *ns;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	union rsbac_target_id_t rsbac_new_target_id;
+#endif
+
 	if (cmd < 0 || shmid < 0)
 		return -EINVAL;
 
@@ -1005,6 +1085,41 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
 	case IPC_STAT:
 		return shmctl_nolock(ns, shmid, cmd, version, buf);
 	case IPC_RMID:
+
+#ifdef CONFIG_RSBAC
+		rsbac_target_id.ipc.type = I_shm;
+		rsbac_target_id.ipc.id.id_nr = shmid;
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_DELETE,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+		err = shmctl_down(ns, shmid, cmd, buf, version);
+		if (!err) {
+	                rsbac_target_id.ipc.type = I_shm;
+			rsbac_target_id.ipc.id.id_nr = shmid;
+			rsbac_attribute_value.dummy = 0;
+			rsbac_new_target_id.dummy = 0;
+			if (rsbac_adf_set_attr(R_DELETE,
+						task_pid(current),
+						T_IPC,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				rsbac_printk(KERN_WARNING
+						"sys_shmctl(): rsbac_adf_set_attr() returned error");
+			}
+		}
+		return err;
+#endif
+
 	case IPC_SET:
 		return shmctl_down(ns, shmid, cmd, buf, version);
 	case SHM_LOCK:
@@ -1108,6 +1223,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 	fmode_t f_mode;
 	unsigned long populate = 0;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_request = R_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = -EINVAL;
 	if (shmid < 0)
 		goto out;
@@ -1177,6 +1299,27 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 		goto out_unlock;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef,  "calling ADF\n");
+	if ((shmflg & SHM_RDONLY))
+		rsbac_request = R_READ_OPEN;
+	else
+		rsbac_request = R_READ_WRITE_OPEN;
+	rsbac_target_id.ipc.type   = I_shm;
+	rsbac_target_id.ipc.id.id_nr  = shp->shm_perm.id;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		ipc_unlock_object(&shp->shm_perm);
+		goto out_unlock;
+	}
+#endif
+
 	path = shp->shm_file->f_path;
 	path_get(&path);
 	shp->shm_nattch++;
@@ -1254,6 +1397,25 @@ out_nattch:
 	else
 		shm_unlock(shp);
 	up_write(&shm_ids(ns).rwsem);
+
+/* RSBAC: notify ADF of attached shm */
+#ifdef CONFIG_RSBAC
+	if(!err) {
+		rsbac_new_target_id.dummy = 0;
+		if (rsbac_adf_set_attr(rsbac_request,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			rsbac_printk(KERN_WARNING
+					"sys_shmat(): rsbac_adf_set_attr() returned error");
+		}
+	}
+#endif
+
 	return err;
 
 out_unlock:
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0fcb43c..713bba1 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -18,6 +18,8 @@
 #include <linux/filter.h>
 #include <linux/version.h>
 
+#include <rsbac/hooks.h>
+
 static LIST_HEAD(bpf_map_types);
 
 static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
@@ -557,6 +559,12 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
 	union bpf_attr attr = {};
 	int err;
 
+#ifdef CONFIG_RSBAC_NET
+	enum  rsbac_adf_request_t     rsbac_adf_req;
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* the syscall is limited to root temporarily. This restriction will be
 	 * lifted when security audit is clean. Note that eBPF+tracing must have
 	 * this restriction, since it may pass kernel data to user space
@@ -597,6 +605,29 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
 	if (copy_from_user(&attr, uattr, size) != 0)
 		return -EFAULT;
 
+#ifdef CONFIG_RSBAC_NET
+	switch (cmd) {
+	case BPF_MAP_LOOKUP_ELEM:
+	case BPF_MAP_GET_NEXT_KEY:
+		rsbac_adf_req = R_GET_STATUS_DATA;
+		break;
+	default:
+		rsbac_adf_req = R_MODIFY_SYSTEM_DATA;
+		break;
+	}
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_firewall;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_adf_req,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	switch (cmd) {
 	case BPF_MAP_CREATE:
 		err = map_create(&attr);
diff --git a/kernel/capability.c b/kernel/capability.c
index 022df09..9a45593 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -19,6 +19,8 @@
 #include <linux/user_namespace.h>
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 /*
  * Leveraged for setting/resetting capabilities
  */
@@ -119,6 +121,15 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
 {
 	int ret;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.process = NULL;
+#endif
+
 	if (pid && (pid != task_pid_vnr(current))) {
 		struct task_struct *target;
 
@@ -127,12 +138,36 @@ static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
 		target = find_task_by_vpid(pid);
 		if (!target)
 			ret = -ESRCH;
-		else
+		else {
 			ret = security_capget(target, pEp, pIp, pPp);
+#ifdef CONFIG_RSBAC
+			rsbac_target_id.process = get_task_pid(target, PIDTYPE_PID);
+#endif
+		}
 
 		rcu_read_unlock();
-	} else
+	} else {
 		ret = security_capget(current, pEp, pIp, pPp);
+#ifdef CONFIG_RSBAC
+		rsbac_target_id.process = get_task_pid(current, PIDTYPE_PID);
+#endif
+	}
+#ifdef CONFIG_RSBAC
+	if(!ret) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if(!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			ret = -EPERM;
+		}
+	}
+	if (rsbac_target_id.process)
+		put_pid(rsbac_target_id.process);
+#endif
 
 	return ret;
 }
@@ -229,6 +264,12 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
 	int ret;
 	pid_t pid;
 
+#ifdef CONFIG_RSBAC
+     union rsbac_target_id_t rsbac_target_id;
+     union rsbac_target_id_t rsbac_new_target_id;
+     union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	ret = cap_validate_magic(header, &tocopy);
 	if (ret != 0)
 		return ret;
@@ -272,9 +313,47 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
 	if (ret < 0)
 		goto error;
 
+#ifdef CONFIG_RSBAC
+	if (!cap_issubset(effective, new->cap_effective)
+		     || !cap_issubset(permitted, new->cap_permitted)
+		     || !cap_issubset(inheritable, new->cap_inheritable)) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.scd = ST_capability;
+		rsbac_attribute_value.dummy = 0;
+		if(!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+		     ret = -EPERM;
+		     goto error;
+		}
+	}
+#endif
+
 	audit_log_capset(new, current_cred());
 
-	return commit_creds(new);
+	ret = commit_creds(new);
+
+#ifdef CONFIG_RSBAC
+	if (!ret) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_setcap(): rsbac_adf_set_attr() returned error");
+		}
+	}
+#endif
+
+	return ret;
 
 error:
 	abort_creds(new);
@@ -383,6 +462,9 @@ bool ns_capable(struct user_namespace *ns, int cap)
 		current->flags |= PF_SUPERPRIV;
 		return true;
 	}
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_JAIL_LOG_MISSING)
+	rsbac_log_missing_cap(cap);
+#endif
 	return false;
 }
 EXPORT_SYMBOL(ns_capable);
diff --git a/kernel/cred.c b/kernel/cred.c
index ec1c076..f945f78 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -237,7 +237,9 @@ error:
  */
 struct cred *prepare_creds(void)
 {
+#ifndef CONFIG_RSBAC
 	struct task_struct *task = current;
+#endif
 	const struct cred *old;
 	struct cred *new;
 
@@ -249,7 +251,11 @@ struct cred *prepare_creds(void)
 
 	kdebug("prepare_creds() alloc %p", new);
 
+#ifdef CONFIG_RSBAC
+	old = current_cred();
+#else
 	old = task->cred;
+#endif
 	memcpy(new, old, sizeof(struct cred));
 
 	atomic_set(&new->usage, 1);
diff --git a/kernel/exit.c b/kernel/exit.c
index 819f51e..d7bcd5a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -59,6 +59,8 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 
+#include <rsbac/hooks.h>
+
 static void exit_mm(struct task_struct *tsk);
 
 static void __unhash_process(struct task_struct *p, bool group_dead)
@@ -654,6 +656,12 @@ void do_exit(long code)
 {
 	struct task_struct *tsk = current;
 	int group_dead;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	TASKS_RCU(int tasks_rcu_i);
 
 	profile_task_exit(tsk);
@@ -711,6 +719,22 @@ void do_exit(long code)
 			current->comm, task_pid_nr(current),
 			preempt_count());
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_exit()]: calling ADF\n");
+	rsbac_target_id.process = get_task_pid(tsk, PIDTYPE_PID);
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_TERMINATE,
+				rsbac_target_id.process,
+				T_PROCESS,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		rsbac_printk(KERN_WARNING
+				"do_exit() [sys_exit()]: ADF request for TERMINATE returned NOT_GRANTED!\n");
+	}
+	put_pid(rsbac_target_id.process);
+#endif
+
 	acct_update_integrals(tsk);
 	/* sync mm's RSS info before statistics gathering */
 	if (tsk->mm)
diff --git a/kernel/fork.c b/kernel/fork.c
index edc1916..d33618d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -83,6 +83,8 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
+#include <rsbac/hooks.h>
+
 #include <trace/events/sched.h>
 
 #define CREATE_TRACE_POINTS
@@ -1674,7 +1676,12 @@ struct task_struct *fork_idle(int cpu)
  * It copies the process, and if successful kick-starts
  * it and waits for it to finish using the VM if required.
  */
+
+#ifdef CONFIG_RSBAC
+long do_fork(unsigned long long clone_flags,
+#else
 long do_fork(unsigned long clone_flags,
+#endif
 	      unsigned long stack_start,
 	      unsigned long stack_size,
 	      int __user *parent_tidptr,
@@ -1684,6 +1691,30 @@ long do_fork(unsigned long clone_flags,
 	int trace = 0;
 	long nr;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_attribute = A_none;
+	rsbac_attribute_value.dummy = 0;
+	if(current->pid) {
+		rsbac_pr_debug(aef, "[sys_fork(),sys_clone(),sys_vfork]: calling ADF\n");
+		rsbac_target_id.process = task_pid(current);
+		if (!rsbac_adf_request(R_CLONE,
+					rsbac_target_id.process,
+					T_PROCESS,
+					rsbac_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+	}
+#endif
+
 	/*
 	 * Determine whether and which event to report to ptracer.  When
 	 * called from kernel_thread or CLONE_UNTRACED is explicitly
@@ -1726,6 +1757,33 @@ long do_fork(unsigned long clone_flags,
 			get_task_struct(p);
 		}
 
+#ifdef CONFIG_RSBAC
+		if (clone_flags & CLONE_KTHREAD) {
+			rsbac_attribute = A_kernel_thread;
+			rsbac_attribute_value.kernel_thread = 1;
+			rsbac_mark_kthread(task_pid(p));
+			rsbac_kthread_notify(task_pid(p));
+		}
+
+		if (current->pid)
+		{
+			rsbac_pr_debug(aef, "[sys_fork(),sys_clone(),sys_vfork()]: calling ADF_set_attr\n");
+			rsbac_target_id.process = task_pid(current);
+			rsbac_new_target_id.process = task_pid(p);
+			if (unlikely(rsbac_adf_set_attr(R_CLONE,
+						rsbac_target_id.process,
+						T_PROCESS,
+						rsbac_target_id,
+						T_PROCESS,
+						rsbac_new_target_id,
+						rsbac_attribute,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"do_fork() [sys_fork(), sys_clone()]: rsbac_adf_set_attr() returned error!\n");
+			}
+		}
+#endif
+
 		wake_up_new_task(p);
 
 		/* forking complete and child started to run, tell ptracer */
@@ -1749,8 +1807,13 @@ long do_fork(unsigned long clone_flags,
  */
 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 {
+#ifdef CONFIG_RSBAC
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED|CLONE_KTHREAD, (unsigned long)fn,
+		(unsigned long)arg, NULL, NULL);
+#else
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
 		(unsigned long)arg, NULL, NULL);
+#endif
 }
 
 #ifdef __ARCH_WANT_SYS_FORK
diff --git a/kernel/groups.c b/kernel/groups.c
index 5ea9847..4548ddd 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -9,6 +9,8 @@
 #include <linux/user_namespace.h>
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 struct group_info *groups_alloc(int gidsetsize)
 {
 	struct group_info *group_info;
@@ -229,6 +231,12 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
 	struct group_info *group_info;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int i;
+#endif
+
 	if (!may_setgroups())
 		return -EPERM;
 	if ((unsigned)gidsetsize > NGROUPS_MAX)
@@ -243,6 +251,25 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
 		return retval;
 	}
 
+#ifdef CONFIG_RSBAC
+	if (gidsetsize > 0) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = task_pid(current);
+		for (i=0; i < gidsetsize; i++) {
+			rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, __kgid_val(group_info->blocks[i / NGROUPS_PER_BLOCK][i]));
+			if(!rsbac_adf_request(R_CHANGE_GROUP,
+						rsbac_target_id.process,
+						T_PROCESS,
+						rsbac_target_id,
+						A_group,
+						rsbac_attribute_value)) {
+				put_group_info(group_info);
+				return -EPERM;
+			}
+		}
+	}
+#endif
+
 	groups_sort(group_info);
 	retval = set_current_groups(group_info);
 	put_group_info(group_info);
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 5c5987f..389d49e 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -27,6 +27,8 @@
 
 #include <asm/sections.h>
 
+#include <rsbac/hooks.h>
+
 #ifdef CONFIG_KALLSYMS_ALL
 #define all_var 1
 #else
@@ -565,6 +567,27 @@ static int kallsyms_open(struct inode *inode, struct file *file)
 	 * using get_symbol_offset for every symbol.
 	 */
 	struct kallsym_iter *iter;
+
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.scd = ST_ksyms;
+	rsbac_attribute_value.dummy = 0;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if(!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
 	if (!iter)
 		return -ENOMEM;
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 7a36fdc..835f8d9 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -45,6 +45,8 @@
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 
+#include <rsbac/hooks.h>
+
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t __percpu *crash_notes;
 
@@ -1242,10 +1244,29 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
 	struct kimage **dest_image, *image;
 	int result;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t	rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* We only trust the superuser with rebooting the system. */
 	if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.scd = ST_kexec;
+	rsbac_attribute_value.dummy = 0;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if(!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	/*
 	 * Verify we have a legal set of flags
 	 * This leaves us room for future extensions.
diff --git a/kernel/module.c b/kernel/module.c
index c38bf6e..764d4e4 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -62,6 +62,8 @@
 #include <uapi/linux/module.h>
 #include "module-internal.h"
 
+#include <rsbac/hooks.h>
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
 
@@ -800,6 +802,11 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 	char name[MODULE_NAME_LEN];
 	int ret, forced = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
 		return -EPERM;
 
@@ -807,9 +814,21 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
 		return -EFAULT;
 	name[MODULE_NAME_LEN-1] = '\0';
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dummy = 0;
+	rsbac_attribute_value.mod_name = name;
+	if (!rsbac_adf_request(R_REMOVE_FROM_KERNEL,
+				task_pid(current),
+				T_NONE,
+				rsbac_target_id,
+				A_mod_name,
+				rsbac_attribute_value))
+		return -EPERM;
+#endif
+
 	if (mutex_lock_interruptible(&module_mutex) != 0)
 		return -EINTR;
-
 	mod = find_module(name);
 	if (!mod) {
 		ret = -ENOENT;
@@ -3454,10 +3473,29 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
 	int err;
 	struct load_info info = { };
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = may_init_module();
 	if (err)
 		return err;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dummy = 0;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_ADD_TO_KERNEL,
+				task_pid(current),
+				T_NONE,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	pr_debug("init_module: umod=%p, len=%lu, uargs=%p\n",
 	       umod, len, uargs);
 
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 59dc17b..06ddf64 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -49,6 +49,8 @@
 
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/printk.h>
 
@@ -1260,10 +1262,53 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 	static int saved_console_loglevel = LOGLEVEL_DEFAULT;
 	int error;
 
+#ifdef CONFIG_RSBAC_SYSLOG
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	error = check_syslog_permissions(type, from_file);
 	if (error)
 		goto out;
 
+
+#ifdef CONFIG_RSBAC_SYSLOG
+	rsbac_pr_debug(aef, "[sys_syslog()]: calling ADF\n");
+	rsbac_target_id.scd = ST_syslog;
+	rsbac_attribute_value.dummy = 0;
+	switch(type) {
+		case 2:
+		case 3:
+			if (!rsbac_adf_request(R_GET_STATUS_DATA,
+						task_pid(current),
+						T_SCD,
+						rsbac_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				error = -EPERM;
+				goto out;
+			}
+			break;
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+			if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+						task_pid(current),
+						T_SCD,
+						rsbac_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				error = -EPERM;
+				goto out;
+			}
+			break;
+
+		default:
+			break;
+	}
+#endif
 	switch (type) {
 	case SYSLOG_ACTION_CLOSE:	/* Close log */
 		break;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 740a9c3..863dccd 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -29,6 +29,8 @@
 #include <linux/compat.h>
 
 
+#include <rsbac/hooks.h>
+
 void __ptrace_link(struct task_struct *child, struct task_struct *new_parent,
 		   const struct cred *ptracer_cred)
 {
@@ -1096,7 +1098,27 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
 	struct task_struct *child;
 	long ret;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (request == PTRACE_TRACEME) {
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "sys_ptrace(): calling ADF\n");
+		rsbac_target_id.process = task_pid(current);
+		rsbac_attribute_value.trace_request = PTRACE_TRACEME;
+		if (!rsbac_adf_request(R_TRACE,
+				rsbac_target_id.process,
+				T_PROCESS,
+				rsbac_target_id,
+				A_trace_request,
+				rsbac_attribute_value)) {
+			ret = -EPERM;
+			goto out;
+		}
+#endif
+
 		ret = ptrace_traceme();
 		if (!ret)
 			arch_ptrace_attach(current);
@@ -1109,6 +1131,23 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
 		goto out;
 	}
 
+#ifdef CONFIG_RSBAC
+	if (request != PTRACE_DETACH) {
+		rsbac_pr_debug(aef, "sys_ptrace(): calling ADF\n");
+		rsbac_target_id.process = task_pid(child);
+		rsbac_attribute_value.trace_request = request;
+		if (!rsbac_adf_request(R_TRACE,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_trace_request,
+					rsbac_attribute_value)) {
+			ret = -EPERM;
+			goto out_put_task_struct;
+		}
+	}
+#endif
+
 	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
 		ret = ptrace_attach(child, request, addr, data);
 		/*
@@ -1242,7 +1281,27 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid,
 	struct task_struct *child;
 	long ret;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (request == PTRACE_TRACEME) {
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "compat_sys_ptrace(): calling ADF\n");
+		rsbac_target_id.process = task_pid(current);
+		rsbac_attribute_value.trace_request = PTRACE_TRACEME;
+		if (!rsbac_adf_request(R_TRACE,
+				rsbac_target_id.process,
+				T_PROCESS,
+				rsbac_target_id,
+				A_trace_request,
+				rsbac_attribute_value)) {
+			ret = -EPERM;
+			goto out;
+		}
+#endif
+
 		ret = ptrace_traceme();
 		goto out;
 	}
@@ -1253,6 +1312,23 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid,
 		goto out;
 	}
 
+#ifdef CONFIG_RSBAC
+	if (request != PTRACE_DETACH) {
+		rsbac_pr_debug(aef, "compat_sys_ptrace(): calling ADF\n");
+		rsbac_target_id.process = task_pid(child);
+		rsbac_attribute_value.trace_request = request;
+		if (!rsbac_adf_request(R_TRACE,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_trace_request,
+					rsbac_attribute_value)) {
+			ret = -EPERM;
+			goto out_put_task_struct;
+		}
+	}
+#endif
+
 	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
 		ret = ptrace_attach(child, request, addr, data);
 		/*
diff --git a/kernel/reboot.c b/kernel/reboot.c
index d20c85d..b198bdd 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -17,6 +17,11 @@
 #include <linux/syscore_ops.h>
 #include <linux/uaccess.h>
 
+#ifdef CONFIG_RSBAC
+#include <linux/sched/rt.h>
+#include <rsbac/hooks.h>
+#endif
+
 /*
  * this indicates whether you can reboot with ctrl-alt-del: the default is yes
  */
@@ -284,6 +289,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
 	char buffer[256];
 	int ret = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* We only trust the superuser with rebooting the system. */
 	if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))
 		return -EPERM;
@@ -311,6 +321,20 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
 	if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
 		cmd = LINUX_REBOOT_CMD_HALT;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.dummy = 0;
+	rsbac_attribute_value.reboot_cmd = cmd;
+	if (!rsbac_adf_request(R_SHUTDOWN,
+				task_pid(current),
+				T_NONE,
+				rsbac_target_id,
+				A_reboot_cmd,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	mutex_lock(&reboot_mutex);
 	switch (cmd) {
 	case LINUX_REBOOT_CMD_RESTART:
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5e7608c..e4cade6 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -83,6 +83,8 @@
 #include <asm/paravirt.h>
 #endif
 
+#include <rsbac/hooks.h>
+
 #include "sched.h"
 #include "../workqueue_internal.h"
 #include "../smpboot.h"
@@ -3174,6 +3176,10 @@ int can_nice(const struct task_struct *p, const int nice)
 SYSCALL_DEFINE1(nice, int, increment)
 {
 	long nice, retval;
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	/*
 	 * Setpriority might change our priority at the same moment.
@@ -3187,6 +3193,22 @@ SYSCALL_DEFINE1(nice, int, increment)
 	if (increment < 0 && !can_nice(current, nice))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC
+	if (increment < 0) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.scd = ST_priority;
+		rsbac_attribute_value.priority = nice;
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_priority,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+	}
+#endif
+
 	retval = security_task_setnice(current, nice);
 	if (retval)
 		return retval;
@@ -3730,6 +3752,12 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
 	struct task_struct *p;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!param || pid < 0)
 		return -EINVAL;
 	if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
@@ -3738,8 +3766,31 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
 	rcu_read_lock();
 	retval = -ESRCH;
 	p = find_process_by_pid(pid);
-	if (p != NULL)
+	if (p != NULL) {
+
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "[sys_sched_setscheduler, sys_sched_setparam]: calling ADF\n");
+		if (!pid || (pid == current->pid)) {
+			rsbac_target = T_SCD;
+			rsbac_target_id.scd = ST_priority;
+		} else {
+			rsbac_target = T_PROCESS;
+			rsbac_target_id.process = task_pid(p);
+		}
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			rcu_read_unlock();
+			return -EPERM;
+		}
+#endif
+
 		retval = sched_setscheduler(p, policy, &lparam);
+	}
 	rcu_read_unlock();
 
 	return retval;
@@ -3891,6 +3942,12 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
 	struct task_struct *p;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+        enum  rsbac_target_t rsbac_target;
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (pid < 0)
 		return -EINVAL;
 
@@ -3899,6 +3956,29 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
 	p = find_process_by_pid(pid);
 	if (p) {
 		retval = security_task_getscheduler(p);
+
+#ifdef CONFIG_RSBAC
+		if (!retval) {
+		        rsbac_pr_debug(aef, "[sys_sched_getscheduler]: calling ADF\n");
+		        if (!pid || (pid == current->pid)) {
+		                rsbac_target = T_SCD;
+		                rsbac_target_id.scd = ST_priority;
+		        } else {
+		                rsbac_target = T_PROCESS;
+		                rsbac_target_id.process = task_pid(p);
+		        }
+		        rsbac_attribute_value.dummy = 0;
+		        if (!rsbac_adf_request(R_GET_STATUS_DATA,
+		                                task_pid(current),
+		                                rsbac_target,
+		                                rsbac_target_id,
+		                                A_none,
+		                                rsbac_attribute_value)) {
+		                retval = -EPERM;
+		        }
+		}
+#endif
+
 		if (!retval)
 			retval = p->policy
 				| (p->sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0);
@@ -3921,6 +4001,12 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
 	struct task_struct *p;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+        enum  rsbac_target_t rsbac_target;
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!param || pid < 0)
 		return -EINVAL;
 
@@ -3934,6 +4020,27 @@ SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
 	if (retval)
 		goto out_unlock;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_sched_getparam]: calling ADF\n");
+	if (!pid || (pid == current->pid)) {
+		rsbac_target = T_SCD;
+		rsbac_target_id.scd = ST_priority;
+	} else {
+		rsbac_target = T_PROCESS;
+		rsbac_target_id.process = task_pid(p);
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		retval = -EPERM;
+		goto out_unlock;
+	}
+#endif
+
 	if (task_has_rt_policy(p))
 		lp.sched_priority = p->rt_priority;
 	rcu_read_unlock();
@@ -4038,6 +4145,12 @@ out_unlock:
 
 long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 {
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	cpumask_var_t cpus_allowed, new_mask;
 	struct task_struct *p;
 	int retval;
@@ -4080,6 +4193,26 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
 	if (retval)
 		goto out_free_new_mask;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_sched_setaffinity]: calling ADF\n");
+	if (p == current) {
+		rsbac_target = T_SCD;
+		rsbac_target_id.scd = ST_priority;
+	} else {
+		rsbac_target = T_PROCESS;
+		rsbac_target_id.process = task_pid(p);
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		retval = -EPERM;
+		goto out_free_new_mask;
+	}
+#endif
 
 	cpuset_cpus_allowed(p, cpus_allowed);
 	cpumask_and(new_mask, in_mask, cpus_allowed);
@@ -4149,6 +4282,31 @@ SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
 {
 	cpumask_var_t new_mask;
 	int retval;
+#ifdef CONFIG_RSBAC
+	enum rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sched_getaffinity]: calling ADF\n");
+	if (!pid || (pid == current->pid)) {
+		rsbac_target = T_SCD;
+		rsbac_target_id.scd = ST_priority;
+	} else {
+		rsbac_target = T_PROCESS;
+		rsbac_target_id.process = find_pid_ns(pid, &init_pid_ns);
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
 
 	if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
 		return -ENOMEM;
@@ -4506,6 +4664,12 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
 	int retval;
 	struct timespec t;
 
+#ifdef CONFIG_RSBAC
+	enum rsbac_target_t rsbac_target;
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (pid < 0)
 		return -EINVAL;
 
@@ -4519,6 +4683,27 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
 	if (retval)
 		goto out_unlock;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_sched_rr_get_interval]: calling ADF\n");
+	if (!pid || (pid == current->pid)) {
+		rsbac_target = T_SCD;
+		rsbac_target_id.scd = ST_priority;
+	} else {
+		rsbac_target = T_PROCESS;
+		rsbac_target_id.process = task_pid(p);
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		retval = -EPERM;
+		goto out_unlock;
+	}
+#endif
+
 	rq = task_rq_lock(p, &flags);
 	time_slice = 0;
 	if (p->sched_class->get_rr_interval)
diff --git a/kernel/signal.c b/kernel/signal.c
index 46a2471..4c1dcca 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -45,6 +45,8 @@
 #include <asm/cacheflush.h>
 #include "audit.h"	/* audit_signal_info() */
 
+#include <rsbac/hooks.h>
+
 /*
  * SLAB caches for signal bits.
  */
@@ -769,6 +771,12 @@ static int check_kill_permission(int sig, struct siginfo *info,
 	struct pid *sid;
 	int error;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_adf_request_t rsbac_adf_req;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!valid_signal(sig))
 		return -EINVAL;
 
@@ -795,6 +803,31 @@ static int check_kill_permission(int sig, struct siginfo *info,
 		}
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "check_kill_permission() [group_send_sig_info(), sys_tgkill(),sys_tkill()]: calling ADF\n");
+	rsbac_target_id.process = get_task_pid(t, PIDTYPE_PID);
+	rsbac_attribute_value.signal = sig;
+	if (sig)
+		rsbac_adf_req = R_SEND_SIGNAL;
+	else
+		rsbac_adf_req = R_GET_STATUS_DATA;
+	if ((!info || ((unsigned long)info != 1
+			&& (unsigned long)info != 2 && SI_FROMUSER(info)))
+			&& ((sig != SIGCONT) || (task_session(current) != task_session(t)))
+			&& !(t->flags & PF_EXITING)
+			&& !rsbac_adf_request(rsbac_adf_req,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_signal,
+				rsbac_attribute_value)
+	  ) {
+		put_pid(rsbac_target_id.process);
+		return -EPERM;
+        }
+	put_pid(rsbac_target_id.process);
+#endif
+
 	return security_task_kill(t, info, sig, 0);
 }
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 25ae8d2..ee47cdf 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -61,6 +61,11 @@
 #include <asm/io.h>
 #include <asm/unistd.h>
 
+#ifdef CONFIG_RSBAC
+#include <linux/sched/rt.h>
+#include <rsbac/hooks.h>
+#endif
+
 #ifndef SET_UNALIGN_CTL
 # define SET_UNALIGN_CTL(a, b)	(-EINVAL)
 #endif
@@ -181,6 +186,12 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
 	struct pid *pgrp;
 	kuid_t uid;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (which > PRIO_USER || which < PRIO_PROCESS)
 		goto out;
 
@@ -191,6 +202,43 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
 	if (niceval > MAX_NICE)
 		niceval = MAX_NICE;
 
+#ifdef CONFIG_RSBAC
+	if ((niceval < (current->static_prio - MAX_RT_PRIO - 20)) || ((which == PRIO_PROCESS)
+				&& (who != 0)
+				&& (who != current->pid))
+					|| ((which == PRIO_PGRP)
+					&& (who != 0)
+					&& (who != current->pid))) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		if (niceval < (current->static_prio - MAX_RT_PRIO - 20)) {
+			rsbac_target = T_SCD;
+			rsbac_target_id.scd = ST_priority;
+		} else {
+			rcu_read_lock();
+			rsbac_target_id.process = find_pid_ns(who, &init_pid_ns);
+			if (likely(rsbac_target_id.process)) {
+				rsbac_target = T_PROCESS;
+				get_pid(rsbac_target_id.process);
+			}
+			rcu_read_unlock();
+		}
+		rsbac_attribute_value.priority = niceval;
+		if ((rsbac_target != T_NONE) && !rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_priority,
+					rsbac_attribute_value)) {
+			error = -EPERM;
+			if ((rsbac_target == T_PROCESS) && rsbac_target_id.process)
+				put_pid(rsbac_target_id.process);
+			goto out;
+		}
+		if ((rsbac_target == T_PROCESS) && rsbac_target_id.process)
+			put_pid(rsbac_target_id.process);
+	}
+#endif
+
 	rcu_read_lock();
 	read_lock(&tasklist_lock);
 	switch (which) {
@@ -349,18 +397,65 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, gid_t, egid)
 
 	retval = -EPERM;
 	if (rgid != (gid_t) -1) {
-		if (gid_eq(old->gid, krgid) ||
+
+#ifdef CONFIG_RSBAC
+		union rsbac_target_id_t rsbac_target_id;
+		union rsbac_attribute_value_t rsbac_attribute_value;
+
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = task_pid(current);
+		rsbac_attribute_value.long_dummy = 0;
+		rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, rgid);
+#endif
+
+		if ((gid_eq(old->gid, krgid) ||
 		    gid_eq(old->egid, krgid) ||
 		    ns_capable(old->user_ns, CAP_SETGID))
+#ifdef CONFIG_RSBAC
+				&& rsbac_adf_request(R_CHANGE_GROUP,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_group,
+					rsbac_attribute_value)
+#endif
+		   )
 			new->gid = krgid;
 		else
 			goto error;
 	}
 	if (egid != (gid_t) -1) {
-		if (gid_eq(old->gid, kegid) ||
+
+#ifdef CONFIG_RSBAC_DAC_GROUP
+		union rsbac_target_id_t rsbac_target_id;
+		union rsbac_attribute_value_t rsbac_attribute_value;
+
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = task_pid(current);
+		rsbac_attribute_value.long_dummy = 0;
+		rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, egid);
+#endif
+
+		if ((gid_eq(old->gid, kegid) ||
 		    gid_eq(old->egid, kegid) ||
 		    gid_eq(old->sgid, kegid) ||
 		    ns_capable(old->user_ns, CAP_SETGID))
+
+#ifdef CONFIG_RSBAC_DAC_GROUP
+				&& rsbac_adf_request(R_CHANGE_DAC_EFF_GROUP,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_group,
+					rsbac_attribute_value)
+				&& rsbac_adf_request(R_CHANGE_DAC_FS_GROUP,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_group,
+					rsbac_attribute_value)
+#endif
+		   )
 			new->egid = kegid;
 		else
 			goto error;
@@ -391,6 +486,11 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
 	int retval;
 	kgid_t kgid;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	kgid = make_kgid(ns, gid);
 	if (!gid_valid(kgid))
 		return -EINVAL;
@@ -400,10 +500,57 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
 		return -ENOMEM;
 	old = current_cred();
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = task_pid(current);
+	rsbac_attribute_value.long_dummy = 0;
+	rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, gid);
+#endif
+
 	retval = -EPERM;
-	if (ns_capable(old->user_ns, CAP_SETGID))
+	if (ns_capable(old->user_ns, CAP_SETGID)
+
+#ifdef CONFIG_RSBAC
+		&& rsbac_adf_request(R_CHANGE_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value)
+#ifdef CONFIG_RSBAC_DAC_GROUP
+		&& rsbac_adf_request(R_CHANGE_DAC_EFF_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value)
+		&& rsbac_adf_request(R_CHANGE_DAC_FS_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value)
+#endif
+#endif
+	)
 		new->gid = new->egid = new->sgid = new->fsgid = kgid;
-	else if (gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
+	else if ((gid_eq(kgid, old->gid) || gid_eq(kgid, old->sgid))
+
+#ifdef CONFIG_RSBAC_DAC_GROUP
+			&& rsbac_adf_request(R_CHANGE_DAC_EFF_GROUP,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_group,
+					rsbac_attribute_value)
+			&& rsbac_adf_request(R_CHANGE_DAC_FS_GROUP,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_group,
+					rsbac_attribute_value)
+#endif
+		)
 		new->egid = new->fsgid = kgid;
 	else
 		goto error;
@@ -467,6 +614,13 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
 	int retval;
 	kuid_t kruid, keuid;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	rsbac_uid_t rsbac_old_uid;
+#endif
+
 	kruid = make_kuid(ns, ruid);
 	keuid = make_kuid(ns, euid);
 
@@ -512,7 +666,103 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
 	if (retval < 0)
 		goto error;
 
-	return commit_creds(new);
+#ifdef CONFIG_RSBAC
+	rsbac_old_uid = __kuid_val(old->uid);
+	rsbac_target_id.process = task_pid(current);
+	if (ruid != (uid_t) -1) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.long_dummy = 0;
+		rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, ruid);
+		if (!rsbac_adf_request(R_CHANGE_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_owner,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			goto error;
+		}
+	}
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	if (euid != (uid_t) -1) {
+		rsbac_pr_debug(aef, "calling ADF for euid\n");
+		rsbac_attribute_value.long_dummy = 0;
+		rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, euid);
+		if (!rsbac_adf_request(R_CHANGE_DAC_EFF_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_owner,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			goto error;
+		}
+		if (!rsbac_adf_request(R_CHANGE_DAC_FS_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_owner,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			goto error;
+		}
+	}
+#endif
+#endif
+
+	retval = commit_creds(new);
+
+#ifdef CONFIG_RSBAC
+	if(!retval) {
+		rsbac_target_id.process = task_pid(current);
+		if(ruid != (uid_t) -1) {
+			rsbac_set_audit_uid(rsbac_old_uid);
+			rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, __kuid_val(current_uid()));
+			rsbac_new_target_id.dummy = 0;
+			if (unlikely(rsbac_adf_set_attr(R_CHANGE_OWNER,
+						task_pid(current),
+						T_PROCESS,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_owner,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_setreuid(): rsbac_adf_set_attr() returned error");
+			}
+		}
+#ifdef CONFIG_RSBAC_DAC_OWNER
+		if(euid != (uid_t) -1) {
+			rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, __kuid_val(current_euid()));
+			rsbac_new_target_id.dummy = 0;
+			if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_EFF_OWNER,
+						task_pid(current),
+						T_PROCESS,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_owner,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_setreuid(): rsbac_adf_set_attr() for euid returned error");
+			}
+			if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_FS_OWNER,
+						task_pid(current),
+						T_PROCESS,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_owner,
+						rsbac_attribute_value))) {
+				printk(KERN_WARNING
+						"sys_setreuid(): rsbac_adf_set_attr() for fsuid returned error");
+			}
+		}
+#endif
+	}
+#endif
+
+	return retval;
 
 error:
 	abort_creds(new);
@@ -538,10 +788,22 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
 	int retval;
 	kuid_t kuid;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	uid_t rsbac_old_uid;
+#endif
+
 	kuid = make_kuid(ns, uid);
 	if (!uid_valid(kuid))
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+	if(!uid && rsbac_uid_faked())
+		return 0;
+#endif
+
 	new = prepare_creds();
 	if (!new)
 		return -ENOMEM;
@@ -565,7 +827,91 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
 	if (retval < 0)
 		goto error;
 
-	return commit_creds(new);
+#ifdef CONFIG_RSBAC
+	rsbac_old_uid = __kuid_val(old->uid);
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = task_pid(current);
+	rsbac_attribute_value.long_dummy = 0;
+	rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, uid);
+	if(!rsbac_adf_request(R_CHANGE_OWNER,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_owner,
+				rsbac_attribute_value)) {
+		retval = -EPERM;
+		goto error;
+	}
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	rsbac_pr_debug(aef, "calling ADF for euid\n");
+	if (!rsbac_adf_request(R_CHANGE_DAC_EFF_OWNER,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_owner,
+				rsbac_attribute_value)) {
+		retval = -EPERM;
+		goto error;
+	}
+	rsbac_pr_debug(aef, "calling ADF for fsuid\n");
+	if (!rsbac_adf_request(R_CHANGE_DAC_FS_OWNER,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_owner,
+				rsbac_attribute_value)) {
+		retval = -EPERM;
+		goto error;
+	}
+#endif
+#endif
+
+	retval = commit_creds(new);
+
+#ifdef CONFIG_RSBAC
+	if (!retval) {
+		rsbac_target_id.process = task_pid(current);
+		rsbac_set_audit_uid(rsbac_old_uid);
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_CHANGE_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_owner,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_setuid(): rsbac_adf_set_attr() returned error");
+		}
+#ifdef CONFIG_RSBAC_DAC_OWNER
+		if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_EFF_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_owner,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_setuid(): rsbac_adf_set_attr() for euid returned error");
+		}
+		if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_FS_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_owner,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_setuid(): rsbac_adf_set_attr() for fsuid returned error");
+		}
+#endif
+	}
+#endif
+
+	return retval;
 
 error:
 	abort_creds(new);
@@ -585,6 +931,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
 	int retval;
 	kuid_t kruid, keuid, ksuid;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	uid_t rsbac_old_uid;
+#endif
+
 	kruid = make_kuid(ns, ruid);
 	keuid = make_kuid(ns, euid);
 	ksuid = make_kuid(ns, suid);
@@ -635,7 +988,103 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
 	if (retval < 0)
 		goto error;
 
-	return commit_creds(new);
+#ifdef CONFIG_RSBAC
+	rsbac_old_uid = __kuid_val(old->uid);
+	rsbac_target_id.process = task_pid(current);
+	if(ruid != (uid_t) -1) {
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.long_dummy = 0;
+		rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, ruid);
+		if(!rsbac_adf_request(R_CHANGE_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_owner,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			goto error;
+		}
+	}
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	if(euid != (uid_t) -1) {
+		rsbac_pr_debug(aef, "calling ADF for euid\n");
+		rsbac_attribute_value.long_dummy = 0;
+		rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, euid);
+		if(!rsbac_adf_request(R_CHANGE_DAC_EFF_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_owner,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			goto error;
+		}
+		rsbac_pr_debug(aef, "calling ADF for fsuid\n");
+		if(!rsbac_adf_request(R_CHANGE_DAC_FS_OWNER,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_owner,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			goto error;
+		}
+	}
+#endif
+#endif
+
+	retval = commit_creds(new);
+
+#ifdef CONFIG_RSBAC
+	if (!retval) {
+		rsbac_target_id.process = task_pid(current);
+		rsbac_new_target_id.dummy = 0;
+		if(ruid != (uid_t) -1) {
+			rsbac_set_audit_uid(rsbac_old_uid);
+			rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, __kuid_val(current_uid()));
+			if (unlikely(rsbac_adf_set_attr(R_CHANGE_OWNER,
+						task_pid(current),
+						T_PROCESS,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_owner,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_setresuid(): rsbac_adf_set_attr() returned error");
+			}
+		}
+#ifdef CONFIG_RSBAC_DAC_OWNER
+		if(euid != (uid_t) -1) {
+			rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, __kuid_val(current_euid()));
+			if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_EFF_OWNER,
+						task_pid(current),
+						T_PROCESS,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_owner,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_setreuid(): rsbac_adf_set_attr() for euid returned error\n");
+			}
+			if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_FS_OWNER,
+						task_pid(current),
+						T_PROCESS,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_owner,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_setreuid(): rsbac_adf_set_attr() for fsuid returned error\n");
+			}
+		}
+#endif
+	}
+#endif
+
+	return retval;
 
 error:
 	abort_creds(new);
@@ -672,6 +1121,11 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
 	int retval;
 	kgid_t krgid, kegid, ksgid;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	krgid = make_kgid(ns, rgid);
 	kegid = make_kgid(ns, egid);
 	ksgid = make_kgid(ns, sgid);
@@ -688,6 +1142,11 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
 		return -ENOMEM;
 	old = current_cred();
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = task_pid(current);
+#endif
+
 	retval = -EPERM;
 	if (!ns_capable(old->user_ns, CAP_SETGID)) {
 		if (rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
@@ -701,6 +1160,38 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
 			goto error;
 	}
 
+#ifdef CONFIG_RSBAC
+	if (rgid != (gid_t) -1) {
+		rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, rgid);
+		if (!rsbac_adf_request(R_CHANGE_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value))
+			goto error;
+	}
+#ifdef CONFIG_RSBAC_DAC_GROUP
+	if (egid != (gid_t) -1) {
+		rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, egid);
+		if (!rsbac_adf_request(R_CHANGE_DAC_EFF_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value))
+			goto error;
+		if (!rsbac_adf_request(R_CHANGE_DAC_FS_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value))
+			goto error;
+	}
+#endif
+#endif
+
 	if (rgid != (gid_t) -1)
 		new->gid = krgid;
 	if (egid != (gid_t) -1)
@@ -750,6 +1241,12 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 	uid_t old_fsuid;
 	kuid_t kuid;
 
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	old = current_cred();
 	old_fsuid = from_kuid_munged(old->user_ns, old->fsuid);
 
@@ -761,9 +1258,25 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 	if (!new)
 		return old_fsuid;
 
-	if (uid_eq(kuid, old->uid)  || uid_eq(kuid, old->euid)  ||
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = task_pid(current);
+	rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, uid);
+#endif
+
+	if ((uid_eq(kuid, old->uid)  || uid_eq(kuid, old->euid)  ||
 	    uid_eq(kuid, old->suid) || uid_eq(kuid, old->fsuid) ||
-	    ns_capable(old->user_ns, CAP_SETUID)) {
+	    ns_capable(old->user_ns, CAP_SETUID))
+
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	   && rsbac_adf_request(R_CHANGE_DAC_FS_OWNER,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_owner,
+				rsbac_attribute_value)
+#endif
+	) {
 		if (!uid_eq(kuid, old->fsuid)) {
 			new->fsuid = kuid;
 			if (security_task_fix_setuid(new, old, LSM_SETID_FS) == 0)
@@ -776,6 +1289,24 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid)
 
 change_okay:
 	commit_creds(new);
+
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	rsbac_target_id.process = task_pid(current);
+	rsbac_new_target_id.dummy = 0;
+	rsbac_attribute_value.owner = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, uid);
+	if (unlikely(rsbac_adf_set_attr(R_CHANGE_DAC_FS_OWNER,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_owner,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"sys_setfsuid(): rsbac_adf_set_attr() returned error\n");
+	}
+#endif
+
 	return old_fsuid;
 }
 
@@ -789,6 +1320,11 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
 	gid_t old_fsgid;
 	kgid_t kgid;
 
+#ifdef CONFIG_RSBAC_DAC_GROUP
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	old = current_cred();
 	old_fsgid = from_kgid_munged(old->user_ns, old->fsgid);
 
@@ -800,9 +1336,25 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid)
 	if (!new)
 		return old_fsgid;
 
-	if (gid_eq(kgid, old->gid)  || gid_eq(kgid, old->egid)  ||
+#ifdef CONFIG_RSBAC_DAC_GROUP
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = task_pid(current);
+	rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, gid);
+#endif
+
+	if ((gid_eq(kgid, old->gid)  || gid_eq(kgid, old->egid)  ||
 	    gid_eq(kgid, old->sgid) || gid_eq(kgid, old->fsgid) ||
-	    ns_capable(old->user_ns, CAP_SETGID)) {
+	    ns_capable(old->user_ns, CAP_SETGID))
+
+#ifdef CONFIG_RSBAC_DAC_GROUP
+		&& rsbac_adf_request(R_CHANGE_DAC_FS_GROUP,
+				task_pid(current),
+				T_PROCESS,
+				rsbac_target_id,
+				A_group,
+				rsbac_attribute_value)
+#endif
+	) {
 		if (!gid_eq(kgid, old->fsgid)) {
 			new->fsgid = kgid;
 			goto change_okay;
@@ -857,14 +1409,22 @@ SYSCALL_DEFINE0(getppid)
 
 SYSCALL_DEFINE0(getuid)
 {
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+	return rsbac_fake_uid();
+#else
 	/* Only we change this so SMP safe */
 	return from_kuid_munged(current_user_ns(), current_uid());
+#endif
 }
 
 SYSCALL_DEFINE0(geteuid)
 {
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+	return rsbac_fake_euid();
+#else
 	/* Only we change this so SMP safe */
 	return from_kuid_munged(current_user_ns(), current_euid());
+#endif
 }
 
 SYSCALL_DEFINE0(getgid)
@@ -923,6 +1483,11 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
 	struct pid *pgrp;
 	int err;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!pid)
 		pid = task_pid_vnr(group_leader);
 	if (!pgid)
@@ -931,6 +1496,23 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid_t, pgid)
 		return -EINVAL;
 	rcu_read_lock();
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.process = find_pid_ns(pid, &init_pid_ns);
+	if (likely(rsbac_target_id.process)) {
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			rcu_read_unlock();
+			return -EPERM;
+		}
+	}
+#endif
+
 	/* From this point forward we keep holding onto the tasklist lock
 	 * so that our parent does not change from under us. -DaveM
 	 */
@@ -997,6 +1579,11 @@ SYSCALL_DEFINE1(getpgid, pid_t, pid)
 	if (!pid)
 		grp = task_pgrp(current);
 	else {
+#ifdef CONFIG_RSBAC
+		union rsbac_target_id_t rsbac_target_id;
+		union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 		retval = -ESRCH;
 		p = find_task_by_vpid(pid);
 		if (!p)
@@ -1005,6 +1592,23 @@ SYSCALL_DEFINE1(getpgid, pid_t, pid)
 		if (!grp)
 			goto out;
 
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = get_task_pid(p, PIDTYPE_PID);
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			put_pid(rsbac_target_id.process);
+			goto out;
+		}
+		put_pid(rsbac_target_id.process);
+#endif
+
 		retval = security_task_getpgid(p);
 		if (retval)
 			goto out;
@@ -1034,6 +1638,11 @@ SYSCALL_DEFINE1(getsid, pid_t, pid)
 	if (!pid)
 		sid = task_session(current);
 	else {
+#ifdef CONFIG_RSBAC
+		union rsbac_target_id_t rsbac_target_id;
+		union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 		retval = -ESRCH;
 		p = find_task_by_vpid(pid);
 		if (!p)
@@ -1042,6 +1651,23 @@ SYSCALL_DEFINE1(getsid, pid_t, pid)
 		if (!sid)
 			goto out;
 
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.process = get_task_pid(p, PIDTYPE_PID);
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_PROCESS,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			retval = -EPERM;
+			put_pid(rsbac_target_id.process);
+			goto out;
+		}
+		put_pid(rsbac_target_id.process);
+#endif
+
 		retval = security_task_getsid(p);
 		if (retval)
 			goto out;
@@ -1217,11 +1843,31 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
 	int errno;
 	char tmp[__NEW_UTS_LEN];
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_host_id;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	down_write(&uts_sem);
 	errno = -EFAULT;
 	if (!copy_from_user(tmp, name, len)) {
@@ -1268,11 +1914,30 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
 	int errno;
 	char tmp[__NEW_UTS_LEN];
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!ns_capable(current->nsproxy->uts_ns->user_ns, CAP_SYS_ADMIN))
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_net_id;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	down_write(&uts_sem);
 	errno = -EFAULT;
 	if (!copy_from_user(tmp, name, len)) {
@@ -1363,6 +2028,12 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
 	struct rlimit *rlim;
 	int retval = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (resource >= RLIM_NLIMITS)
 		return -EINVAL;
 	if (new_rlim) {
@@ -1388,6 +2059,23 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
 		if (new_rlim->rlim_max > rlim->rlim_max &&
 				!capable(CAP_SYS_RESOURCE))
 			retval = -EPERM;
+
+#ifdef CONFIG_RSBAC
+		if (!retval) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_target_id.scd = ST_rlimit;
+			rsbac_attribute_value.rlimit.resource = resource;
+			rsbac_attribute_value.rlimit.limit = *new_rlim;
+			if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+						task_pid(current),
+						T_SCD,
+						rsbac_target_id,
+						A_rlimit,
+						rsbac_attribute_value))
+				retval = -EPERM;
+		}
+#endif
+
 		if (!retval)
 			retval = security_task_setrlimit(tsk->group_leader,
 					resource, new_rlim);
@@ -1409,6 +2097,21 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
 	}
 	task_unlock(tsk->group_leader);
 
+#ifdef CONFIG_RSBAC
+	rsbac_new_target_id.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_rlimit,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"sys_setrlimit(): rsbac_adf_set_attr() returned error");
+	}
+#endif
+
 	/*
 	 * RLIMIT_CPU handling.   Note that the kernel fails to return an error
 	 * code if it rejected the user's attempt to set RLIMIT_CPU.  This is a
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 7a68100..6d0518d 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -19,6 +19,8 @@
 
 #include "ntp_internal.h"
 
+#include <rsbac/hooks.h>
+
 /*
  * NTP timekeeping variables:
  *
@@ -619,6 +621,11 @@ static inline void process_adjtimex_modes(struct timex *txc,
  */
 int ntp_validate_timex(struct timex *txc)
 {
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (txc->modes & ADJ_ADJTIME) {
 		/* singleshot must not be used with any other mode bits */
 		if (!(txc->modes & ADJ_OFFSET_SINGLESHOT))
@@ -630,6 +637,20 @@ int ntp_validate_timex(struct timex *txc)
 		/* In order to modify anything, you gotta be super-user! */
 		 if (txc->modes && !capable(CAP_SYS_TIME))
 			return -EPERM;
+
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.scd = ST_time_strucs;
+		rsbac_attribute_value.dummy = 0;
+		if (txc->modes && !rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value))
+			return -EPERM;
+#endif
+
 		/*
 		 * if the quartz is off by more than 10% then
 		 * something is VERY wrong!
diff --git a/kernel/uid16.c b/kernel/uid16.c
index 651aaa5..9f2c075 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -16,6 +16,8 @@
 
 #include <asm/uaccess.h>
 
+#include <rsbac/hooks.h>
+
 SYSCALL_DEFINE3(chown16, const char __user *, filename, old_uid_t, user, old_gid_t, group)
 {
 	return sys_chown(filename, low2highuid(user), low2highgid(group));
@@ -176,6 +178,12 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
 	struct group_info *group_info;
 	int retval;
 
+#ifdef CONFIG_RSBAC
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+        int i;
+#endif
+
 	if (!may_setgroups())
 		return -EPERM;
 	if ((unsigned)gidsetsize > NGROUPS_MAX)
@@ -191,6 +199,27 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
 	}
 
 	groups_sort(group_info);
+
+#ifdef CONFIG_RSBAC
+        if (gidsetsize > 0) {
+                rsbac_pr_debug(aef, "calling ADF\n");
+                rsbac_target_id.process = task_pid(current);
+                for (i=0; i < gidsetsize; i++) {
+                        rsbac_attribute_value.group = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_KEEP, __kgid_val(group_info->blocks[i / NGROUPS_PER_BLOCK][i]));
+                        if(!rsbac_adf_request(R_CHANGE_GROUP,
+                                                task_pid(current),
+                                                T_PROCESS,
+                                                rsbac_target_id,
+                                                A_group,
+                                                rsbac_attribute_value))
+                        {
+                                put_group_info(group_info);
+                                return -EPERM;
+                        }
+		}
+	}
+#endif
+
 	retval = set_current_groups(group_info);
 	put_group_info(group_info);
 
@@ -199,12 +228,20 @@ SYSCALL_DEFINE2(setgroups16, int, gidsetsize, old_gid_t __user *, grouplist)
 
 SYSCALL_DEFINE0(getuid16)
 {
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+	return high2lowuid(rsbac_fake_uid());
+#else
 	return high2lowuid(from_kuid_munged(current_user_ns(), current_uid()));
+#endif
 }
 
 SYSCALL_DEFINE0(geteuid16)
 {
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+	return high2lowuid(rsbac_fake_euid());
+#else
 	return high2lowuid(from_kuid_munged(current_user_ns(), current_euid()));
+#endif
 }
 
 SYSCALL_DEFINE0(getgid16)
diff --git a/mm/mlock.c b/mm/mlock.c
index 00ff8c7..bb70edc 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -22,6 +22,8 @@
 #include <linux/memcontrol.h>
 #include <linux/mm_inline.h>
 
+#include <rsbac/hooks.h>
+
 #include "internal.h"
 
 int can_do_mlock(void)
@@ -611,9 +613,29 @@ SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
 	unsigned long lock_limit;
 	int error = -ENOMEM;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!can_do_mlock())
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.scd = ST_mlock;
+	rsbac_attribute_value.dummy = 0;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	lru_add_drain_all();	/* flush pagevec */
 
 	len = PAGE_ALIGN(len + (start & ~PAGE_MASK));
@@ -686,6 +708,11 @@ SYSCALL_DEFINE1(mlockall, int, flags)
 	unsigned long lock_limit;
 	int ret = -EINVAL;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE)))
 		goto out;
 
@@ -693,6 +720,21 @@ SYSCALL_DEFINE1(mlockall, int, flags)
 	if (!can_do_mlock())
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.scd = ST_mlock;
+	rsbac_attribute_value.dummy = 0;
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		ret = -EPERM;
+		goto out;
+	}
+#endif
+
 	if (flags & MCL_CURRENT)
 		lru_add_drain_all();	/* flush pagevec */
 
diff --git a/mm/mmap.c b/mm/mmap.c
index d730c1b..75ec489 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -45,6 +45,7 @@
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/tlb.h>
+#include <rsbac/hooks.h>
 #include <asm/mmu_context.h>
 
 #include "internal.h"
@@ -1274,6 +1275,12 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	struct mm_struct *mm = current->mm;
 	vm_flags_t vm_flags;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	*populate = 0;
 
 	/*
@@ -1406,6 +1413,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 			vm_flags |= VM_NORESERVE;
 	}
 
+#ifdef CONFIG_RSBAC
+	if (prot & PROT_EXEC) {
+		rsbac_pr_debug(aef, "[do_mmap() [sys_mmap()]]: calling ADF\n");
+		if (file) {
+			rsbac_target = T_FILE;
+			rsbac_target_id.file.device = file->f_path.dentry->d_inode->i_sb->s_dev;
+			rsbac_target_id.file.inode  = file->f_path.dentry->d_inode->i_ino;
+			rsbac_target_id.file.dentry_p = file->f_path.dentry;
+		} else {
+			rsbac_target = T_NONE;
+			rsbac_target_id.dummy = 0;
+		}
+		rsbac_attribute_value.prot_bits = prot;
+		if (!rsbac_adf_request(R_MAP_EXEC,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_prot_bits,
+					rsbac_attribute_value)) {
+			rsbac_pr_debug(aef, "[do_mmap() [sys_mmap()]]: request not granted, my PID: %i\n",
+					current->pid);
+			return -EPERM;
+		}
+	}
+#endif
+
 	addr = mmap_region(file, addr, len, vm_flags, pgoff);
 	if (!IS_ERR_VALUE(addr) &&
 	    ((vm_flags & VM_LOCKED) ||
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 8858483..6cfb2f2 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -28,6 +28,7 @@
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <rsbac/hooks.h>
 
 /*
  * For a prot_numa update we only hold mmap_sem for read so there is a
@@ -339,6 +340,14 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
 	struct vm_area_struct *vma, *prev;
 	int error = -EINVAL;
 	const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
+
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int need_notify = FALSE;
+#endif
+
 	prot &= ~(PROT_GROWSDOWN|PROT_GROWSUP);
 	if (grows == (PROT_GROWSDOWN|PROT_GROWSUP)) /* can't be both */
 		return -EINVAL;
@@ -408,6 +417,34 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
 		if (error)
 			goto out;
 
+#ifdef CONFIG_RSBAC
+		if ((prot & PROT_EXEC) && !(vma->vm_flags & PROT_EXEC)) {
+			rsbac_pr_debug(aef, "calling ADF\n");
+			if (vma->vm_file) {
+		                rsbac_target = T_FILE;
+				rsbac_target_id.file.device = vma->vm_file->f_path.dentry->d_inode->i_sb->s_dev;
+				rsbac_target_id.file.inode = vma->vm_file->f_path.dentry->d_inode->i_ino;
+				rsbac_target_id.file.dentry_p = vma->vm_file->f_path.dentry;
+			} else {
+				rsbac_target = T_NONE;
+				rsbac_target_id.dummy = 0;
+			}
+			rsbac_attribute_value.prot_bits = prot;
+			if (!rsbac_adf_request(R_MAP_EXEC,
+						  task_pid(current),
+						  rsbac_target,
+						  rsbac_target_id,
+						  A_prot_bits,
+						  rsbac_attribute_value))
+			{
+				rsbac_pr_debug(aef, "request NOT_GRANTED\n");
+				error = -EPERM;
+				goto out;
+			} else
+			  need_notify = TRUE;
+		}
+#endif
+
 		tmp = vma->vm_end;
 		if (tmp > end)
 			tmp = end;
@@ -429,5 +466,27 @@ SYSCALL_DEFINE3(mprotect, unsigned long, start, size_t, len,
 	}
 out:
 	up_write(&current->mm->mmap_sem);
+
+        /* RSBAC: notify ADF of mapped segment */
+#ifdef CONFIG_RSBAC
+	if (need_notify && !error) {
+		union rsbac_target_id_t rsbac_new_target_id;
+
+		rsbac_pr_debug(aef, "calling ADF_set_attr\n");
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_MAP_EXEC,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_none,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_mprotect: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 	return error;
 }
diff --git a/mm/swapfile.c b/mm/swapfile.c
index a7e7210..d76cab3 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -40,6 +40,8 @@
 #include <linux/swapops.h>
 #include <linux/swap_cgroup.h>
 
+#include <rsbac/hooks.h>
+
 static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
 				 unsigned char);
 static void free_swap_count_continuations(struct swap_info_struct *);
@@ -1812,9 +1814,29 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	int err, found = 0;
 	unsigned int old_block_size;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_swap;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+}
+#endif
+
 	BUG_ON(!current->mm);
 
 	pathname = getname(specialfile);
@@ -1826,6 +1848,35 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	if (IS_ERR(victim))
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF for DEV / FILE\n");
+	if (S_ISBLK(victim->f_path.dentry->d_inode->i_mode)) {
+		rsbac_target = T_DEV;
+		rsbac_target_id.dev.type = D_block;
+		rsbac_target_id.dev.major = RSBAC_MAJOR(victim->f_path.dentry->d_inode->i_rdev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(victim->f_path.dentry->d_inode->i_rdev);
+	} else
+		if (S_ISREG(victim->f_path.dentry->d_inode->i_mode)) {
+			rsbac_target = T_FILE;
+			rsbac_target_id.file.device = victim->f_path.dentry->d_sb->s_dev;
+			rsbac_target_id.file.inode  = victim->f_path.dentry->d_inode->i_ino;
+			rsbac_target_id.file.dentry_p = victim->f_path.dentry;
+		} else {
+			rsbac_target = T_NONE;
+			rsbac_target_id.dummy = 0;
+		}
+	rsbac_attribute_value.dummy = 0;
+	if ((rsbac_target != T_NONE) && !rsbac_adf_request(R_REMOVE_FROM_KERNEL,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto out_dput;
+	}
+#endif
+
 	mapping = victim->f_mapping;
 	spin_lock(&swap_lock);
 	plist_for_each_entry(p, &swap_active_head, list) {
@@ -2361,12 +2412,31 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	struct page *page = NULL;
 	struct inode *inode = NULL;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t          rsbac_target;
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (swap_flags & ~SWAP_FLAGS_VALID)
 		return -EINVAL;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_swap;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+		return -EPERM;
+#endif
+
 	p = alloc_swap_info();
 	if (IS_ERR(p))
 		return PTR_ERR(p);
@@ -2401,6 +2471,38 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	}
 
 	inode = mapping->host;
+
+/* RSBAC */
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "calling ADF for DEV / FILE\n");
+	if(S_ISBLK(inode->i_mode)) {
+		rsbac_target = T_DEV;
+		rsbac_target_id.dev.type = D_block;
+		rsbac_target_id.dev.major = RSBAC_MAJOR(inode->i_rdev);
+		rsbac_target_id.dev.minor = RSBAC_MINOR(inode->i_rdev);
+	} else if(S_ISREG(inode->i_mode)) {
+		rsbac_target = T_FILE;
+		rsbac_target_id.file.device = swap_file->f_path.dentry->d_sb->s_dev;
+		rsbac_target_id.file.inode  = inode->i_ino;
+		rsbac_target_id.file.dentry_p = swap_file->f_path.dentry;
+	} else {
+		rsbac_target = T_NONE;
+		rsbac_target_id.dummy = 0;
+	}
+	rsbac_attribute_value.dummy = 0;
+	if(   (rsbac_target != T_NONE)
+	   && !rsbac_adf_request(R_ADD_TO_KERNEL,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)
+	) {
+		error = -EPERM;
+		goto bad_swap;
+	}
+#endif
+
 	/* If S_ISREG(inode->i_mode) will do mutex_lock(&inode->i_mutex); */
 	error = claim_swapfile(p, inode);
 	if (unlikely(error))
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 1849d96..23f4d8b 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -25,6 +25,8 @@
 #include <net/sock.h>
 #include <linux/if_vlan.h>
 
+#include <rsbac/hooks.h>
+
 #include "br_private.h"
 
 /*
@@ -436,6 +438,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	int err = 0;
 	bool changed_addr;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* Don't allow bridging non-ethernet like devices, or DSA-enabled
 	 * master network devices since the bridge layer rx_handler prevents
 	 * the DSA fake ethertype handler to be invoked, so we do not strip off
@@ -456,6 +463,34 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (br_port_exists(dev))
 		return -EBUSY;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#ifndef CONFIG_RSBAC_NET_DEV_VIRT
+	{
+		char * p = rsbac_target_id.netdev;
+		while (*p) {
+			if (*p == ':') {
+				*p=' ';
+				break;
+			}
+			p++;
+		}
+	}
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+			task_pid(current),
+			T_NETDEV,
+			rsbac_target_id,
+			A_none,
+			rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	/* No bridging devices that dislike that (e.g. wireless) */
 	if (dev->priv_flags & IFF_DONT_BRIDGE)
 		return -EOPNOTSUPP;
@@ -553,10 +588,45 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
 	struct net_bridge_port *p;
 	bool changed_addr;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	p = br_port_get_rtnl(dev);
 	if (!p || p->br != br)
 		return -EINVAL;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#ifndef CONFIG_RSBAC_NET_DEV_VIRT
+	{
+		char * p = rsbac_target_id.netdev;
+		while (*p)
+		{
+			if (*p == ':')
+			{
+				*p=' ';
+				break;
+			}
+			p++;
+		}
+	}
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	/* Since more than one interface can be attached to a bridge,
 	 * there still maybe an alternate path for netconsole to use;
 	 * therefore there is no reason for a NETDEV_RELEASE event.
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 151e047..37a2315 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -6,6 +6,8 @@
 #include <linux/wireless.h>
 #include <net/wext.h>
 
+#include <rsbac/hooks.h>
+
 /*
  *	Map an interface index to its name (SIOCGIFNAME)
  */
@@ -397,6 +399,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	int ret;
 	char *colon;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* One special case: SIOCGIFCONF takes ifconf argument
 	   and requires shared lock, because it sleeps writing
 	   to user space.
@@ -416,10 +423,20 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 
 	ifr.ifr_name[IFNAMSIZ-1] = 0;
 
+#ifdef CONFIG_RSBAC_NET_DEV_VIRT
+	strncpy(rsbac_target_id.netdev, ifr.ifr_name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#endif
+
 	colon = strchr(ifr.ifr_name, ':');
 	if (colon)
 		*colon = 0;
 
+#if defined(CONFIG_RSBAC_NET_DEV) && !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	strncpy(rsbac_target_id.netdev, ifr.ifr_name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#endif
+
 	/*
 	 *	See which interface the caller is talking about.
 	 */
@@ -439,6 +456,20 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	case SIOCGIFMAP:
 	case SIOCGIFINDEX:
 	case SIOCGIFTXQLEN:
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_NETDEV,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+#endif
+
 		dev_load(net, ifr.ifr_name);
 		rcu_read_lock();
 		ret = dev_ifsioc_locked(net, &ifr, cmd);
@@ -525,6 +556,20 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	case SIOCSHWTSTAMP:
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EPERM;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_NETDEV,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+#endif
+
 		/* fall through */
 	case SIOCBONDSLAVEINFOQUERY:
 	case SIOCBONDINFOQUERY:
@@ -551,6 +596,20 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		    cmd == SIOCGHWTSTAMP ||
 		    (cmd >= SIOCDEVPRIVATE &&
 		     cmd <= SIOCDEVPRIVATE + 15)) {
+
+#ifdef CONFIG_RSBAC_NET_DEV
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_attribute_value.dummy = 0;
+			if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+						task_pid(current),
+						T_NETDEV,
+						rsbac_target_id,
+						A_none,
+						rsbac_attribute_value)) {
+				return -EPERM;
+			}
+#endif
+
 			dev_load(net, ifr.ifr_name);
 			rtnl_lock();
 			ret = dev_ifsioc(net, &ifr, cmd);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 0ad144f..4d12a06 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -17,6 +17,8 @@
 #include <net/sock.h>
 #include <net/fib_rules.h>
 
+#include <rsbac/hooks.h>
+
 int fib_default_rule_add(struct fib_rules_ops *ops,
 			 u32 pref, u32 table, u32 flags)
 {
@@ -270,6 +272,10 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 	struct fib_rule *rule, *r, *last = NULL;
 	struct nlattr *tb[FRA_MAX+1];
 	int err = -EINVAL, unresolved = 0;
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
 		goto errout;
@@ -288,6 +294,22 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 	if (err < 0)
 		goto errout;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "fib_nl_newrule(): calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	rule = kzalloc(ops->rule_size, GFP_KERNEL);
 	if (rule == NULL) {
 		err = -ENOMEM;
@@ -427,6 +449,10 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 	struct fib_rule *rule, *tmp;
 	struct nlattr *tb[FRA_MAX+1];
 	int err = -EINVAL;
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
 
 	if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
 		goto errout;
@@ -445,6 +471,22 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
 	if (err < 0)
 		goto errout;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "fib_nl_delrule(): calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	list_for_each_entry(rule, &ops->rules_list, list) {
 		if (frh->action && (frh->action != rule->action))
 			continue;
@@ -549,6 +591,25 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 {
 	struct nlmsghdr *nlh;
 	struct fib_rule_hdr *frh;
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "fib_nl_fill_rule(): calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
 
 	nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
 	if (nlh == NULL)
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 24b4174..f717647 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -118,6 +118,8 @@
 
 #include <linux/netfilter_arp.h>
 
+#include <rsbac/hooks.h>
+
 /*
  *	Interface to generic neighbour cache.
  */
@@ -1096,15 +1098,32 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	struct arpreq r;
 	struct net_device *dev = NULL;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	enum  rsbac_adf_request_t rsbac_request = R_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	switch (cmd) {
 	case SIOCDARP:
 	case SIOCSARP:
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EPERM;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_request = R_MODIFY_SYSTEM_DATA;
+#endif
+
 	case SIOCGARP:
 		err = copy_from_user(&r, arg, sizeof(struct arpreq));
 		if (err)
 			return -EFAULT;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		if (rsbac_request == R_NONE)
+			rsbac_request = R_GET_STATUS_DATA;
+#endif
+
 		break;
 	default:
 		return -EINVAL;
@@ -1132,6 +1151,24 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		err = -EINVAL;
 		if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type)
 			goto out;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_pr_debug(aef, "calling ADF\n");
+		strncpy(rsbac_target_id.netdev, r.arp_dev, RSBAC_IFNAMSIZ);
+		rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(rsbac_request,
+					task_pid(current),
+					T_NETDEV,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value))
+		{
+			err = -EPERM;
+			goto out;
+		}
+#endif
+
 	} else if (cmd == SIOCGARP) {
 		err = -ENODEV;
 		goto out;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 1d2fba4..4c67bab 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -67,6 +67,8 @@
 
 #include "fib_lookup.h"
 
+#include <rsbac/hooks.h>
+
 static struct ipv4_devconf ipv4_devconf = {
 	.data = {
 		[IPV4_DEVCONF_ACCEPT_REDIRECTS - 1] = 1,
@@ -581,6 +583,11 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct in_ifaddr *ifa, **ifap;
 	int err = -EINVAL;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	ASSERT_RTNL();
 
 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
@@ -594,6 +601,37 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
 		goto errout;
 	}
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	strncpy(rsbac_target_id.netdev, in_dev->dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#ifndef CONFIG_RSBAC_NET_DEV_VIRT
+	{
+		char * p = rsbac_target_id.netdev;
+
+		while (*p)
+		{
+			if (*p == ':')
+			{
+				*p=' ';
+				break;
+			}
+			p++;
+		}
+	}
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_BIND,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
 	     ifap = &ifa->ifa_next) {
 		if (tb[IFA_LOCAL] &&
@@ -753,6 +791,11 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
 	struct in_device *in_dev;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
 	if (err < 0)
 		goto errout;
@@ -772,6 +815,37 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
 	if (!in_dev)
 		goto errout;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	strncpy(rsbac_target_id.netdev, in_dev->dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#ifndef CONFIG_RSBAC_NET_DEV_VIRT
+	{
+		char * p = rsbac_target_id.netdev;
+		while (*p)
+		{
+			if (*p == ':')
+			{
+				*p=' ';
+				break;
+			}
+			p++;
+		}
+	}
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_BIND,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	ifa = inet_alloc_ifa();
 	if (!ifa)
 		/*
@@ -929,6 +1003,12 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	int ret = -EFAULT;
 	int tryaddrmatch = 0;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	enum  rsbac_adf_request_t rsbac_request = R_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/*
 	 *	Fetch the caller's info block into kernel space
 	 */
@@ -937,6 +1017,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		goto out;
 	ifr.ifr_name[IFNAMSIZ - 1] = 0;
 
+#ifdef CONFIG_RSBAC_NET_DEV_VIRT
+	strncpy(rsbac_target_id.netdev, ifr.ifr_name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#endif
+
 	/* save original address for comparison */
 	memcpy(&sin_orig, sin, sizeof(*sin));
 
@@ -944,6 +1029,11 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	if (colon)
 		*colon = 0;
 
+#if defined(CONFIG_RSBAC_NET_DEV) && !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	strncpy(rsbac_target_id.netdev, ifr.ifr_name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#endif
+
 	dev_load(net, ifr.ifr_name);
 
 	switch (cmd) {
@@ -958,12 +1048,22 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		tryaddrmatch = (sin_orig.sin_family == AF_INET);
 		memset(sin, 0, sizeof(*sin));
 		sin->sin_family = AF_INET;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_request = R_GET_STATUS_DATA;
+#endif
+
 		break;
 
 	case SIOCSIFFLAGS:
 		ret = -EPERM;
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			goto out;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_request = R_MODIFY_SYSTEM_DATA;
+#endif
+
 		break;
 	case SIOCSIFADDR:	/* Set interface address (and family) */
 	case SIOCSIFBRDADDR:	/* Set the broadcast address */
@@ -975,12 +1075,31 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		ret = -EINVAL;
 		if (sin->sin_family != AF_INET)
 			goto out;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_request = R_BIND;
+#endif
 		break;
 	default:
 		ret = -EINVAL;
 		goto out;
 	}
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		ret = -EPERM;
+		goto out;
+	}
+#endif
+
 	rtnl_lock();
 
 	ret = -ENODEV;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 5095491..b271187 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -46,6 +46,8 @@
 #include <net/rtnetlink.h>
 #include <net/xfrm.h>
 
+#include <rsbac/hooks.h>
+
 #ifndef CONFIG_IP_MULTIPLE_TABLES
 
 static int __net_init fib4_rules_init(struct net *net)
@@ -543,6 +545,11 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 	struct rtentry rt;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	switch (cmd) {
 	case SIOCADDRT:		/* Add a route */
 	case SIOCDELRT:		/* Delete a route */
@@ -552,6 +559,20 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		if (copy_from_user(&rt, arg, sizeof(rt)))
 			return -EFAULT;
 
+#ifdef CONFIG_RSBAC_NET
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.scd = ST_network;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+#endif
+
 		rtnl_lock();
 		err = rtentry_to_fib_config(net, cmd, &rt, &cfg);
 		if (err == 0) {
@@ -671,10 +692,30 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct fib_table *tb;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = rtm_to_fib_config(net, skb, nlh, &cfg);
 	if (err < 0)
 		goto errout;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	tb = fib_get_table(net, cfg.fc_table);
 	if (!tb) {
 		err = -ESRCH;
@@ -693,10 +734,30 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh)
 	struct fib_table *tb;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = rtm_to_fib_config(net, skb, nlh, &cfg);
 	if (err < 0)
 		goto errout;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	tb = fib_new_table(net, cfg.fc_table);
 	if (!tb) {
 		err = -ENOBUFS;
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 4d32262..cc52240 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -35,6 +35,8 @@
 #include <linux/inet_diag.h>
 #include <linux/sock_diag.h>
 
+#include <rsbac/hooks.h>
+
 static const struct inet_diag_handler **inet_diag_table;
 
 struct inet_diag_entry {
@@ -1019,6 +1021,11 @@ static int inet_diag_get_exact_compat(struct sk_buff *in_skb,
 
 static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	int hdrlen = sizeof(struct inet_diag_req);
 	struct net *net = sock_net(skb->sk);
 
@@ -1030,6 +1037,19 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
 		if (nlmsg_attrlen(nlh, hdrlen)) {
 			struct nlattr *attr;
 
+#ifdef CONFIG_RSBAC_NET
+			rsbac_pr_debug(aef, "calling ADF\n");
+			rsbac_target_id.scd = ST_network;
+			rsbac_attribute_value.dummy = 0;
+			if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value))
+				return -EPERM;
+#endif
+
 			attr = nlmsg_find_attr(nlh, hdrlen,
 					       INET_DIAG_REQ_BYTECODE);
 			if (!attr ||
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index c3bfebd..7104e92 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -67,6 +67,8 @@
 #include <net/fib_rules.h>
 #include <linux/netconf.h>
 
+#include <rsbac/hooks.h>
+
 #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
 #define CONFIG_IP_PIMSM	1
 #endif
@@ -1293,9 +1295,28 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
 		return -ENOENT;
 
 	if (optname != MRT_INIT) {
+#ifdef CONFIG_RSBAC_NET_DEV
+		union rsbac_target_id_t rsbac_target_id;
+		union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 		if (sk != rcu_access_pointer(mrt->mroute_sk) &&
 		    !ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EACCES;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_pr_debug(aef, "calling ADF\n");
+		rsbac_target_id.scd = ST_network;
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_SCD,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			return -EPERM;
+		}
+#endif
 	}
 
 	switch (optname) {
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8e729cb..62899d5 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -31,6 +31,8 @@
 #include <net/netfilter/nf_log.h>
 #include "../../netfilter/xt_repldata.h"
 
+#include <rsbac/hooks.h>
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
 MODULE_DESCRIPTION("IPv4 packet filter");
@@ -1147,6 +1149,24 @@ get_entries(struct net *net, struct ipt_get_entries __user *uptr,
 	struct ipt_get_entries get;
 	struct xt_table *t;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_firewall;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	if (*len < sizeof(get)) {
 		duprintf("get_entries: %u < %zu\n", *len, sizeof(get));
 		return -EINVAL;
@@ -1717,9 +1737,28 @@ compat_do_ipt_set_ctl(struct sock *sk,	int cmd, void __user *user,
 {
 	int ret;
 
+#ifdef CONFIG_RSBAC_NET
+        union rsbac_target_id_t       rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_firewall;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	switch (cmd) {
 	case IPT_SO_SET_REPLACE:
 		ret = compat_do_replace(sock_net(sk), user, len);
@@ -1786,6 +1825,26 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
 	struct compat_ipt_get_entries get;
 	struct xt_table *t;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_firewall;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+#endif
+
 	if (*len < sizeof(get)) {
 		duprintf("compat_get_entries: %u < %zu\n", *len, sizeof(get));
 		return -EINVAL;
@@ -1854,9 +1913,28 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 {
 	int ret;
 
+#ifdef CONFIG_RSBAC_NET
+        union rsbac_target_id_t rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_firewall;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	switch (cmd) {
 	case IPT_SO_SET_REPLACE:
 		ret = do_replace(sock_net(sk), user, len);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 7a64003..6cdd70e 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -110,6 +110,8 @@
 #endif
 #include <net/secure_seq.h>
 
+#include <rsbac/hooks.h>
+
 #define RT_FL_TOS(oldflp4) \
 	((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
 
@@ -2485,6 +2487,26 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 	int mark;
 	struct sk_buff *skb;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto errout;
+	}
+#endif
+
 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy);
 	if (err < 0)
 		goto errout;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index a75864d..5293698 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -30,6 +30,8 @@
 #include <net/pkt_sched.h>
 #include <net/pkt_cls.h>
 
+#include <rsbac/hooks.h>
+
 /* The list of all installed classifier types */
 static LIST_HEAD(tcf_proto_base);
 
@@ -139,10 +141,34 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
 	int err;
 	int tp_created = 0;
 
+#ifdef CONFIG_RSBAC_NET
+	enum  rsbac_adf_request_t rsbac_request;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if ((n->nlmsg_type != RTM_GETTFILTER) &&
 	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
 
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (n->nlmsg_type == RTM_GETTFILTER)
+		rsbac_request = R_GET_STATUS_DATA;
+	else
+		rsbac_request = R_MODIFY_SYSTEM_DATA;
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 replay:
 	err = nlmsg_parse(n, sizeof(*t), tca, TCA_MAX, NULL);
 	if (err < 0)
@@ -435,6 +461,25 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 	const struct Qdisc_class_ops *cops;
 	struct tcf_dump_args arg;
 
+#ifdef CONFIG_RSBAC_NET
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC_NET
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_network;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	if (nlmsg_len(cb->nlh) < sizeof(*tcm))
 		return skb->len;
 	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 2535305..304ae93 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -35,6 +35,8 @@
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 
+#include <rsbac/hooks.h>
+
 static int qdisc_notify(struct net *net, struct sk_buff *oskb,
 			struct nlmsghdr *n, u32 clid,
 			struct Qdisc *old, struct Qdisc *new);
@@ -1121,6 +1123,15 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
 	struct Qdisc *p = NULL;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	enum  rsbac_adf_request_t rsbac_request;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	char * rsbac_colon;
+#endif
+#endif
+
 	if ((n->nlmsg_type != RTM_GETQDISC) &&
 	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
@@ -1133,6 +1144,30 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
 	if (!dev)
 		return -ENODEV;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (n->nlmsg_type == RTM_GETQDISC)
+		rsbac_request = R_GET_STATUS_DATA;
+	else
+		rsbac_request = R_MODIFY_SYSTEM_DATA;
+	strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	rsbac_colon = strchr(rsbac_target_id.netdev, ':');
+	if (rsbac_colon)
+		*rsbac_colon = 0;
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	clid = tcm->tcm_parent;
 	if (clid) {
 		if (clid != TC_H_ROOT) {
@@ -1189,6 +1224,14 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n)
 	struct Qdisc *q, *p;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	char * rsbac_colon;
+#endif
+#endif
+
 	if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
 
@@ -1206,6 +1249,25 @@ replay:
 	if (!dev)
 		return -ENODEV;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "tc_modify_qdisc(): calling ADF\n");
+	strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	rsbac_colon = strchr(rsbac_target_id.netdev, ':');
+	if (rsbac_colon)
+		*rsbac_colon = 0;
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
 
 	if (clid) {
 		if (clid != TC_H_ROOT) {
@@ -1479,6 +1541,14 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
 	int s_idx, s_q_idx;
 	struct net_device *dev;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	char * rsbac_colon;
+#endif
+#endif
+
 	s_idx = cb->args[0];
 	s_q_idx = q_idx = cb->args[1];
 
@@ -1491,6 +1561,27 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
 			goto cont;
 		if (idx > s_idx)
 			s_q_idx = 0;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+		rsbac_pr_debug(aef, "tc_dump_qdisc(): calling ADF\n");
+		strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+		rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+		rsbac_colon = strchr(rsbac_target_id.netdev, ':');
+		if(rsbac_colon)
+			*rsbac_colon = 0;
+#endif
+		rsbac_attribute_value.dummy = 0;
+		if (!rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					T_NETDEV,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value)) {
+			goto cont;
+		}
+#endif
+
 		q_idx = 0;
 
 		if (tc_dump_qdisc_root(dev->qdisc, skb, cb, &q_idx, s_q_idx) < 0)
@@ -1536,6 +1627,15 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n)
 	u32 qid;
 	int err;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	enum  rsbac_adf_request_t rsbac_request;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	char * rsbac_colon;
+#endif
+#endif
+
 	if ((n->nlmsg_type != RTM_GETTCLASS) &&
 	    !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
 		return -EPERM;
@@ -1548,6 +1648,30 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n)
 	if (!dev)
 		return -ENODEV;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "tc_ctl_tclass(): calling ADF\n");
+	if (n->nlmsg_type == RTM_GETTCLASS)
+		rsbac_request = R_GET_STATUS_DATA;
+	else
+		rsbac_request = R_MODIFY_SYSTEM_DATA;
+	strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	rsbac_colon = strchr(rsbac_target_id.netdev, ':');
+	if (rsbac_colon)
+		*rsbac_colon = 0;
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(rsbac_request,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		return -EPERM;
+	}
+#endif
+
 	/*
 	   parent == TC_H_UNSPEC - unspecified parent.
 	   parent == TC_H_ROOT   - class is root, which has no parent.
@@ -1791,12 +1915,41 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
 	struct net_device *dev;
 	int t, s_t;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	char * rsbac_colon;
+#endif
+#endif
+
 	if (nlmsg_len(cb->nlh) < sizeof(*tcm))
 		return 0;
 	dev = dev_get_by_index(net, tcm->tcm_ifindex);
 	if (!dev)
 		return 0;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, "calling ADF\n");
+	strncpy(rsbac_target_id.netdev, dev->name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#if !defined(CONFIG_RSBAC_NET_DEV_VIRT)
+	rsbac_colon = strchr(rsbac_target_id.netdev, ':');
+	if (rsbac_colon)
+		*rsbac_colon = 0;
+#endif
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value)) {
+		dev_put(dev);
+		return -EPERM;
+	}
+#endif
+
 	s_t = cb->args[0];
 	t = 0;
 
diff --git a/net/socket.c b/net/socket.c
index 12d681c..e9312f3 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -90,6 +90,14 @@
 #include <linux/slab.h>
 #include <linux/xattr.h>
 
+#ifdef CONFIG_RSBAC
+#include <net/af_unix.h>
+#include <net/scm.h>
+#include <rsbac/hooks.h>
+#define rsbac_unix_peer(sk) (unix_sk(sk)->peer)
+#define rsbac_unix_sk_peer(sk) (unix_sk(unix_sk(sk)->peer))
+#endif
+
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
@@ -610,8 +618,78 @@ EXPORT_SYMBOL(__sock_tx_timestamp);
 
 static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg)
 {
-	int ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
+	int ret;
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	rsbac_pr_debug(aef, "[sys_send(), sys_sendto(), sys_sendmsg()]: calling ADF\n");
+	if (sock->ops->family != AF_UNIX) {
+#if !defined(CONFIG_RSBAC_NET_OBJ_RW)
+		if(sock->type != SOCK_STREAM)
+#endif
+		{
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p = sock;
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = msg->msg_name;
+			rsbac_target_id.netobj.remote_len = msg->msg_namelen;
+			rsbac_attribute_value.process = get_pid(sock->sk->sk_peer_pid);
+			if (rsbac_attribute_value.process) {
+				if (pid_nr(rsbac_attribute_value.process) > 0) {
+					rsbac_attribute = A_process;
+				} else {
+					put_pid(rsbac_attribute_value.process);
+					rsbac_attribute = A_sock_type;
+					rsbac_attribute_value.sock_type = sock->type;
+				}
+			} else {
+				rsbac_attribute = A_sock_type;
+				rsbac_attribute_value.sock_type = sock->type;
+			}
+			if (!rsbac_adf_request(R_SEND,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				rsbac_attribute,
+				rsbac_attribute_value))	{
+				if (rsbac_attribute == A_process)
+					put_pid(rsbac_attribute_value.process);
+				return -EPERM;
+			}
+		}
+	}
+#endif
+
+	ret = sock->ops->sendmsg(sock, msg, msg_data_left(msg));
 	BUG_ON(ret == -EIOCBQUEUED);
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	if (!ret && (rsbac_target != T_NONE)) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_SEND,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sock_sendmsg() [sys_send(), sys_sendto(), sys_sendmsg()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return ret;
 }
 
@@ -712,7 +790,80 @@ EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
 static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
 				     size_t size, int flags)
 {
-	return sock->ops->recvmsg(sock, msg, size, flags);
+	int ret;
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+	ret = sock->ops->recvmsg(sock, msg, size, flags);
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	if (ret > 0) {
+		rsbac_pr_debug(aef, "[sys_recv(), sys_recvfrom(), sys_recvmsg()]: calling ADF\n");
+		if (sock->ops->family != AF_UNIX) {
+#if !defined(CONFIG_RSBAC_NET_OBJ_RW)
+			if (sock->type != SOCK_STREAM)
+#endif
+			{
+				rsbac_target = T_NETOBJ;
+				rsbac_target_id.netobj.sock_p = sock;
+				rsbac_target_id.netobj.local_addr = NULL;
+				rsbac_target_id.netobj.local_len = 0;
+				rsbac_target_id.netobj.remote_addr = msg->msg_name;
+				rsbac_target_id.netobj.remote_len = msg->msg_namelen;
+				rsbac_attribute_value.process = get_pid(sock->sk->sk_peer_pid);
+				if (rsbac_attribute_value.process) {
+					if (pid_nr(rsbac_attribute_value.process) > 0) {
+						rsbac_attribute = A_process;
+					} else {
+						put_pid(rsbac_attribute_value.process);
+						rsbac_attribute = A_sock_type;
+						rsbac_attribute_value.sock_type = sock->type;
+					}
+				} else {
+					rsbac_attribute = A_sock_type;
+					rsbac_attribute_value.sock_type = sock->type;
+				}
+				if (!rsbac_adf_request(R_RECEIVE,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						rsbac_attribute,
+						rsbac_attribute_value)) {
+					if (rsbac_attribute == A_process)
+						put_pid(rsbac_attribute_value.process);
+					return -EPERM;
+				}
+			}
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	if ((ret > 0) && (rsbac_target != T_NONE)) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_RECEIVE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sock_recvmsg() [sys_recv(), sys_recvfrom(), sys_recvmsg()]: rsbac_adf_set_attr() for RECEIVE returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
+	return ret;
 }
 
 int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
@@ -1225,6 +1376,13 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
 	struct socket *sock;
 	int flags;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union  rsbac_target_id_t rsbac_target_id;
+	union  rsbac_target_id_t rsbac_new_target_id;
+	union  rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	/* Check the SOCK_* constants for consistency.  */
 	BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
 	BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
@@ -1243,10 +1401,58 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
 	if (retval < 0)
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	if (family == AF_UNIX) {
+		rsbac_target = T_IPC;
+		rsbac_target_id.ipc.type = I_anonunix;
+		rsbac_target_id.ipc.id.id_nr = SOCK_INODE(sock)->i_ino;
+	}
+#ifdef CONFIG_RSBAC_NET_OBJ
+	else {
+		rsbac_pr_debug(aef, "[sys_socket()]: calling ADF\n");
+		rsbac_target = T_NETOBJ;
+		rsbac_target_id.netobj.sock_p = sock;
+		rsbac_target_id.netobj.local_addr = NULL;
+		rsbac_target_id.netobj.local_len = 0;
+		rsbac_target_id.netobj.remote_addr = NULL;
+		rsbac_target_id.netobj.remote_len = 0;
+	}
+#endif
+	rsbac_attribute_value.sock_type = type;
+	if ((rsbac_target != T_NONE)
+			&& !rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_sock_type,
+				rsbac_attribute_value)) {
+		rsbac_pr_debug(aef, "[sys_socket()]: ADF returned NOT_GRANTED\n");
+		retval = -EPERM;
+		goto out_release;
+	}
+#endif
+
 	retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
 	if (retval < 0)
 		goto out_release;
 
+#ifdef CONFIG_RSBAC
+	if(rsbac_target != T_NONE) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_CREATE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_sock_type,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"sys_socket(): rsbac_adf_set_attr() returned error\n");
+		}
+	}
+#endif
+
 out:
 	/* It may be already another descriptor 8) Not kernel problem. */
 	return retval;
@@ -1268,6 +1474,12 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
 	struct file *newfile1, *newfile2;
 	int flags;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	flags = type & ~SOCK_TYPE_MASK;
 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
 		return -EINVAL;
@@ -1285,10 +1497,43 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
 	if (err < 0)
 		goto out;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "sys_socketpair() [sys_socketcall()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_anonunix;
+	rsbac_target_id.ipc.id.id_nr = SOCK_INODE(sock1)->i_ino;
+	rsbac_attribute_value.sock_type = type;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_sock_type,
+				rsbac_attribute_value)) {
+		rsbac_pr_debug(aef, "sys_socketpair() [sys_socketcall()]: ADF returned NOT_GRANTED\n");
+		err = -EPERM;
+		goto out_release_1;
+	}
+#endif
+
 	err = sock_create(family, type, protocol, &sock2);
 	if (err < 0)
 		goto out_release_1;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "sys_socketpair() [sys_socketcall()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_anonunix;
+	rsbac_target_id.ipc.id.id_nr = SOCK_INODE(sock2)->i_ino;
+	if (!rsbac_adf_request(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_sock_type,
+				rsbac_attribute_value)) {
+		rsbac_pr_debug(aef, "sys_socketpair() [sys_socketcall()]: ADF returned NOT_GRANTED\n");
+		err = -EPERM;
+		goto out_release_both;
+	}
+#endif
+
 	err = sock1->ops->socketpair(sock1, sock2);
 	if (err < 0)
 		goto out_release_both;
@@ -1333,6 +1578,34 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
 	 * Not kernel problem.
 	 */
 
+#ifdef CONFIG_RSBAC
+	rsbac_target_id.ipc.id.id_nr = SOCK_INODE(sock1)->i_ino;
+	rsbac_new_target_id.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_sock_type,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"sys_socketpair() [sys_socketcall()]: rsbac_adf_set_attr() for sock1 returned error\n");
+	}
+	rsbac_target_id.ipc.id.id_nr = SOCK_INODE(sock2)->i_ino;
+	if (unlikely(rsbac_adf_set_attr(R_CREATE,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_sock_type,
+				rsbac_attribute_value))) {
+		rsbac_printk(KERN_WARNING
+				"sys_socketpair() [sys_socketcall()]: rsbac_adf_set_attr() for sock2 returned error\n");
+	}
+#endif
+
 	return 0;
 
 out_fput_both:
@@ -1375,10 +1648,38 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
 	struct sockaddr_storage address;
 	int err, fput_needed;
 
+#ifdef CONFIG_RSBAC_NET_OBJ
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t	rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (sock) {
 		err = move_addr_to_kernel(umyaddr, addrlen, &address);
 		if (err >= 0) {
+#ifdef CONFIG_RSBAC_NET_OBJ
+			if (sock->ops->family != AF_UNIX) {
+				rsbac_target_id.netobj.sock_p = sock;
+				rsbac_target_id.netobj.local_addr = (struct sockaddr *)&address;
+				rsbac_target_id.netobj.local_len = addrlen;
+				rsbac_target_id.netobj.remote_addr = NULL;
+				rsbac_target_id.netobj.remote_len = 0;
+				rsbac_attribute_value.sock_type = sock->type;
+				rsbac_pr_debug(aef, "[sys_socketcall()]: calling ADF");
+				if(!rsbac_adf_request(R_BIND,
+							task_pid(current),
+							T_NETOBJ,
+							rsbac_target_id,
+							A_sock_type,
+							rsbac_attribute_value)) {
+					rsbac_pr_debug(aef, "[sys_socketcall()]: ADF returned NOT_GRANTED\n");
+					fput_light(sock->file, fput_needed);
+					return -EPERM;
+				}
+			}
+#endif
+
 			err = security_socket_bind(sock,
 						   (struct sockaddr *)&address,
 						   addrlen);
@@ -1386,6 +1687,23 @@ SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
 				err = sock->ops->bind(sock,
 						      (struct sockaddr *)
 						      &address, addrlen);
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+			if (!err && sock->ops && (sock->ops->family != AF_UNIX)) {
+				rsbac_new_target_id.dummy = 0;
+				if (unlikely(rsbac_adf_set_attr(R_BIND,
+							task_pid(current),
+							T_NETOBJ,
+							rsbac_target_id,
+							T_NONE,
+							rsbac_new_target_id,
+							A_sock_type,
+							rsbac_attribute_value))) {
+					rsbac_printk(KERN_WARNING
+							"sys_bind() [sys_socketcall()]: rsbac_adf_set_attr() returned error\n");
+				}
+			}
+#endif
 		}
 		fput_light(sock->file, fput_needed);
 	}
@@ -1402,10 +1720,60 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
 {
 	struct socket *sock;
 	int err, fput_needed;
+
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	int somaxconn;
 
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (sock) {
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "[sys_socketcall()]: calling ADF\n");
+		if (sock->ops->family == AF_UNIX) {
+			if (sock->file
+			&& sock->file->f_path.dentry
+			&& sock->file->f_path.dentry->d_inode) {
+				if (sock->file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+					rsbac_target = T_IPC;
+					rsbac_target_id.ipc.type = I_anonunix;
+					rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+				} else {
+					rsbac_target = T_UNIXSOCK;
+					rsbac_target_id.unixsock.device = sock->file->f_path.dentry->d_sb->s_dev;
+					rsbac_target_id.unixsock.inode  = sock->file->f_path.dentry->d_inode->i_ino;
+					rsbac_target_id.unixsock.dentry_p = sock->file->f_path.dentry;
+				}
+			}
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p = sock;
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+		rsbac_attribute_value.sock_type = sock->type;
+		if ((rsbac_target != T_NONE)
+				&& !rsbac_adf_request(R_LISTEN,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_sock_type,
+					rsbac_attribute_value)) {
+			rsbac_pr_debug(aef, "sys_listen() [sys_socketcall()]: ADF returned NOT_GRANTED\n");
+			fput_light(sock->file, fput_needed);
+			return -EPERM;
+		}
+#endif
+
 		somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
 		if ((unsigned int)backlog > somaxconn)
 			backlog = somaxconn;
@@ -1414,6 +1782,23 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
 		if (!err)
 			err = sock->ops->listen(sock, backlog);
 
+
+#ifdef CONFIG_RSBAC
+		if (!err && (rsbac_target != T_NONE)) {
+			rsbac_new_target_id.dummy = 0;
+			if (unlikely(rsbac_adf_set_attr(R_LISTEN,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_sock_type,
+						rsbac_attribute_value)))
+				rsbac_printk(KERN_WARNING
+						"sys_listen() [sys_socketcall()]: rsbac_adf_set_attr() returned error\n");
+		}
+#endif
+
 		fput_light(sock->file, fput_needed);
 	}
 	return err;
@@ -1439,6 +1824,14 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
 	int err, len, newfd, fput_needed;
 	struct sockaddr_storage address;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
 		return -EINVAL;
 
@@ -1485,6 +1878,122 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
 	if (err < 0)
 		goto out_fd;
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "[sys_socketcall()]: calling ADF\n");
+	if (sock->ops->family == AF_UNIX) {
+		if (sock->sk) {
+			if (unix_sk(unix_sk(sock->sk)->peer)) {
+				if (unix_sk(unix_sk(sock->sk)->peer)->path.dentry
+						&& unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode) {
+					rsbac_target = T_UNIXSOCK;
+					rsbac_target_id.unixsock.device = unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_sb->s_dev;
+					rsbac_target_id.unixsock.inode  = unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode->i_ino;
+					rsbac_target_id.unixsock.dentry_p = unix_sk(unix_sk(sock->sk)->peer)->path.dentry;
+				} else {
+					rsbac_target = T_IPC;
+					rsbac_target_id.ipc.type = I_anonunix;
+					if (unix_sk(unix_sk(sock->sk)->peer)->path.dentry
+							&& unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode
+							&& SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file
+							&& SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file->f_path.dentry
+							&& SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file->f_path.dentry->d_inode)
+						rsbac_target_id.ipc.id.id_nr = SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file->f_path.dentry->d_inode->i_ino;
+					else
+						if (sock->file
+								&& sock->file->f_path.dentry
+								&& sock->file->f_path.dentry->d_inode)
+							rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+						else
+							rsbac_target_id.ipc.id.id_nr = 0;
+				}
+			} else {
+				if(   unix_sk(sock->sk)->path.dentry
+						&& unix_sk(sock->sk)->path.dentry->d_inode) {
+					rsbac_target = T_UNIXSOCK;
+					rsbac_target_id.unixsock.device = unix_sk(sock->sk)->path.dentry->d_sb->s_dev;
+					rsbac_target_id.unixsock.inode  = unix_sk(sock->sk)->path.dentry->d_inode->i_ino;
+					rsbac_target_id.unixsock.dentry_p = unix_sk(sock->sk)->path.dentry;
+				} else {
+					rsbac_target = T_IPC;
+					rsbac_target_id.ipc.type = I_anonunix;
+					if (sock->file
+							&& sock->file->f_path.dentry
+							&& sock->file->f_path.dentry->d_inode)
+						rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+					else
+						rsbac_target_id.ipc.id.id_nr = 0;
+				}
+			}
+		}
+		if (sock->sk) {
+			rsbac_attribute_value.process = get_pid(sock->sk->sk_peer_pid);
+			if (rsbac_attribute_value.process) {
+				if (pid_nr(rsbac_attribute_value.process) > 0) {
+					rsbac_attribute = A_process;
+					rsbac_attribute_value.process = sock->sk->sk_peer_pid;
+				} else {
+					put_pid(rsbac_attribute_value.process);
+					rsbac_attribute = A_sock_type;
+					rsbac_attribute_value.sock_type = sock->type;
+				}
+			} else {
+				rsbac_attribute = A_sock_type;
+				rsbac_attribute_value.sock_type = sock->type;
+			}
+		} else {
+			rsbac_attribute = A_sock_type;
+			rsbac_attribute_value.sock_type = sock->type;
+		}
+	}
+#ifdef CONFIG_RSBAC_NET_OBJ
+	else {
+		rsbac_target = T_NETOBJ;
+		rsbac_target_id.netobj.sock_p = newsock;
+		rsbac_target_id.netobj.local_addr = NULL;
+		rsbac_target_id.netobj.local_len = 0;
+		if(newsock->ops->getname(newsock, (struct sockaddr *)&address, &len, 2) <0) {
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		} else {
+			rsbac_target_id.netobj.remote_addr = (struct sockaddr *)&address;
+			rsbac_target_id.netobj.remote_len = len;
+		}
+		if (sock->sk) {
+			rsbac_attribute_value.process = get_pid(sock->sk->sk_peer_pid);
+			if (rsbac_attribute_value.process) {
+				if (pid_nr(rsbac_attribute_value.process) > 0) {
+					rsbac_attribute = A_process;
+					rsbac_attribute_value.process = sock->sk->sk_peer_pid;
+				} else {
+					put_pid(rsbac_attribute_value.process);
+					rsbac_attribute = A_sock_type;
+					rsbac_attribute_value.sock_type = sock->type;
+				}
+			} else {
+				rsbac_attribute = A_sock_type;
+				rsbac_attribute_value.sock_type = sock->type;
+			}
+		} else {
+			rsbac_attribute = A_sock_type;
+			rsbac_attribute_value.sock_type = sock->type;
+		}
+	}
+#endif
+	if ((rsbac_target != T_NONE)
+		&& !rsbac_adf_request(R_ACCEPT,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				rsbac_attribute,
+				rsbac_attribute_value)) {
+		rsbac_pr_debug(aef, "[sys_socketcall()]: ADF returned NOT_GRANTED\n");
+		err = -EPERM;
+		if (rsbac_attribute == A_process)
+			put_pid(rsbac_attribute_value.process);
+		goto out_fd;
+	}
+#endif
+
 	if (upeer_sockaddr) {
 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
 					  &len, 2) < 0) {
@@ -1502,6 +2011,24 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
 	fd_install(newfd, newfile);
 	err = newfd;
 
+#ifdef CONFIG_RSBAC
+	if (rsbac_target != T_NONE) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_ACCEPT,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value)))
+			rsbac_printk(KERN_WARNING
+					"sys_accept() [sys_socketcall()]: rsbac_adf_set_attr() returned error\n");
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 out_put:
 	fput_light(sock->file, fput_needed);
 out:
@@ -1537,6 +2064,12 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
 	struct sockaddr_storage address;
 	int err, fput_needed;
 
+#ifdef CONFIG_RSBAC_NET_OBJ
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
@@ -1549,8 +2082,50 @@ SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
 	if (err)
 		goto out_put;
 
+	/* RSBAC UNIX socket connects get intercepted in unix/af_unix.c */
+#ifdef CONFIG_RSBAC_NET_OBJ
+	if (sock->ops->family != AF_UNIX) {
+		rsbac_pr_debug(aef, "[sys_socketcall()]: calling ADF\n");
+		rsbac_target_id.netobj.sock_p = sock;
+		rsbac_target_id.netobj.local_addr = NULL;
+		rsbac_target_id.netobj.local_len = 0;
+		rsbac_target_id.netobj.remote_addr = (struct sockaddr *)&address;
+		rsbac_target_id.netobj.remote_len = addrlen;
+		rsbac_attribute_value.sock_type = sock->type;
+		if (!rsbac_adf_request(R_CONNECT,
+					task_pid(current),
+					T_NETOBJ,
+					rsbac_target_id,
+					A_sock_type,
+					rsbac_attribute_value)) {
+			rsbac_pr_debug(aef, "[sys_socketcall()]: ADF returned NOT_GRANTED\n");
+			err = -EPERM;
+			goto out_put;
+		}
+	}
+#endif
+
 	err = sock->ops->connect(sock, (struct sockaddr *)&address, addrlen,
 				 sock->file->f_flags);
+
+	/* RSBAC: notify ADF of opened socket connection */
+#ifdef CONFIG_RSBAC_NET_OBJ
+	if (!err
+		&& (sock->ops->family != AF_UNIX)) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_CONNECT,
+					task_pid(current),
+					T_NETOBJ,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_sock_type,
+					rsbac_attribute_value)))
+			rsbac_printk(KERN_WARNING
+					"sys_connect() [sys_socketcall()]: rsbac_adf_set_attr() returned error\n");
+	}
+#endif
+
 out_put:
 	fput_light(sock->file, fput_needed);
 out:
@@ -1569,6 +2144,12 @@ SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
 	struct sockaddr_storage address;
 	int len, err, fput_needed;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
@@ -1577,6 +2158,47 @@ SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
 	if (err)
 		goto out_put;
 
+#if defined(CONFIG_RSBAC)
+	rsbac_pr_debug(aef, "calling ADF\n");
+	if (sock->ops->family == AF_UNIX) {
+		if (sock->file
+		&& sock->file->f_path.dentry
+		&& sock->file->f_path.dentry->d_inode) {
+			if (sock->file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+				rsbac_target = T_IPC;
+				rsbac_target_id.ipc.type = I_anonunix;
+				rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+			} else {
+				rsbac_target = T_UNIXSOCK;
+				rsbac_target_id.unixsock.device = sock->file->f_path.dentry->d_sb->s_dev;
+				rsbac_target_id.unixsock.inode  = sock->file->f_path.dentry->d_inode->i_ino;
+				rsbac_target_id.unixsock.dentry_p = sock->file->f_path.dentry;
+			}
+		}
+	}
+#ifdef CONFIG_RSBAC_NET_OBJ
+	else {
+		rsbac_target = T_NETOBJ;
+		rsbac_target_id.netobj.sock_p = sock;
+		rsbac_target_id.netobj.local_addr = NULL;
+		rsbac_target_id.netobj.local_len = 0;
+		rsbac_target_id.netobj.remote_addr = NULL;
+		rsbac_target_id.netobj.remote_len = 0;
+	}
+#endif
+	rsbac_attribute_value.sock_type = sock->type;
+	if ((rsbac_target != T_NONE)
+		&& !rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				A_sock_type,
+				rsbac_attribute_value)) {
+		err = -EPERM;
+		goto out_put;
+	}
+#endif
+
 	err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
 	if (err)
 		goto out_put;
@@ -1600,6 +2222,12 @@ SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
 	struct sockaddr_storage address;
 	int len, err, fput_needed;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (sock != NULL) {
 		err = security_socket_getpeername(sock);
@@ -1608,6 +2236,47 @@ SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
 			return err;
 		}
 
+#if defined(CONFIG_RSBAC)
+		rsbac_pr_debug(aef, "calling ADF\n");
+		if (sock->ops->family == AF_UNIX) {
+			if (sock->file
+			&& sock->file->f_path.dentry
+			&& sock->file->f_path.dentry->d_inode) {
+				if (sock->file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+					rsbac_target = T_IPC;
+					rsbac_target_id.ipc.type = I_anonunix;
+					rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+				} else {
+					rsbac_target = T_UNIXSOCK;
+					rsbac_target_id.unixsock.device = sock->file->f_path.dentry->d_sb->s_dev;
+					rsbac_target_id.unixsock.inode  = sock->file->f_path.dentry->d_inode->i_ino;
+					rsbac_target_id.unixsock.dentry_p = sock->file->f_path.dentry;
+				}
+			}
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p = sock;
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+		rsbac_attribute_value.sock_type = sock->type;
+		if ((rsbac_target != T_NONE)
+				&& !rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_sock_type,
+					rsbac_attribute_value)) {
+			fput_light(sock->file, fput_needed);
+			return -EPERM;
+		}
+#endif
+
 		err =
 		    sock->ops->getname(sock, (struct sockaddr *)&address, &len,
 				       1);
@@ -1744,6 +2413,12 @@ SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
 	int err, fput_needed;
 	struct socket *sock;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	if (optlen < 0)
 		return -EINVAL;
 
@@ -1753,6 +2428,47 @@ SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
 		if (err)
 			goto out_put;
 
+#if defined(CONFIG_RSBAC)
+		rsbac_pr_debug(aef, "calling ADF\n");
+		if (sock->ops->family == AF_UNIX) {
+			if (sock->file
+			&& sock->file->f_path.dentry
+			&& sock->file->f_path.dentry->d_inode) {
+				if (sock->file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+					rsbac_target = T_IPC;
+					rsbac_target_id.ipc.type = I_anonunix;
+					rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+				} else {
+					rsbac_target = T_UNIXSOCK;
+					rsbac_target_id.unixsock.device = sock->file->f_path.dentry->d_sb->s_dev;
+					rsbac_target_id.unixsock.inode  = sock->file->f_path.dentry->d_inode->i_ino;
+					rsbac_target_id.unixsock.dentry_p = sock->file->f_path.dentry;
+				}
+			}
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p = sock;
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+		rsbac_attribute_value.setsockopt_level = level;
+		if ((rsbac_target != T_NONE)
+				&& !rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_setsockopt_level,
+					rsbac_attribute_value)) {
+			err = -EPERM;
+			goto out_put;
+		}
+#endif
+
 		if (level == SOL_SOCKET)
 			err =
 			    sock_setsockopt(sock, level, optname, optval,
@@ -1778,12 +2494,62 @@ SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
 	int err, fput_needed;
 	struct socket *sock;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (sock != NULL) {
 		err = security_socket_getsockopt(sock, level, optname);
 		if (err)
 			goto out_put;
 
+#if defined(CONFIG_RSBAC)
+		rsbac_pr_debug(aef, "calling ADF\n");
+		if (sock->ops->family == AF_UNIX) {
+			if (sock->file
+			&& sock->file->f_path.dentry
+			&& sock->file->f_path.dentry->d_inode
+			&& sock->file->f_path.dentry->d_inode->i_ino
+			&& sock->file->f_path.dentry->d_sb
+			&& sock->file->f_path.dentry->d_sb->s_dev) {
+				if (sock->file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+					rsbac_target = T_IPC;
+					rsbac_target_id.ipc.type = I_anonunix;
+					rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+				} else {
+					rsbac_target = T_UNIXSOCK;
+					rsbac_target_id.unixsock.device = sock->file->f_path.dentry->d_sb->s_dev;
+					rsbac_target_id.unixsock.inode  = sock->file->f_path.dentry->d_inode->i_ino;
+					rsbac_target_id.unixsock.dentry_p = sock->file->f_path.dentry;
+				}
+			}
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+		else {
+			rsbac_target = T_NETOBJ;
+			rsbac_target_id.netobj.sock_p = sock;
+			rsbac_target_id.netobj.local_addr = NULL;
+			rsbac_target_id.netobj.local_len = 0;
+			rsbac_target_id.netobj.remote_addr = NULL;
+			rsbac_target_id.netobj.remote_len = 0;
+		}
+#endif
+		rsbac_attribute_value.sock_type = sock->type;
+		if ((rsbac_target != T_NONE)
+				&& !rsbac_adf_request(R_GET_STATUS_DATA,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_sock_type,
+					rsbac_attribute_value)) {
+			err = -EPERM;
+			goto out_put;
+		}
+#endif
+
 		if (level == SOL_SOCKET)
 			err =
 			    sock_getsockopt(sock, level, optname, optval,
@@ -1807,11 +2573,83 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how)
 	int err, fput_needed;
 	struct socket *sock;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+#ifdef CONFIG_RSBAC_NET_OBJ
+	union rsbac_target_id_t rsbac_new_target_id;
+#endif
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (sock != NULL) {
 		err = security_socket_shutdown(sock, how);
+
+#ifdef CONFIG_RSBAC
+		if (!err) {
+			rsbac_pr_debug(aef, "[sys_socketcall()]: calling ADF\n");
+			if (sock->ops->family == AF_UNIX) {
+				if (sock->file
+				&& sock->file->f_path.dentry
+				&& sock->file->f_path.dentry->d_inode) {
+					if (sock->file->f_path.dentry->d_sb->s_magic == SOCKFS_MAGIC) {
+						rsbac_target = T_IPC;
+						rsbac_target_id.ipc.type = I_anonunix;
+						rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+					} else {
+						rsbac_target = T_UNIXSOCK;
+						rsbac_target_id.unixsock.device = sock->file->f_path.dentry->d_sb->s_dev;
+						rsbac_target_id.unixsock.inode  = sock->file->f_path.dentry->d_inode->i_ino;
+						rsbac_target_id.unixsock.dentry_p = sock->file->f_path.dentry;
+					}
+				}
+			}
+#ifdef CONFIG_RSBAC_NET_OBJ
+			else {
+				rsbac_target = T_NETOBJ;
+				rsbac_target_id.netobj.sock_p = sock;
+				rsbac_target_id.netobj.local_addr = NULL;
+				rsbac_target_id.netobj.local_len = 0;
+				rsbac_target_id.netobj.remote_addr = NULL;
+				rsbac_target_id.netobj.remote_len = 0;
+			}
+#endif
+			rsbac_attribute_value.sock_type = sock->type;
+			if ((rsbac_target != T_NONE)
+					&& !rsbac_adf_request(R_NET_SHUTDOWN,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						A_sock_type,
+						rsbac_attribute_value)) {
+				err = -EPERM;
+			}
+		}
+#endif
+
 		if (!err)
 			err = sock->ops->shutdown(sock, how);
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+		if (!err && (rsbac_target != T_NONE)) {
+			rsbac_pr_debug(aef, "calling rsbac_adf_set_attr() for NET_SHUTDOWN on netobj\n");
+			rsbac_new_target_id.dummy = 0;
+			rsbac_attribute_value.dummy = 0;
+			if (unlikely(rsbac_adf_set_attr(R_NET_SHUTDOWN,
+						task_pid(current),
+						rsbac_target,
+						rsbac_target_id,
+						T_NONE,
+						rsbac_new_target_id,
+						A_sock_type,
+						rsbac_attribute_value))) {
+				rsbac_printk(KERN_WARNING
+						"sys_shutdown(): rsbac_adf_set_attr() for NET_SHUTDOWN on socket returned error\n");
+			}
+		}
+#endif
+
 		fput_light(sock->file, fput_needed);
 	}
 	return err;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index ce6f2bf..b5d8fc8 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -118,6 +118,8 @@
 #include <linux/security.h>
 #include <linux/freezer.h>
 
+#include <rsbac/hooks.h>
+
 struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
 EXPORT_SYMBOL_GPL(unix_socket_table);
 DEFINE_SPINLOCK(unix_table_lock);
@@ -810,9 +812,24 @@ static int unix_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t       rsbac_target_id;
+#endif
+
 	if (!sk)
 		return 0;
 
+#ifdef CONFIG_RSBAC
+	if (   sock->file
+		&& sock->file->f_path.dentry
+		&& sock->file->f_path.dentry->d_inode
+	   ) {
+		rsbac_target_id.ipc.type = I_anonunix;
+		rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+		rsbac_remove_target(T_IPC, rsbac_target_id);
+	}
+#endif
+
 	unix_release_sock(sk, 0);
 	sock->sk = NULL;
 
@@ -829,6 +846,34 @@ static int unix_autobind(struct socket *sock)
 	int err;
 	unsigned int retries = 0;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "unix_autobind() [sys_bind()]: calling ADF\n");
+	rsbac_target_id.ipc.type = I_anonunix;
+	if (   sock->file
+	    && sock->file->f_path.dentry
+	    && sock->file->f_path.dentry->d_inode
+	   )
+		rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+	else
+		rsbac_target_id.ipc.id.id_nr = 0;
+	rsbac_attribute_value.sock_type = sock->type;
+	if (!rsbac_adf_request(R_BIND,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				A_sock_type,
+				rsbac_attribute_value)) {
+		rsbac_pr_debug(aef, "unix_autobind() [sys_bind() etc.]: ADF returned NOT_GRANTED\n");
+		return -EPERM;
+	}
+#endif
+
 	err = mutex_lock_interruptible(&u->readlock);
 	if (err)
 		return err;
@@ -876,6 +921,20 @@ retry:
 	spin_unlock(&unix_table_lock);
 	err = 0;
 
+#ifdef CONFIG_RSBAC
+	rsbac_new_target_id.dummy = 0;
+	if (unlikely(rsbac_adf_set_attr(R_BIND,
+				task_pid(current),
+				T_IPC,
+				rsbac_target_id,
+				T_NONE,
+				rsbac_new_target_id,
+				A_sock_type,
+				rsbac_attribute_value)))
+		rsbac_printk(KERN_WARNING
+				"unix_autobind() [sys_bind() etc.]: rsbac_adf_set_attr() returned error\n");
+#endif
+
 out:	mutex_unlock(&u->readlock);
 	return err;
 }
@@ -966,6 +1025,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	struct path path;
 	struct dentry *dentry;
 
+#ifdef CONFIG_RSBAC
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = -EINVAL;
 	if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
 	    sunaddr->sun_family != AF_UNIX)
@@ -981,6 +1046,35 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 		goto out;
 	addr_len = err;
 
+#ifdef CONFIG_RSBAC
+	if (!sun_path[0]) {
+		rsbac_pr_debug(aef, "unix_bind() [sys_bind()]: calling ADF\n");
+		rsbac_target_id.ipc.type = I_anonunix;
+		if (   sock->file
+		    && sock->file->f_path.dentry
+		    && sock->file->f_path.dentry->d_inode
+		   )
+			rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+		else
+			rsbac_target_id.ipc.id.id_nr = 0;
+		rsbac_attribute_value.sock_type = sock->type;
+		if (!rsbac_adf_request(R_BIND,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					A_sock_type,
+					rsbac_attribute_value)) {
+			rsbac_pr_debug(aef, "unix_bind() [sys_bind()]: ADF returned NOT_GRANTED\n");
+			err = -EPERM;
+			goto out;
+		}
+	} else {
+		/* RSBAC add: set credentials so that sendto() can copy them */
+		if (sock->type == SOCK_DGRAM)
+			init_peercred(sk);
+	}
+#endif
+
 	name_err = 0;
 	dentry = NULL;
 	if (sun_path[0]) {
@@ -1045,6 +1139,21 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 		}
 
 		list = &unix_socket_table[addr->hash];
+
+#ifdef CONFIG_RSBAC
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_BIND,
+					task_pid(current),
+					T_IPC,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					A_sock_type,
+					rsbac_attribute_value)))
+			rsbac_printk(KERN_WARNING
+					"unix_bind() [sys_bind()]: rsbac_adf_set_attr() returned error\n");
+#endif
+
 	}
 
 	err = 0;
@@ -1099,6 +1208,14 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,
 	unsigned int hash;
 	int err;
 
+#ifdef CONFIG_RSBAC
+	enum rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = -EINVAL;
 	if (alen < offsetofend(struct sockaddr, sa_family))
 		goto out;
@@ -1135,6 +1252,47 @@ restart:
 		if (err)
 			goto out_unlock;
 
+#ifdef CONFIG_RSBAC
+		rsbac_pr_debug(aef, "[sys_connect() [sys_socketcall()]]: calling ADF\n");
+		/* Named socket? */
+		if(sunaddr->sun_path[0]) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(other)->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(other)->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(other)->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			rsbac_target_id.ipc.id.id_nr = unix_sk(other)->path.dentry->d_inode->i_ino;
+		}
+		if (   other->sk_peer_pid
+		    && (pid_nr(other->sk_peer_pid) > 0)
+		   ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(other->sk_peer_pid);
+		} else if (   sk->sk_peer_pid
+			   && (pid_nr(sk->sk_peer_pid) > 0)
+		          ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(sk->sk_peer_pid);
+		} else {
+			rsbac_attribute = A_sock_type;
+			rsbac_attribute_value.sock_type = sock->type;
+		}
+		if (!rsbac_adf_request(R_CONNECT,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value)) {
+			rsbac_pr_debug(aef, "[sys_connect() [sys_socketcall()]]: ADF returned NOT_GRANTED\n");
+			err = -EPERM;
+			if (rsbac_attribute == A_process)
+				put_pid(rsbac_attribute_value.process);
+			goto out_unlock;
+		}
+#endif
+
 	} else {
 		/*
 		 *	1003.1g breaking connected state with AF_UNSPEC
@@ -1160,6 +1318,26 @@ restart:
 		unix_peer(sk) = other;
 		unix_state_double_unlock(sk, other);
 	}
+
+#ifdef CONFIG_RSBAC
+	if (rsbac_target != T_NONE) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_CONNECT,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value)))
+			rsbac_printk(KERN_WARNING
+					"unix_dgram_connect() [sys_connect() [sys_socketcall()]]: rsbac_adf_set_attr() returned error\n");
+	}
+
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return 0;
 
 out_unlock:
@@ -1205,6 +1383,15 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 	int err;
 	long timeo;
 
+#ifdef CONFIG_RSBAC
+	enum rsbac_target_t rsbac_target = T_NONE;
+	enum rsbac_target_t rsbac_new_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = unix_mkname(sunaddr, addr_len, &hash);
 	if (err < 0)
 		goto out;
@@ -1310,6 +1497,57 @@ restart:
 		goto out_unlock;
 	}
 
+#ifdef CONFIG_RSBAC
+	rsbac_pr_debug(aef, "unix_stream_connect() [sys_connect()]: calling ADF\n");
+	/* Named socket? */
+	if (unix_sk(other)->path.dentry&& unix_sk(other)->path.dentry->d_inode) {
+		rsbac_target = T_UNIXSOCK;
+		rsbac_target_id.unixsock.device = unix_sk(other)->path.dentry->d_sb->s_dev;
+		rsbac_target_id.unixsock.inode  = unix_sk(other)->path.dentry->d_inode->i_ino;
+		rsbac_target_id.unixsock.dentry_p = unix_sk(other)->path.dentry;
+	} else {
+		if (other->sk_socket
+                    && other->sk_socket->file
+                    && other->sk_socket->file->f_path.dentry
+                    && other->sk_socket->file->f_path.dentry->d_inode
+		   ) {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			rsbac_target_id.ipc.id.id_nr = other->sk_socket->file->f_path.dentry->d_inode->i_ino;
+		}
+	}
+	if (rsbac_target != T_NONE) {
+		if (   other->sk_peer_pid
+		    && (pid_nr(other->sk_peer_pid) > 0)
+		   ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(other->sk_peer_pid);
+		} else if (   sk->sk_peer_pid
+			   && (pid_nr(sk->sk_peer_pid) > 0)
+		          ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(sk->sk_peer_pid);
+		} else {
+			rsbac_attribute = A_sock_type;
+			rsbac_attribute_value.sock_type = sock->type;
+		}
+		if (!rsbac_adf_request(R_CONNECT,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value)) {
+			rsbac_pr_debug(aef, "[sys_connect() [sys_socketcall()]]:"
+					" ADF returned NOT_GRANTED\n");
+			err = -EPERM;
+			unix_state_unlock(sk);
+			if (rsbac_attribute == A_process)
+				put_pid(rsbac_attribute_value.process);
+			goto out_unlock;
+		}
+	}
+#endif
+
 	/* The way is open! Fastly set all the necessary fields... */
 
 	sock_hold(sk);
@@ -1349,6 +1587,56 @@ restart:
 	spin_unlock(&other->sk_receive_queue.lock);
 	unix_state_unlock(other);
 	other->sk_data_ready(other);
+
+#ifdef CONFIG_RSBAC
+	if (rsbac_target != T_NONE) {
+		if (newu->path.dentry && newu->path.dentry->d_inode) {
+			rsbac_new_target = T_UNIXSOCK;
+			rsbac_new_target_id.unixsock.device = newu->path.dentry->d_sb->s_dev;
+			rsbac_new_target_id.unixsock.inode  = newu->path.dentry->d_inode->i_ino;
+			rsbac_new_target_id.unixsock.dentry_p = newu->path.dentry;
+		} else {
+			if (newsk->sk_socket
+	                    && newsk->sk_socket->file
+	                    && newsk->sk_socket->file->f_path.dentry
+	                    && newsk->sk_socket->file->f_path.dentry->d_inode
+			   ) {
+				rsbac_new_target = T_IPC;
+				rsbac_new_target_id.ipc.type = I_anonunix;
+				rsbac_new_target_id.ipc.id.id_nr = newsk->sk_socket->file->f_path.dentry->d_inode->i_ino;
+			}
+		}
+		if (unlikely(rsbac_adf_set_attr(R_CONNECT,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_new_target,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value)))
+			rsbac_printk(KERN_WARNING
+					"unix_stream_connect() [sys_connect() [sys_socketcall()]]: rsbac_adf_set_attr() returned error\n");
+#ifdef CONFIG_RSBAC_NET
+#ifdef CONFIG_RSBAC_DEBUG
+		if (   rsbac_debug_aef_net
+		    && sk->sk_socket
+		    && newsk->sk_socket
+		    && other->sk_socket
+		   ) {
+			rsbac_printk("unix_stream_connect() [sys_connect()]: connected from %u to %u (type %u), orig %u\n",
+			sk->sk_socket->file->f_path.dentry->d_inode->i_ino,
+			newsk->sk_socket->file->f_path.dentry->d_inode->i_ino,
+			rsbac_target,
+			other->sk_socket->file->f_path.dentry->d_inode->i_ino);
+		}
+#endif
+#endif
+	}
+
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	sock_put(other);
 	return 0;
 
@@ -1430,6 +1718,21 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
 	unix_state_lock(tsk);
 	newsock->state = SS_CONNECTED;
 	unix_sock_inherit_flags(sock, newsock);
+
+#ifdef CONFIG_RSBAC
+	/* copy dentry and mnt, if there */
+	if (unix_sk(sk)->path.dentry) {
+		if (!unix_sk(tsk)->path.dentry) {
+			unix_sk(tsk)->path.dentry = dget(unix_sk(sk)->path.dentry);
+			unix_sk(tsk)->path.mnt = mntget(unix_sk(sk)->path.mnt);
+		}
+		if (newsock->sk && !unix_sk(newsock->sk)->path.dentry) {
+			unix_sk(newsock->sk)->path.dentry = dget(unix_sk(sk)->path.dentry);
+			unix_sk(newsock->sk)->path.mnt = mntget(unix_sk(sk)->path.mnt);
+		}
+	}
+#endif
+
 	sock_graft(tsk, newsock);
 	unix_state_unlock(tsk);
 	return 0;
@@ -1607,6 +1910,14 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
 	int data_len = 0;
 	int sk_locked;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	wait_for_unix_gc();
 	err = scm_send(sock, msg, &scm, false);
 	if (err < 0)
@@ -1733,6 +2044,61 @@ restart_locked:
 			goto out_unlock;
 	}
 
+#if defined(CONFIG_RSBAC)
+	if (other->sk_socket) {
+		if (rsbac_attribute == A_process) {
+			put_pid(rsbac_attribute_value.process);
+		}
+		rsbac_pr_debug(aef, "unix_dgram_sendmsg() [sys_send(), sys_sendto(), sys_sendmsg()]: calling ADF\n");
+		if (   other->sk_socket->sk
+		    && unix_sk(other->sk_socket->sk)->path.dentry
+		    && unix_sk(other->sk_socket->sk)->path.dentry->d_sb
+		    && unix_sk(other->sk_socket->sk)->path.dentry->d_inode
+		   ) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(other->sk_socket->sk)->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(other->sk_socket->sk)->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(other->sk_socket->sk)->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			if (   other->sk_socket->file
+			    && other->sk_socket->file->f_path.dentry
+			    && other->sk_socket->file->f_path.dentry->d_inode
+			   )
+				rsbac_target_id.ipc.id.id_nr = other->sk_socket->file->f_path.dentry->d_inode->i_ino;
+			else
+				rsbac_target_id.ipc.id.id_nr = 0;
+		}
+		if (   sk->sk_peer_pid
+		    && (pid_nr(sk->sk_peer_pid) > 0)
+		   ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(sk->sk_peer_pid);
+		} else if (   other->sk_socket->sk
+		    && other->sk_socket->sk->sk_peer_pid
+		    && (pid_nr(other->sk_socket->sk->sk_peer_pid) > 0)
+		   ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(other->sk_socket->sk->sk_peer_pid);
+		} else {
+			rsbac_attribute = A_sock_type;
+			rsbac_attribute_value.sock_type = sock->type;
+		}
+		if(!rsbac_adf_request(R_SEND,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))	{
+			err = -EPERM;
+			if (rsbac_attribute == A_process)
+				put_pid(rsbac_attribute_value.process);
+			goto out_unlock;
+		}
+	}
+#endif
+
 	/* other == sk && unix_peer(other) != sk if
 	 * - unix_peer(sk) == NULL, destination address bound to sk
 	 * - unix_peer(sk) == sk by time of get but disconnected before lock
@@ -1780,6 +2146,26 @@ restart_locked:
 	other->sk_data_ready(other);
 	sock_put(other);
 	scm_destroy(&scm);
+
+#if defined(CONFIG_RSBAC)
+	if ((len > 0) && (rsbac_target != T_NONE)) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_SEND,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"unix_dgram_sendmsg() [sys_send(), sys_sendto(), sys_sendmsg()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return len;
 
 out_unlock:
@@ -1813,6 +2199,14 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
 	int max_level;
 	int data_len;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	wait_for_unix_gc();
 	err = scm_send(sock, msg, &scm, false);
 	if (err < 0)
@@ -1835,6 +2229,56 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
 	if (sk->sk_shutdown & SEND_SHUTDOWN)
 		goto pipe_err;
 
+#if defined(CONFIG_RSBAC)
+	if (other->sk_socket) {
+		rsbac_pr_debug(aef, "unix_stream_sendmsg() [sys_send(), sys_sendto(), sys_sendmsg()]: calling ADF\n");
+		if (   other->sk_socket->sk
+		    && unix_sk(other->sk_socket->sk)->path.dentry
+		    && unix_sk(other->sk_socket->sk)->path.dentry->d_sb
+		    && unix_sk(other->sk_socket->sk)->path.dentry->d_inode
+		   ) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(other->sk_socket->sk)->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(other->sk_socket->sk)->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(other->sk_socket->sk)->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			if (   other->sk_socket->file
+			    && other->sk_socket->file->f_path.dentry
+			    && other->sk_socket->file->f_path.dentry->d_inode
+			   )
+				rsbac_target_id.ipc.id.id_nr = other->sk_socket->file->f_path.dentry->d_inode->i_ino;
+			else
+				rsbac_target_id.ipc.id.id_nr = 0;
+		}
+		if (   sk->sk_peer_pid
+		    && (pid_nr(sk->sk_peer_pid) > 0)
+		   ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(sk->sk_peer_pid);
+		} else if (   other->sk_socket->sk
+		    && other->sk_socket->sk->sk_peer_pid
+		    && (pid_nr(other->sk_socket->sk->sk_peer_pid) > 0)
+		   ) {
+			rsbac_attribute = A_process;
+			rsbac_attribute_value.process = get_pid(other->sk_socket->sk->sk_peer_pid);
+		} else {
+			rsbac_attribute = A_sock_type;
+			rsbac_attribute_value.sock_type = sock->type;
+		}
+		if(!rsbac_adf_request(R_SEND,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))	{
+			err = -EPERM;
+			goto out_err;
+		}
+	}
+#endif
+
 	while (sent < len) {
 		size = len - sent;
 
@@ -1889,6 +2333,25 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
 
 	scm_destroy(&scm);
 
+#if defined(CONFIG_RSBAC)
+	if (sent && (rsbac_target != T_NONE)) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_SEND,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"unix_stream_sendmsg() [sys_send(), sys_sendto(), sys_sendmsg()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return sent;
 
 pipe_err_free:
@@ -1900,6 +2363,26 @@ pipe_err:
 	err = -EPIPE;
 out_err:
 	scm_destroy(&scm);
+
+#if defined(CONFIG_RSBAC)
+	if (sent > 0) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_SEND,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"unix_stream_sendmsg() [sys_send(), sys_sendto(), sys_sendmsg()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return sent ? : err;
 }
 
@@ -1954,10 +2437,79 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
 	int err;
 	int peeked, skip;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = -EOPNOTSUPP;
 	if (flags&MSG_OOB)
 		goto out;
 
+#if defined(CONFIG_RSBAC)
+	rsbac_pr_debug(aef, "unix_dgram_recvmsg() [sys_recv(), sys_recvfrom(), sys_recvmsg()]: calling ADF\n");
+	if (unix_peer(sk)) {
+		if (   unix_sk(unix_peer(sk))->path.dentry
+		    && unix_sk(unix_peer(sk))->path.dentry->d_sb
+		    && unix_sk(unix_peer(sk))->path.dentry->d_inode
+		   ) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(unix_peer(sk))->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(unix_peer(sk))->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(unix_peer(sk))->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			if (   unix_peer(sk)->sk_socket
+			    && unix_peer(sk)->sk_socket->file
+			    && unix_peer(sk)->sk_socket->file->f_path.dentry
+			    && unix_peer(sk)->sk_socket->file->f_path.dentry->d_inode
+			   )
+				rsbac_target_id.ipc.id.id_nr = unix_peer(sk)->sk_socket->file->f_path.dentry->d_inode->i_ino;
+		}
+	} else {
+		if (   unix_sk(sk)->path.dentry
+		    && unix_sk(sk)->path.dentry->d_inode
+		   ) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(sk)->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(sk)->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(sk)->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			if (   sock->file
+			    && sock->file->f_path.dentry
+			    && sock->file->f_path.dentry->d_inode
+			   )
+				rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+			else
+				rsbac_target_id.ipc.id.id_nr = 0;
+		}
+	}
+	if (   sk->sk_peer_pid
+	    && (pid_nr(sk->sk_peer_pid) > 0)
+	   ) {
+		rsbac_attribute = A_process;
+		rsbac_attribute_value.process = get_pid(sk->sk_peer_pid);
+	} else {
+		rsbac_attribute = A_sock_type;
+		rsbac_attribute_value.sock_type = sock->type;
+	}
+	if(!rsbac_adf_request(R_RECEIVE,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				rsbac_attribute,
+				rsbac_attribute_value))	{
+		err = -EPERM;
+		goto out;
+	}
+#endif
+
 	err = mutex_lock_interruptible(&u->readlock);
 	if (unlikely(err)) {
 		/* recvmsg() in non blocking mode is supposed to return -EAGAIN
@@ -2036,6 +2588,26 @@ out_free:
 out_unlock:
 	mutex_unlock(&u->readlock);
 out:
+
+#if defined(CONFIG_RSBAC)
+	if (err > 0) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_RECEIVE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"unix_dgram_recvmsg() [sys_recv(), sys_recvfrom(), sys_recvmsg()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return err;
 }
 
@@ -2095,6 +2667,14 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
 	long timeo;
 	int skip;
 
+#ifdef CONFIG_RSBAC
+	enum  rsbac_target_t rsbac_target = T_NONE;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_target_id_t rsbac_new_target_id;
+	enum  rsbac_attribute_t rsbac_attribute = A_none;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
 	err = -EINVAL;
 	if (sk->sk_state != TCP_ESTABLISHED)
 		goto out;
@@ -2103,6 +2683,67 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
 	if (flags&MSG_OOB)
 		goto out;
 
+#if defined(CONFIG_RSBAC)
+	rsbac_pr_debug(aef, "unix_stream_recvmsg() [sys_recv(), sys_recvfrom(), sys_recvmsg()]: calling ADF\n");
+	if (unix_peer(sk)) {
+		if (   unix_sk(unix_peer(sk))->path.dentry
+		    && unix_sk(unix_peer(sk))->path.dentry->d_sb
+		    && unix_sk(unix_peer(sk))->path.dentry->d_inode
+		   ) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(unix_peer(sk))->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(unix_peer(sk))->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(unix_peer(sk))->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			if (   unix_peer(sk)->sk_socket
+			    && unix_peer(sk)->sk_socket->file
+			    && unix_peer(sk)->sk_socket->file->f_path.dentry
+			    && unix_peer(sk)->sk_socket->file->f_path.dentry->d_inode
+			   )
+				rsbac_target_id.ipc.id.id_nr = unix_peer(sk)->sk_socket->file->f_path.dentry->d_inode->i_ino;
+		}
+	} else {
+		if (   unix_sk(sk)->path.dentry
+		    && unix_sk(sk)->path.dentry->d_inode
+		   ) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = unix_sk(sk)->path.dentry->d_sb->s_dev;
+			rsbac_target_id.unixsock.inode  = unix_sk(sk)->path.dentry->d_inode->i_ino;
+			rsbac_target_id.unixsock.dentry_p = unix_sk(sk)->path.dentry;
+		} else {
+			rsbac_target = T_IPC;
+			rsbac_target_id.ipc.type = I_anonunix;
+			if (   sock->file
+			    && sock->file->f_path.dentry
+			    && sock->file->f_path.dentry->d_inode
+			   )
+				rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+			else
+				rsbac_target_id.ipc.id.id_nr = 0;
+		}
+	}
+	if (   sk->sk_peer_pid
+	    && (pid_nr(sk->sk_peer_pid) > 0)
+	   ) {
+		rsbac_attribute = A_process;
+		rsbac_attribute_value.process = get_pid(sk->sk_peer_pid);
+	} else {
+		rsbac_attribute = A_sock_type;
+		rsbac_attribute_value.sock_type = sock->type;
+	}
+	if(!rsbac_adf_request(R_RECEIVE,
+				task_pid(current),
+				rsbac_target,
+				rsbac_target_id,
+				rsbac_attribute,
+				rsbac_attribute_value))	{
+		err = -EPERM;
+		goto out;
+	}
+#endif
+
 	target = sock_rcvlowat(sk, flags&MSG_WAITALL, size);
 	timeo = sock_rcvtimeo(sk, noblock);
 
@@ -2246,6 +2887,25 @@ again:
 	mutex_unlock(&u->readlock);
 	scm_recv(sock, msg, &scm, flags);
 out:
+#if defined(CONFIG_RSBAC)
+	if (copied > 0) {
+		rsbac_new_target_id.dummy = 0;
+		if (unlikely(rsbac_adf_set_attr(R_RECEIVE,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					T_NONE,
+					rsbac_new_target_id,
+					rsbac_attribute,
+					rsbac_attribute_value))) {
+			rsbac_printk(KERN_WARNING
+					"unix_stream_recvmsg() [sys_recv(), sys_recvfrom(), sys_recvmsg()]: rsbac_adf_set_attr() returned error\n");
+		}
+	}
+	if (rsbac_attribute == A_process)
+		put_pid(rsbac_attribute_value.process);
+#endif
+
 	return copied ? : err;
 }
 
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index b50ee5d..750cb65 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -20,6 +20,8 @@
 #include <net/wext.h>
 #include <net/net_namespace.h>
 
+#include <rsbac/hooks.h>
+
 typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *,
 			       unsigned int, struct iw_request_info *,
 			       iw_handler);
@@ -981,9 +983,37 @@ static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
 {
 	int ret = wext_permission_check(cmd);
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#ifndef CONFIG_RSBAC_NET_DEV_VIRT
+	char * rsbac_colon;
+#endif
+#endif
+
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_RSBAC_NET_DEV
+	rsbac_pr_debug(aef, " calling ADF\n");
+	strncpy(rsbac_target_id.netdev, ifr->ifr_name, RSBAC_IFNAMSIZ);
+	rsbac_target_id.netdev[RSBAC_IFNAMSIZ] = 0;
+#ifndef CONFIG_RSBAC_NET_DEV_VIRT
+	rsbac_colon = strchr(rsbac_target_id.netdev, ':');
+	if (rsbac_colon)
+		*rsbac_colon = 0;
+#endif
+	rsbac_attribute_value.dummy = 0;
+
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+				task_pid(current),
+				T_NETDEV,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+		return -EPERM;
+#endif
+
 	dev_load(net, ifr->ifr_name);
 	rtnl_lock();
 	ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
diff --git a/rsbac/Kconfig b/rsbac/Kconfig
new file mode 100644
index 0000000..6b0c356
--- /dev/null
+++ b/rsbac/Kconfig
@@ -0,0 +1,2358 @@
+#
+# RSBAC configuration
+# (c) 1999-2016 Amon Ott <ao@rsbac.org>
+#
+
+menuconfig RSBAC
+	bool "Rule Set Based Access Control (RSBAC)"
+	default y
+	---help---
+	  RSBAC adds 'real' access control to the kernel. Currently there are
+	  the following policies supported: Mandatory Access Control,
+	  Functional Control, Privacy Model, Dazuko, File Flags,
+	  Role Compatibility, Authentication Enforcement, User Management,
+	  Access Control Lists, System Resources, Linux Capabilities and Jail.
+
+	  Additionally, you can add your own policies, e.g. as a kernel module
+	  (see Module Registration (REG)).
+
+	  Since RSBAC exclusively uses the virtual file system, files on all
+	  mounted filesystems are monitored. Still, on some filesystems, no
+	  access control information is stored, it is instead kept in kernel
+	  memory. These file system types are currently PROC, NFS, CODAFS, SMBFS
+	  NCPFS, ISO9660 and (configurable below) all MSDOS types (inodes may
+	  change between boots). You can make attribute backups and restore them
+	  on each boot to keep them persistent.
+
+	  RSBAC will increase your kernel size by up to 520K with all options
+	  turned on, plus allocated memory for dynamical data structures.
+	  If you are tight on memory, it is generally a good idea to turn off
+	  those features which you do not need.
+
+	  Please read the RSBAC docs in Documentation/rsbac or
+	  http://www.rsbac.org/documentation before installing a RSBAC enabled
+	  kernel, since you can easily make your system unaccessible when
+	  changing the RSBAC configuration...
+
+if RSBAC
+
+menu "General RSBAC options"
+	depends on RSBAC=y
+
+config RSBAC_INIT_THREAD
+	bool 'Initialize RSBAC in separate kernel thread'
+	---help---
+	  Some people experienced system hangs, oopses etc. during RSBAC
+	  initialization. If you experience this, enabling this option might
+	  help.
+
+	  At least, init can be timed out and the system more or less comes up -
+	  if you are in softmode or maintenance mode, that is. The timeout value
+	  is indicated by the RSBAC_MAX_INIT_TIME configure option below.
+
+config RSBAC_MAX_INIT_TIME
+	int 'Initialization timeout in seconds'
+	default 60
+	depends on RSBAC_INIT_THREAD=y
+	---help---
+	  Maximum time in seconds the init process waits for rsbac_initd to
+	  complete the RSBAC initialization process via rsbac_do_init(). After
+	  this time, RSBAC initialization is considered as failed and
+	  rsbac_initd is killed.
+
+config RSBAC_PROC
+	bool 'RSBAC proc support'
+	depends on PROC_FS
+	default y
+	---help---
+	  If enabled, RSBAC adds one directory to the main proc dir, called
+	  rsbac-info.
+	  The files in rsbac-info give read access to RSBAC statistics, and
+	  read and write access to many RSBAC settings.
+
+	  If unsure, say Y.
+
+	  See <file:Documentation/rsbac/README-proc> for details.
+
+config RSBAC_INIT_CHECK
+	bool 'Check on init'
+	default y
+	---help---
+	  Check RSBAC attribute consistency at boot time.
+
+	  NOTE: This cannot check attributes on other than the root filesystem.
+	        You should run rsbac_check regularly, e.g. once per day from
+	        cron.
+
+config RSBAC_NO_WRITE
+	bool 'Disable RSBAC writing to disk'
+	---help---
+	  If enabled, RSBAC treats all file system types as read-only. No
+	  attributes are saved and all settings are instead kept in memory.
+	  If off, only PROC, NFS, CODAFS, SMBFS, NCPFS, ISO9660 and all MSDOS
+	  filesystems are read-only.
+
+	  If you only want to turn off automatical writing, but keep the
+	  syscall sys_rsbac_write() to write by hand, set auto write to 0
+	  instead.
+
+	  This switch is intended for testing purposes only and off by
+	  default.
+
+	  If unsure, say N.
+
+config RSBAC_MSDOS_WRITE
+	bool 'Allow attribute writing on MSDOS filesystems'
+	depends on RSBAC_NO_WRITE=n
+	---help---
+	  This setting allows attribute writing on MSDOS filesystems, like FAT,
+	  VFAT, UMSDOS. Turning it on makes these attributes persistent through
+	  reboots.
+	  Unfortunately, MSDOS filesystems do not guarantee reproducable inode
+	  numbers on reboots - so attributes might be applied to wrong files or
+	  get lost. Watch for warning messages from rsbac_check.
+
+	  As a more reliable alternative, disable this feature, and make regular
+	  attribute backups, which you can restore each time after mounting
+	  the disk.
+
+	  If unsure, say N.
+
+config RSBAC_AUTO_WRITE
+	int 'RSBAC auto write to disk interval in seconds'
+	default 5
+	depends on RSBAC_NO_WRITE=n
+	---help---
+	  If not 0, a kernel daemon saves all changed RSBAC attributes to disk
+	  every n seconds. You can also initiate each saving through the
+	  sys_rsbac_write() syscall. This interval can alternatively be changed
+	  via the proc interface.
+
+config RSBAC_RCU_RATE
+	int 'RSBAC attribute change burst per second'
+	default 1000
+	---help---
+	  Normally, RSBAC removes list items in the background while the
+	  process continues without delay. Keeping the items longer needs
+	  extra memory, so a rate limit ensures that memory does not get
+	  exhausted.
+
+	  When the limit has been reached, deleting items is still
+	  possible, but the process gets delayed until all possible
+	  readers of the deleted item have finished reading and the item
+	  is deleted immediately. This slows down attribute changes
+	  somewhat, but should only be noticable on mass changes like at
+	  a restore.
+
+	  The default value of 1000 should be fine for normal system use
+	  even with FD cache. Valid values are 0 to 1000, 0 means always
+	  wait for readers.
+	  The value can later be changed at boot time with
+	  rsbac_list_rcu_rate=n kernel parameter and at runtime through
+	  /proc/rsbac-info/debug.
+
+config RSBAC_LIST_MAX_HASH_BITS
+	int 'Maximum number of list hash bits'
+	default 9
+	---help---
+	  Define the maximum number of bits for internal hashes per generic
+	  list. The number of lists is 2^number.
+	  Bigger values may need more memory, but allow to distribute many
+          list items over more and thus smaller lists behind the hashes.
+	  It is safe to change this value at any time, but it may not
+	  go below 3 or above 18. The system will not use more hashes per
+	  list than necessary, see next item for more info. Default is 9.
+
+config RSBAC_LIST_AUTO_REHASH_TRIGGER
+	int 'Rehash trigger number of list items per hash'
+	default 20
+	---help---
+	  If the average number of items per hashed list is bigger than
+	  this value and the list flag RSBAC_LIST_AUTO_HASH_RESIZE is set
+	  for the list, rehash it with higher number of hash bits up to
+	  CONFIG_RSBAC_LIST_MAX_HASH_BITS.
+
+config RSBAC_LIST_CHECK_INTERVAL
+	int 'Interval of automatic list check and cleanup'
+	default 1800
+	depends on CONFIG_RSBAC_AUTO_WRITE!=0
+	---help---
+	  Check all lists and remove items over ttl at this interval.
+	  Uses rsbacd and thus uses CONFIG_RSBAC_AUTO_WRITE granularity.
+
+	  Default is 1800, one half hour.
+
+config RSBAC_LIST_STATS
+	bool 'List access statistics'
+	default n
+	---help---
+	  Count read and write accesses to each list for optimization.
+	  The values are shown in /proc/rsbac-info/gen_list_counts.
+
+config RSBAC_LIST_TRANS
+	bool 'Support transactions'
+	default y
+	---help---
+	  This option enables support for RSBAC configuration transactions.
+	  RSBAC transactions are a set of temporary changes within a list that
+	  are either commited or forgotten.
+
+	  Any user can start a transaction with the rsbac_list_ta() syscall
+	  (e.g. via the rsbac_list_ta admin tool), and use the returned
+	  transaction number for further administration calls which collect a
+	  set of allowed changes.
+
+	  When finished, a simple commit through rsbac_list_ta applies all these
+	  changes atomically to the system, while the forget command or a
+	  transaction timeout (see next option) remove the complete set of
+	  proposes changes.
+
+	  The number of transactions in parallel is not limited, but each list,
+	  which has been changed by one transaction, is locked against changes
+	  by all other transactions. Such change attempts return the error
+	  -RSBAC_EBUSY, while using invalid transaction numbers returns the
+	  error -RSBAC_EINVALIDTRANSACTION. This means that when using
+	  transactions, both error codes should be checked for each call. When
+	  a list is BUSY, it is the user's choice to retry later, forget all
+	  changes or leave it as it is.
+
+	  Changes with transaction number 0 (no transaction) and automatic
+	  changes by the system always affect both the real lists and all
+	  transaction lists.
+
+config RSBAC_LIST_TRANS_MAX_TTL
+	int 'Maximum transaction time in seconds'
+	default 3600
+	depends on RSBAC_LIST_TRANS
+	---help---
+	  When starting a transaction, the ttl parameter sets its maximum
+	  lifetime, after which it will be automatically removed, if
+	  it has not been renewed in time.
+	  This option sets the maximum allowed lifetime for any transaction in
+	  seconds. The default value is 3600 (one hour).
+
+config RSBAC_LIST_TRANS_RANDOM_TA
+	bool 'Randomize transaction numbers'
+	default y
+	depends on RSBAC_LIST_TRANS
+	---help---
+	  Usually, transaction numbers start with one and increase with every
+	  new transaction. With this option, they will be randomized to make
+	  it a bit more difficult to tamper with other admins' transactions.
+
+	  However, this is no real protection and makes transactions less human
+	  friendly because of large numbers - use the transaction key or the
+	  user limit to get more security for transaction handling.
+
+config RSBAC_FD_CACHE
+	bool 'Cache FD attribute values'
+	default n
+	---help---
+	  This option allows to cache inherited attribute values for some
+	  modules. It speeds up attribute lookup, but increases memory
+	  usage significantly.
+
+config RSBAC_FD_CACHE_TTL
+	int 'Time to live for FD cache items'
+	default 3600
+	depends on RSBAC_FD_CACHE
+	---help---
+	  After the time given here in seconds, FD cache items will be
+	  removed at the next list cleanup. You can change the value at
+	  boottime with kernel parameter rsbac_fd_cache_ttl= and at
+	  runtime through /proc/rsbac-info/debug interface.
+	  Please also adjust CONFIG_RSBAC_LIST_CHECK_INTERVAL
+	  accordingly to get items over ttl expunged timely.
+
+	  Default is 3600, one hour.
+
+config RSBAC_FD_CACHE_MAX_ITEMS
+	int 'Maximum number of FD cache items per hash'
+	default 100
+	depends on RSBAC_FD_CACHE
+	---help---
+	  Specify the maximum number of cache FD items allowed per
+	  hashed list. Multiply by max number of hashes per list to get
+	  total maximum number of cache entries.
+
+	  Default is 100.
+
+config RSBAC_DEBUG
+	bool 'RSBAC debugging support'
+	default y
+	---help---
+	  This option enables many debugging switches to examine RSBAC internals
+	  as well as request sanity checks.
+	  Most of the debugging switches can be set with rsbac_debug_* kernel
+	  parameters or via proc interface at /proc/rsbac-info/debug.
+	  See <file:Documentation/rsbac/README-proc> for details.
+
+	  This option is recommended to be on, but you may as well turn it off,
+	  if performance really matters and your RSBAC system runs without
+	  problems.
+
+	  If unsure, say Y.
+
+config RSBAC_DEV_USER_BACKUP
+	bool 'Provide DEV and USER backup files'
+	depends on RSBAC_PROC=y
+	---help---
+	  If enabled, you will find images of the USER and DEV target general
+	  attribute list files in /proc/rsbac-info/backup. Since attribute
+	  backup should be done with tools, this is usually not needed and
+	  thus off by default.
+
+	  If unsure, say N.
+
+config RSBAC_SECOFF_UID
+	int 'RSBAC default security officer user ID'
+	default 400
+	---help---
+	  The number n given here specifies which user IDs should be used for
+	  the Security Officer/Role Admin/Supervisor in the default
+	  configuration at first boot.
+
+	  WARNING: This value should only be changed if you have a severe
+	           conflict with the default value of 400. After the
+		   first boot, the defaults are set and saved, and changes to
+		   this option will not have any effect.
+
+config RSBAC_INIT_DELAY
+	bool 'Delayed init for initial ramdisk'
+	---help---
+	  This option allows to delay RSBAC initialization until the first mount
+	  of a real disk partition (major number > 1). It is intended to be used
+	  with initial ramdisks, which mount the final root partition during
+	  boot.
+
+	  You can trigger initialization at a specific partition mount with the
+	  kernel parameter rsbac_delayed_root=major:minor. If the given
+	  partition is not mounted and thus RSBAC not initialized, you can also
+	  call the rsbac_init() system call at any time, e.g. with the
+	  rsbac_init utility.
+
+	  To disable delayed init, you have to use the kernel parameter
+	  rsbac_no_delay_init. This will force the standard initialization after
+	  the first root mount. If this is your initrd, the RSBAC setup in there
+	  will be used instead of the configuration on your real root device.
+
+	  WARNING: The delayed init option requires the RSBAC init code to be
+	           kept in memory all the time, which increases your kernel
+	           memory usage by a few 10s of KB. It should only be used in
+	           combination with an initial ramdisk.
+endmenu
+
+menuconfig RSBAC_UM
+	depends on RSBAC=y
+	bool 'User Management'
+	---help---
+	  Enable RSBAC User Management, a fully passwd/shadow compatible, but
+	  kernel based Linux user and group database. All changes are access
+	  controlled with USER and GROUP targets.
+
+	  You will need the PAM and NSS modules from the RSBAC admin tools
+	  contrib section to make transparent use of this feature.
+
+	  If the SHA1 algorithm is available through the crypto API, passwords
+	  can also optionally be encrypted (next option).
+
+if RSBAC_UM
+config RSBAC_UM_DIGEST
+	bool 'Use Crypto API Digest SHA1'
+	depends on RSBAC_UM=y
+	select CRYPTO
+	select CRYPTO_SHA1
+	default y
+	---help---
+	   If enabled, all passwords are hashed with SHA1 digests. To make the
+	   resulting hash values unique, the password functions add a 32 Bit
+	   salt value to the password string before hashing.
+
+config RSBAC_UM_USER_MIN
+	int 'Minimum auto user ID'
+	depends on RSBAC_UM=y
+	default 2000
+	---help---
+	  When users get added without giving a desired ID, the system picks the
+	  lowest available number starting from the set value.
+
+config RSBAC_UM_GROUP_MIN
+	int 'Minimum auto group ID'
+	depends on RSBAC_UM=y
+	default 2000
+	---help---
+	  When groups get added without giving a desired ID, the system picks
+	  the lowest available number starting from the set value.
+
+config RSBAC_UM_EXCL
+	bool 'Exclusive user management'
+	depends on RSBAC_UM=y
+	---help---
+	  With this option, RSBAC makes sure that only user and group IDs it
+	  knows about can be used within the system. The User Management
+	  component will only make consistency checks, but the AUTH module will
+	  enforce the exclusive use.
+
+config RSBAC_UM_MIN_PASS_LEN
+	int 'Minimum password length'
+	default 6
+	depends on RSBAC_UM=y
+	---help---
+	  Set this to the minimum length a password set by the user must have.
+	  The default minimum length is 6, but using at least 8 is recommended
+	  for production systems.
+
+	  Passwords set by admins with MODIFY_PERMISSIONS_DATA right to the user
+	  will not be restricted!
+
+config RSBAC_UM_NON_ALPHA
+	bool 'Require non-alphabetic character in password'
+	default y
+	depends on RSBAC_UM=y
+	---help---
+	  This option requires that a password set by the user must have at
+	  least one non-alphabetic character.
+
+	  Passwords set by admins with MODIFY_PERMISSIONS_DATA right on the
+	  user will not be restricted!
+
+config RSBAC_UM_PWHISTORY
+	bool 'Remember password history'
+	default y
+	depends on RSBAC_UM=y
+	---help---
+	  This option requires that the password set by the user must not be
+	  the same as the RSBAC_UM_HISTORY_SIZE previous ones.
+
+	  Passwords set by admins with MODIFY_PERMISSIONS_DATA right on the
+	  user will not be restricted!
+
+config RSBAC_UM_PWHISTORY_MAX
+	int 'Number of successive passwords to remember'
+	default 8
+	depends on RSBAC_UM_PWHISTORY=y
+	---help---
+	  This is the number of passwords RSBAC User Management will
+	  remember and check against when changing a password.
+
+config RSBAC_UM_ONETIME
+	bool 'Support one-time passwords'
+	default n
+	depends on RSBAC_UM=y
+	---help---
+	  With this option you can add additional passwords to every user
+	  account, which can only be used once.
+
+config RSBAC_UM_ONETIME_MAX
+	int 'Max number of one-time passwords per account'
+	default 100
+	depends on RSBAC_UM_ONETIME=y
+	---help---
+	  Set the number of one-time passwords, which can be set at
+	  each account.
+
+config RSBAC_UM_VIRTUAL
+	bool 'Support virtual users'
+	default n
+	depends on RSBAC_UM=y
+	---help---
+	  If enabled, RSBAC User Management supports virtual users,
+	  which are organized in sets with 32 Bit ID numbers. ID 0 is
+          the main set.
+
+config RSBAC_UM_VIRTUAL_ISOLATE
+	bool 'Isolate virtual user sets'
+	default y
+	depends on RSBAC_UM_VIRTUAL=y
+	---help---
+	  Select this option to ensure that users in virtual sets > 0
+	  never see users and groups in other virtual sets.
+
+config RSBAC_UM_NAME_CACHE
+	bool 'Cache name lookups to IDs'
+	default n
+	depends on RSBAC_UM=y
+	---help---
+	  If enabled, RSBAC User Management will cache lookups of names
+	  to user or group IDs, which are slow.
+
+config RSBAC_UM_NAME_CACHE_TTL
+	int 'TTL of name lookup cache items'
+	default 3600
+	depends on RSBAC_UM_NAME_CACHE=y
+	---help---
+	  Time to live of UM name lookup cache items in seconds.
+	  Default is 3600.
+endif
+
+if NET
+menu 'RSBAC networking options'
+	depends on RSBAC
+
+config RSBAC_NET
+	bool 'RSBAC network support'
+	depends on NET
+	default y
+	---help---
+	  The net support switch adds generic network device, network template
+	  and network object attribute support.
+
+	  Also, general settings of IPv4 (INET) networks are controlled through
+	  the SCD targets 'network' and 'firewall'.
+
+	  To get network device or object access control, you have to enable
+	  the conditional switches below, as well as the individual model
+	  switches for network access control.
+
+config RSBAC_NET_DEV
+	bool 'Net device control'
+	default y
+	depends on RSBAC_NET
+	---help---
+	  With this option turned on, reading and modifying network device
+	  settings, like binding addresses to devices etc., are controlled as
+	  NETDEV targets. NETDEV objects are identified by their device name.
+
+config RSBAC_NET_DEV_VIRT
+	bool 'Treat virtual devices as individuals'
+	depends on RSBAC_NET_DEV
+	---help---
+	  Turn this on, if you want to provide access control over virtual
+	  devices independently from their base device. Due to the possible
+	  number of virtual devices, be careful with this option.
+
+config RSBAC_IND_NETDEV_LOG
+	bool 'Individual network device logging'
+	default y
+	depends on RSBAC_NET_DEV
+	---help---
+	  Enable individual log levels for every request type for network
+	  devices. Log levels are none, denied requests, full, request based.
+	  Default value is request based for all request types.
+
+	  If this option is off, only general log levels for requests are used
+	  (same as individual logging for all objects set to request based).
+
+config RSBAC_NET_OBJ
+	bool 'Net object control (sockets)'
+	default y
+	depends on RSBAC_NET
+	depends on INET
+	---help---
+	  This option enables access control for all socket based
+	  communication, except the UNIX address family (controlled by extra
+	  option).
+
+	  Access control is based on network object (NETOBJ) targets. Default
+	  values for NETOBJ attributes are derived from the network template
+	  (NETTEMP object), whose description matches this particular network
+	  object.
+
+	  Matching is performed from lowest to highest template number. If no
+	  template matches, general NETOBJ default values will be used.
+	  NOTE: The behaviour in this case is model dependent!
+
+	  Socket system calls are matched to special request types with
+	  matching names.
+
+	  NETTEMP objects themselves are protected as NETTEMP targets with
+	  repective requests.
+
+config RSBAC_NET_OBJ_RW
+	bool 'Also intercept network object read and write'
+	depends on RSBAC_NET_OBJ
+	---help---
+	  If on, READ and WRITE requests on sockets are also checked.
+
+config RSBAC_IND_NETOBJ_LOG
+	bool 'Individual network object logging'
+	default y
+	depends on RSBAC_NET_OBJ
+	---help---
+	  Enable individual log levels for every request type for network
+	  objects.
+	  Log levels are none, denied requests, full, request based.
+	  Default value is request based for all request types.
+
+	  For easier setup, the log levels are set on the network templates,
+	  not the individual network objects.
+
+	  If this option is off, only general log levels for requests are used
+	  (same as individual logging for all objects set to request based).
+endmenu
+endif
+
+menu 'Decision modules (policy) options'
+	depends on RSBAC
+
+config RSBAC_REG
+	bool 'Support for Registration of decision modules (REG)'
+	default y
+	---help---
+	  If enabled, RSBAC supports runtime registering and unregistering of
+	  additional decision module functions, e.g. from kernel modules.
+
+	  Possible functions are for decision, notification and file contents
+	  overwrite decisions and for write-to-disk notifications.
+
+	  Additionally, syscall functions can be registered to the REG syscall
+	  dispatcher.
+
+	  See <file:Documentation/rsbac/README-reg>,
+	  and the module examples in <file:Documentation/rsbac/reg_sample>
+	  for details.
+
+config RSBAC_REG_SAMPLES
+	bool 'Build REG sample modules'
+	depends on RSBAC_REG && USB
+	---help---
+	  Build the REG sample kernel modules. These modules show how to use
+	  the RSBAC infrastructure, but do not perform any access control.
+
+	  The modules will be named reg_sample1, reg_sample2 and reg_sample3.
+
+menuconfig RSBAC_AUTH
+	bool 'AUTH policy support'
+	default y
+	--help---
+	  This module can be seen as a support module for all others. It
+	  restricts CHANGE_OWNER on process targets (setuid) for a process: the
+	  request is only granted, if the process has either the
+	  auth_may_setuid flag set or the target user ID is in its capability
+	  set.
+	  The auth_may_setuid flag and the capability set are inherited on
+	  execute from the program file.
+
+	  Those file capabilities can be set, if all modules grant a
+	  MODIFY_ATTRIBUTE request for A_auth_add_f_cap or A_auth_remove_f_cap.
+	  Process capabilities can only be added by other processes that have
+	  the auth_may_set_cap flag set, which is also inherited from the
+	  executed file.
+
+	  This way an enforcement of daemon based authentification is possible,
+	  as well as a restriction of system daemons to a set of user IDs.
+
+	  WARNING: If enabled without a login program having auth_may_setuid or
+	           a capability set and without a capability setting daemon,
+		   you will not be able to login to your system!
+	           Use kernel parameter rsbac_auth_enable_login in emergencies
+		   or at the first boot to set auth_may_setuid for /bin/login.
+
+	  Also see AUTH model description in
+	  <http://www.rsbac.org/documentation> for details.
+
+	  If unsure, say Y.
+
+if RSBAC_AUTH
+config RSBAC_AUTH_AUTH_PROT
+	bool 'AUTH module and attribute protection'
+	default y
+	---help---
+	  Only, if this option is on, the AUTH module cares for its own
+	  protection, otherwise it fully depends on other modules
+	  (CONFIG_RSBAC_XX_AUTH_PROT).
+	  This is meant for more sophisticated access control than a simple
+	  system_role setting to security_officer.
+
+	  As a special effect, capability sets are cleared on every write
+	  access to reduce system access after tampering.
+
+	  See AUTH model description for details.
+
+config RSBAC_AUTH_OTHER_PROT
+	bool 'Protect switching of other modules'
+	depends on RSBAC_SWITCH
+	---help---
+         This option makes AUTH care for the switching of other modules.
+         Useful if you want to prevent switching a module back on,
+         because it cannot protect itself in this case.
+
+config RSBAC_AUTH_UM_PROT
+	bool 'AUTH protection for User Management'
+	depends on RSBAC_UM
+	default y
+	---help---
+	  This option makes AUTH care for User Management settings, e.g.
+	  creation, change or deletion of users or groups.
+
+	  See User Management description for details.
+
+config RSBAC_AUTH_DAC_OWNER
+	bool 'AUTH support for effective and fs owner control'
+	---help---
+	  If enabled, AUTH also controls the requests CHANGE_DAC_EFF_OWNER
+	  (change process effective owner) and CHANGE_DAC_FS_OWNER (change
+	  process filesystem owner) on process targets. Changes to these Linux
+	  DAC (Discrete Access Control) model owner settings do not affect
+	  RSBAC, so this option is off by default.
+
+	  This option also requires the 'Control DAC process owner (seteuid,
+	  setfsuid)' option from the 'Other options', which enables the
+	  requests mentioned above.
+
+config RSBAC_AUTH_ALLOW_SAME
+	bool 'Always allow setting to same id'
+	---help---
+	  Normally, AUTH restricts all setuid and setgid calls, including those
+	  to the same uid. Enabling this option allows these calls to be
+	  unrestricted by the AUTH module if the same id is given.
+
+config RSBAC_AUTH_GROUP
+	bool 'AUTH support for Linux group control'
+	---help---
+	  If enabled, AUTH also controls the request CHANGE_GROUP
+	  (change process group) on process targets. Changes to these Linux
+	  DAC (Discrete Access Control) model group settings do not affect
+	  RSBAC, so this option is off by default.
+
+config RSBAC_AUTH_DAC_GROUP
+	bool 'AUTH support for effective and fs group control'
+	depends on RSBAC_AUTH_GROUP
+	---help---
+	  If enabled, AUTH also controls the requests CHANGE_DAC_EFF_GROUP
+	  (change process effective group) and CHANGE_DAC_FS_GROUP (change
+	  process filesystem group) on process targets. Changes to these Linux
+	  DAC (Discrete Access Control) model owner settings do not affect
+	  RSBAC, so this option is off by default.
+
+	  This option also requires the 'Control DAC process group (setegid,
+	  setfsgid)' option from the 'Other options', which enables the
+	  requests mentioned above.
+
+config RSBAC_AUTH_LEARN
+	bool 'AUTH learning mode support'
+	---help---
+	  If set, you can enable AUTH learning mode with the rsbac_auth_learn
+	  kernel parameter. In learning mode, the AUTH module will automatically
+	  add all missing auth capabilities.
+
+	  WARNING: This option is useful, but dangerous, so it should be off on
+	           production systems.
+config RSBAC_AUTH_LEARN_TA
+	int 'Learning mode transaction number'
+	default 0
+	depends on RSBAC_AUTH_LEARN && RSBAC_LIST_TRANS
+	---help---
+	  Put learned items into transaction with this number. The
+	  transaction is created, if it does not exist. The default
+	  value 0 means do not use transactions, all extra rights
+	  get added immediately.
+
+	  Note: As the additional rights only appear in the transaction,
+	        the same rights may seem to be added repeatedly, until
+	        the transaction is committed.
+	  Note: All transactions have a maximum lifetime, after which
+	        all data is lost, unless you commit or refresh in time,
+		e.g. with the rsbac_list_ta command line tool.
+	        Increase RSBAC_LIST_TRANS_MAX_TTL as desired.
+
+endif
+
+menuconfig RSBAC_RC
+	bool 'RC policy support'
+	default y
+	---help---
+	  The Role Compatibility model is a powerful and flexible role based
+	  model. It supports an unlimited number of roles and types. Types are
+	  grouped per target type. Each role definition has compatibility
+	  vectors for all types and other roles.
+
+	  Additionally, there are default create/chown/execute types and
+	  several special values for inheritance options.
+	  Roles can also be forced by executable file attributes, similar to
+	  the setuid/setgid mechanism in Unix file systems.
+
+	  See <http://www.rsbac.org/documentation> for details.
+
+	  If unsure, say Y.
+
+if RSBAC_RC
+config RSBAC_RC_AUTH_PROT
+	bool 'RC protection for AUTH module'
+    depends on RSBAC_AUTH
+	default y
+	---help---
+	  This option makes RC care for AUTH module settings, e.g. attributes
+	  auth_may_setuid, auth_may_set_cap and the kernel-only pseudo
+	  attributes auth_add_f_cap, auth_remove_f_cap, auth_get_caplist.
+
+	  These settings are protected by SCD type compatibility with type
+	  auth_administration, which is set for default role 1 (Role Admin).
+
+	  See AUTH model description for details.
+
+config RSBAC_RC_UM_PROT
+	bool 'RC protection for User Management'
+	depends on RSBAC_UM
+	default y
+	---help---
+	  This option makes RC care for User Management settings, e.g. creation,
+	  change or deletion of users or groups.
+
+	  See User Management description for details.
+
+config RSBAC_RC_GEN_PROT
+	bool 'RC protection for GENeral attributes'
+	default y
+	---help---
+	  If on, RC protects general attributes (GEN module) like its own, e.g.,
+	  in default setup only Role Admins may change them.
+
+config RSBAC_RC_UDF_PROT
+	bool 'RC protection for UDF module'
+	depends on RSBAC_UDF
+	default n
+	---help---
+	  This option makes RC care for UDF module settings, e.g. attributes
+	  udf_role, udf_checker, udf_checked, udf_do_check, and
+	  checker setting through proc interface.
+
+	  These settings are protected by SCD type compatibility with type
+	  udf_administration.
+
+	  See UDF model description for details.
+
+config RSBAC_RC_BACKUP
+	bool 'Provide RC backup files'
+	depends on RSBAC_PROC
+	---help---
+	  If enabled, RC provides its binary ACI data files in
+	  /proc/rsbac-info/backup.
+
+	  Because of better backup options with admin tools, this is off by
+	  default.
+
+	  If unsure, say N.
+
+config RSBAC_RC_NET_DEV_PROT
+	bool 'RC network device protection'
+	default y
+	depends on RSBAC_NET_DEV
+	---help---
+	  If on, protect network devices based on RC NETDEV type
+	  compatibilities.
+
+config RSBAC_RC_NET_OBJ_PROT
+	bool 'RC network object protection'
+	default y
+	depends on RSBAC_NET_OBJ
+	---help---
+	  Turn this on to have real RC access control on network objects based
+	  on RC type compatibilities.
+
+	  The NETOBJ default type values are derived from those of the matching
+	  network template.
+
+	  Templates themselves are protected through their own template type
+	  in attribute rc_type_nt and the nettemp type compatibility settings.
+
+config RSBAC_RC_NET_OBJ_UNIX_PROCESS
+	bool 'RC check access to UNIX partner process'
+	default n
+	---help---
+	  This option enables additional checks for UNIX sockets: If a peer
+	  process is known (via peer credential), the requesting process also
+	  needs the same right as in the request to the RC type of the
+	  other process.
+
+	  Affected request types are CONNECT, ACCEPT, SEND and RECEIVE. If
+	  READ and WRITE checking of network sockets is enabled, these request
+	  types are checked as RECEIVE and SEND to avoid possible confusion
+	  about read and write accesses to processes.
+
+config RSBAC_RC_LEARN
+	bool 'Enable learning mode for missing role rights to types'
+	depends on RSBAC_DEBUG
+	---help---
+	  This option allows to enable a learning mode per global switch.
+	  In learning mode, missing role rights to types will be added
+	  automatically. However, it will never add new roles or types
+	  even when this would be a much better solution.
+	  Enable temporarily for all roles with the rsbac_rc_learn
+	  kernel parameter or temporarily at runtime via proc interface.
+
+	  Please check <http://www.rsbac.org/documentation>
+	  for more info about how the RC model works.
+
+config RSBAC_RC_LEARN_TA
+	int 'Learning mode transaction number'
+	default 0
+	depends on RSBAC_RC_LEARN && RSBAC_LIST_TRANS
+	---help---
+	  Put learned items into transaction with this number. The
+	  transaction is created, if it does not exist. The default
+	  value 0 means do not use transactions, all extra rights
+	  get added immediately.
+
+	  Note: As the additional rights only appear in the transaction,
+	        the same rights may seem to be added repeatedly, until
+	        the transaction is committed.
+	  Note: All transactions have a maximum lifetime, after which
+	        all data is lost, unless you commit or refresh in time,
+		e.g. with the rsbac_list_ta command line tool.
+	        Increase RSBAC_LIST_TRANS_MAX_TTL as desired.
+
+config RSBAC_RC_KERNEL_PROCESS_TYPE
+	int 'RC kernel process type'
+	default 999999
+	---help---
+	  This is the type being assigned to all kernel processes, despite the
+	  initiating process owner role's def_process_create_type.
+
+	  The default value is 999999. It should only be changed, if you have
+	  role number conflicts with your existing configuration.
+endif
+
+menuconfig RSBAC_ACL
+	bool 'ACL policy support'
+	default y
+	---help---
+	  This turns on the Access Control List module. ACLs are kept on all
+	  targets but those of type USER. For the IPC and PROCESS targets
+	  there is only one default ACL each.
+
+	  Each ACL entry contains subject type (user, rc_role, acl_group),
+	  subject id and the rights this subject has. Also, rights are inherited
+	  from parents and from a target specific default ACL.
+
+	  Most settings have a time-to-live (TTL) option, which automatically
+	  removes them after a certain amount of time.
+
+	  See <http://www.rsbac.org/documentation> for details.
+
+if RSBAC_ACL
+config RSBAC_ACL_SUPER_FILTER
+	bool 'Allow masking out of SUPERVISOR right'
+	---help---
+	  Normally, inheritance masks can never filter out the SUPERVISOR right
+	  (which contains all other rights) - it is always inherited.
+
+	  If this switch is on, SUPERVISOR *can* be filtered out. This allows
+	  separation of duties and privacy, but is also dangerous, because
+	  administration can easily become impossible. In this case, you have to
+	  reboot into a maintenance kernel to regain access.
+
+	  For safety reasons, you must have a USER ACL entry at the target
+	  containing the SUPERVISOR right to set a new mask without SUPERVISOR.
+
+config RSBAC_ACL_AUTH_PROT
+	bool 'ACL protection for AUTH module'
+	depends on RSBAC_AUTH
+	default y
+	---help---
+	  This option makes ACL care for AUTH module settings, e.g. attributes
+	  auth_may_setuid, auth_may_set_cap and the kernel-only pseudo
+	  attributes auth_add_f_cap, auth_remove_f_cap, auth_get_caplist. Those
+	  settings are protected by SCD 'auth_administration' ACL.
+
+	  See AUTH model description for AUTH details.
+
+config RSBAC_ACL_UM_PROT
+	bool 'ACL protection for User Management'
+	depends on RSBAC_UM
+	default y
+	---help---
+	  This option makes ACL care for User Management settings, e.g.
+	  creation, change or deletion of users or groups.
+
+	  See User Management description for details.
+
+config RSBAC_ACL_GEN_PROT
+	bool 'ACL protection for GENeral attributes'
+	default y
+	---help---
+	  If on, ACL protects general attributes (GEN module) through
+	  the MODIFY_ATTRIBUTE right.
+	  In default setup, only user 400 may change them.
+
+config RSBAC_ACL_UDF_PROT
+	bool 'ACL protection for UDF module'
+	depends on RSBAC_UDF
+	default n
+	---help---
+	  This option makes ACL care for UDF module settings, e.g. attributes
+	  udf_role, udf_checker, udf_checked, udf_do_check, and
+	  checker setting through proc interface.
+	  These settings are protected by SCD 'udf_administration' ACL.
+
+	  See UDF model description for UDF details.
+
+config RSBAC_ACL_BACKUP
+	bool 'Provide ACL backup files'
+	depends on RSBAC_PROC
+	---help---
+	  If on, ACL provides its binary group and group membership data files
+	  in /proc/rsbac-info/backup.
+
+config RSBAC_ACL_LEARN
+	bool 'ACL learning mode support'
+	---help---
+	  If enabled, you can enable ACL learning mode with rsbac_acl_learn or
+	  rsbac_acl_learn_fd kernel parameter. In learning mode, ACL module will
+	  automatically add all missing acl entries for filesystem objects.
+
+	  WARNING: This option is useful, but dangerous, so it should be off on
+	           production systems.
+
+config RSBAC_ACL_LEARN_TA
+	int 'Learning mode transaction number'
+	default 0
+	depends on RSBAC_ACL_LEARN && RSBAC_LIST_TRANS
+	---help---
+	  Put learned items into transaction with this number. The
+	  transaction is created, if it does not exist. The default
+	  value 0 means do not use transactions, all extra rights
+	  get added immediately.
+
+	  Note: As the additional rights only appear in the transaction,
+	        the same rights may seem to be added repeatedly, until
+	        the transaction is committed.
+	  Note: All transactions have a maximum lifetime, after which
+	        all data is lost, unless you commit or refresh in time,
+		e.g. with the rsbac_list_ta command line tool.
+	        Increase RSBAC_LIST_TRANS_MAX_TTL as desired.
+
+config RSBAC_ACL_NET_DEV_PROT
+	bool 'ACL network device protection'
+	default y
+	depends on RSBAC_NET_DEV
+	---help---
+	  If on, protect network devices based on individual and default ACLs.
+
+config RSBAC_ACL_NET_OBJ_PROT
+	bool 'ACL network object protection'
+	default y
+	depends on RSBAC_NET_OBJ
+	---help---
+	  Turn this on to have real ACL access control on network objects based
+	  on inherited ACLs.
+
+	  When determining a subject's right to a network object (NETOBJ), the
+	  following inheritance scheme is used:
+	    - If there is an ACL entry at the NETOBJ itself, use it, else
+	    - If there is an ACL entry at the matching template, use that, but
+	      filter through individual mask, else
+	    - If there is an ACL entry in the NETOBJ default ACL, use that, but
+	      filter through individual mask and matching template's mask.
+
+	  Certainly, user, role and group rights are accumulated as usual.
+
+	  Templates themselves are protected through their own individual and
+	  default ACLs, which are configured using the NETTEMP_NT target.
+endif
+
+menuconfig RSBAC_MAC
+	bool 'MAC policy support'
+	---help---
+	  Mandatory Access Control follows the Bell-LaPadula security model,
+	  in which all users and resources are classified in levels of
+	  confidentiality. Additionally, each subject and object has a set out
+	  of 64 categories.
+
+	  To read from a resource, a user's level must be at least as high as
+	  that of the resource, and the user's category set must be a superset
+	  of the category set of the resource.
+	  To write to a resource, it must be at least as confidential as the
+	  user, and its category set must be a superset of the user's.
+
+	  See <http://www.rsbac.org/documentation> for details.
+
+if RSBAC_MAC
+config RSBAC_MAC_DEF_INHERIT
+	bool 'MAC inherit as default'
+	default y
+	---help---
+	  If enabled, the inheritable attributes security_level and
+	  mac_categories for files, fifos and directories get the default value
+	  'inherit' instead of the old style real value. This reduces the amount
+	  of attributes to be set significantly, because files, fifos and dirs
+	  inherit their parent dir's attribute values automatically. Inheritance
+	  ends at root dir /.
+
+	  This setting should be kept constant between different RSBAC kernels
+	  in use to avoid confusion for administrators/security officers,
+	  rsbac_check() and backup.
+
+	  Please note that inheritance is not conforming to the Bell-LaPadula
+	  model, where all objects must be individually labeled.
+
+config RSBAC_MAC_SMART_INHERIT
+	bool 'Smart inherit'
+	default y
+	depends on RSBAC_MAC_DEF_INHERIT
+	---help---
+	  If enabled, the MAC model checks whether the values of attributes
+	  security_level and mac_categories for new objects would already be in
+	  effect via inheritance. Only if the inherited value differs, the new
+	  values are set explicitely. Otherwise the default value 'inherit' is
+	  automatically applied.
+
+	  This option largely reduces the amount of new attribute objects needed
+	  for whole created directory trees with same values. It thus saves
+	  memory and CPU cycles.
+
+	  However, inheritance is not conforming to the Bell-LaPadula model,
+	  where all objects must be individually labeled - here we are even
+	  denying explicit labeling of new objects. Use with care.
+
+config RSBAC_MAC_AUTH_PROT
+    depends on RSBAC_AUTH
+	bool 'MAC protection for AUTH module'
+	---help---
+	  This option makes MAC care for AUTH module settings, e.g. attributes
+	  auth_may_setuid, auth_may_set_cap and the kernel-only pseudo
+	  attributes auth_add_f_cap, auth_remove_f_cap, auth_get_caplist. These
+	  settings are treated like MAC settings.
+
+	  See AUTH model description for details.
+
+config RSBAC_MAC_UM_PROT
+	bool 'MAC protection for User Management'
+	depends on RSBAC_UM
+	default y
+	---help---
+	  This option makes MAC care for User Management settings, e.g.
+	  creation, change or deletion of users or groups.
+
+	  See User Management description for details.
+
+config RSBAC_MAC_GEN_PROT
+	bool 'MAC protection for GENeral attributes'
+	---help---
+	  If on, MAC protects general attributes (GEN module) like its own,
+	  i.e., only security officers may change them.
+
+config RSBAC_MAC_LIGHT
+	bool 'Light MAC edition'
+	---help---
+	  This option makes MAC easier to use, but a bit less conforming to the
+	  Bell-LaPadula model.
+	   1. Allow R_CREATE of new files WITHOUT any checking. This way, higher
+	      level objects can be created in a lower level directory.
+	   2. Allow R_MOUNT and R_UMOUNT to ANY user (only Administrator in base
+	      MAC version).
+
+config RSBAC_MAC_TRUSTED_READ
+	bool 'Give trusted processes full read access'
+	---help---
+	  Normally, a mac_trusted process may only violate *-property, i.e., it
+	  may write to any level within its owner's level range from
+	  min_security_level to security_level, regardless of its current level
+	  and the max_read boundary. This makes a user's trusted flag equivalent
+	  to the combination of write_up and write_down flag.
+
+	  With this option turned on, a trusted process may also read from any
+	  such level despite its current level and the min_write boundary. This
+	  adds the meaning of the read_up flag to the trusted flag.
+
+	  Please note that the mac_auto privilege with automatic current level
+	  and read/write boundary adjustment as well as the object mac_shared
+	  flag are always tried before trusted, write_up, write_down and
+	  read_up.
+
+config RSBAC_MAC_RESET_CURR
+	bool 'Reset current level on each execute'
+	---help---
+	  If enabled, the current process level is reset to the user's initial
+	  level on every execute.
+
+config RSBAC_MAC_LOG_LEVEL_CHANGE
+	bool 'Log all automatic changes to current level'
+	default y
+	---help---
+	  If both the effective mac_auto flag at an executable and the
+	  mac_allow_auto flag at the user executing it are set, current levels
+	  may be automatically adjusted to allow access, where it would
+	  otherwise be denied.
+
+	  This option logs each such automatic change to the process current
+	  level, because it means a change to the current access rights.
+
+config RSBAC_MAC_NET_DEV_PROT
+	bool 'MAC network device protection'
+	depends on RSBAC_NET_DEV
+	---help---
+	  If enabled, The MAC module protects network devices in that only
+	  System Administrators may configure them.
+
+config RSBAC_MAC_NET_OBJ_PROT
+	bool 'MAC network object protection'
+	depends on RSBAC_NET_OBJ
+	---help---
+	  Turn this on to have real MAC access control on network objects based
+	  on security levels and categories.
+
+	  The default attribute values are derived from those of the matching
+	  network template.
+
+endif
+
+menuconfig RSBAC_PAX
+	bool 'PAX policy support'
+	default y
+	depends on PAX
+	---help---
+	  The PAX module allows to administrate the PaX flags of programs and
+	  processes. To have these flags enforced, you need to enable
+	  "direct" MAC integration in the PaX control menu under the security
+	  menu (CONFIG_PAX_NO_ACL_FLAGS).
+
+	  PaX is a separate Linux kernel patch available at
+	  <http://pax.grsecurity.net>.
+	  Please have a look at the homepage to get some more information.
+
+if RSBAC_PAX
+config RSBAC_PAX_DEFAULT
+	bool 'Change PAX default flags (PeMRxS)'
+	        help
+	  This option allows to change the PaX default flags for all files from
+	  PeMRxS to any other value.
+	  Please be careful, if you change this setting, specially with existing
+	  configurations - unexpected failures of previously running programs
+	  might happen. Nothing you could not fix by reconfiguration, though.
+
+config RSBAC_PAX_PAGEEXEC
+	bool 'PAX Default P: Enable paging based non-exec pages'
+	        depends on RSBAC_PAX_DEFAULT
+	default y
+
+config RSBAC_PAX_EMUTRAMP
+	bool 'PAX Default E: Emulate Trampolines'
+	        depends on RSBAC_PAX_DEFAULT
+
+config RSBAC_PAX_MPROTECT
+	bool 'PAX Default M: Restrict mprotect'
+	        depends on RSBAC_PAX_DEFAULT
+	default y
+
+config RSBAC_PAX_RANDMMAP
+	bool 'PAX Default R: Randomize mmap() base'
+	        depends on RSBAC_PAX_DEFAULT
+	default y
+
+config RSBAC_PAX_RANDEXEC
+	bool 'PAX Default X: Randomize ET_EXEC base'
+	        depends on RSBAC_PAX_DEFAULT
+
+config RSBAC_PAX_SEGMEXEC
+	bool 'PAX Default S: Segmentation based non-exec pages'
+	        depends on RSBAC_PAX_DEFAULT
+	default y
+endif
+
+menuconfig RSBAC_DAZ
+	bool 'DAZuko policy support'
+	---help---
+	  The Dazuko policy provides the Dazuko malware scanning interface.
+	  Scanning results may optionally be cached, see CONFIG_RSBAC_DAZ_CACHE
+	  below.
+
+	  Only programs marked as scanners may connect to the Dazuko interface,
+	  and only DAZ security administrators are allowed to modify daz_scanner
+	  or daz_scanned.
+
+if RSBAC_DAZ
+config RSBAC_DAZ_SELECT
+	bool 'Let scanners subselect paths'
+	default y
+	---help---
+	  Through Dazuko interface, scanners can define a set of paths
+	  they are interested in. Without this option, RSBAC will ignore
+	  these paths for the sake of speed and full mandatory control.
+
+	  Please note that with RSBAC the daz_do_scan attribute on FD
+	  objects controls which paths get scanned or not. The scanner
+	  selection only reduces the set of paths, never increases.
+
+	  In previous RSBAC versions, subselection by scanners was
+	  always on. It now defaults to on, will be off in next RSBAC
+	  version.
+
+config RSBAC_DAZ_CACHE
+	bool 'Cache scanning results'
+	default y
+	---help---
+	  With this option, all scanning results get cached for the time
+	  specified below.
+
+config RSBAC_DAZ_TTL
+	int 'Scanning result lifetime in seconds'
+	default 86400
+	depends on RSBAC_DAZ_CACHE
+	---help---
+	  Specify the time in seconds a scanning result is kept. After this time
+	  the object will be rescanned on the next access.
+
+	  Use 0 for unlimited, default is 86400 (1 day). Set to 1 to force a
+	  fast rescan.
+
+config RSBAC_DAZ_PERSIST
+	bool 'Keep scanning results over reboot'
+	depends on RSBAC_DAZ_CACHE
+	---help---
+	  If on, file scanning results, which are younger than their life time
+	  limit, are kept persistently during reboots.
+
+	  Using this option can reduce the amount of scanning, but it cannot
+	  protect against file modifications while another kernel is booted.
+
+config RSBAC_DAZ_DEV_MAJOR
+	int	'Dazuko device major number'
+	default 250
+	---help---
+	  Specify the major char device number for /dev/dazuko,
+	  which is used for scanner registration and communication.
+
+	  Use 0 to let the system pick one.
+endif
+
+menuconfig RSBAC_CAP
+	bool 'CAP (Linux CAP) policy support'
+	default y
+	---help---
+	  The Linux Capability (CAP) module allows to set minimum and maximum
+	  Linux capability sets for single users and programs. These boundaries
+	  are applied at CHANGE_OWNER on processes (setuid) and EXECUTE.
+
+	  Minimum settings have precedence over maximums, and program settings
+	  have precedence over user settings.
+
+	  Use this module to run programs that need root privileges from normal
+	  user accounts, e.g. file server daemons, or to restrict programs run
+	  by root, e.g. certain mail daemons.
+
+	  If softmode is enabled and turned on, only the minimum sets are
+	  applied.
+
+
+if RSBAC_CAP
+config RSBAC_CAP_PROC_HIDE
+	bool 'Support CAP process hiding'
+	default y
+	---help---
+	  If enabled, you can hide the process properties shown in /proc from
+	  other users, e.g. command line and current state. The hiding level is
+	  set with the cap_process_hiding process attribute. There are three
+	  possible values:
+	  0 / off: no hiding.
+	  1 / from other users: only processes running for the same user, a CAP
+	      security officer or a CAP system admin may read the properties.
+	  2 / full: only this process and CAP security officers may read the
+	      properties.
+
+	  The kernel command line switch rsbac_cap_process_hiding changes the
+	  default value from 0 to 1. Thus, every normal user can only see her
+	  own process properties.
+
+config RSBAC_CAP_AUTH_PROT
+    depends on RSBAC_AUTH
+	bool 'CAP protection for AUTH module'
+	---help---
+	  This option makes CAP care for AUTH module settings, e.g. attributes
+	  auth_may_setuid, auth_may_set_cap and the kernel-only pseudo
+	  attributes auth_add_f_cap, auth_remove_f_cap, auth_get_caplist. Those
+	  settings are protected by the cap_roles admin (read) and security
+	  officer (rw).
+
+	  See AUTH model description for AUTH details.
+
+config RSBAC_CAP_LOG_MISSING
+	bool 'Log missing capabilities in capable()'
+	---help---
+	  If checked, the Linux capability check function capable() can log
+	  all queries for capabilities, which are missing from the effective
+	  set. Enable with the rsbac_cap_log_missing kernel parameter, or at
+	  runtime via proc interface.
+	  The only exception is CAP_SYS_ADMIN, which fails much too often
+	  and thus never gets logged.
+
+	  Background: If you limit Linux capabilities for users or programs
+	  with the CAP module, some programs fail in secure mode without
+	  "NOT_GRANTED" RSBAC log messages, because this Linux internal check
+	  failed.
+
+	  Please check <http://www.rsbac.org/documentation>
+	  for more info about how the CAP module works.
+
+config RSBAC_CAP_LEARN
+	bool 'Learn missing capabilities in capable()'
+	---help---
+	  If checked, the Linux capability check function capable() will
+	  set all capabilities in the max_caps set of user or program,
+	  which are missing from the current process effective set because
+	  of RSBAC max_caps restrictions.
+	  Enable with the rsbac_cap_learn kernel parameter or at runtime
+	  via proc interface.
+	  Warning: In learning mode, a program with reduced max_caps might
+	  temporarily get more effective caps assigned than granted by
+	  standard kernel!
+
+	  Background: If you limit Linux capabilities for users or programs
+	  with the CAP module, some programs fail in secure mode without
+	  "NOT_GRANTED" RSBAC log messages, because this Linux internal check
+	  failed.
+
+	  Please check <http://www.rsbac.org/documentation>
+	  for more info about how the CAP module works.
+
+config RSBAC_CAP_LEARN_TA
+	int 'Learning mode transaction number'
+	default 0
+	depends on RSBAC_CAP_LEARN && RSBAC_LIST_TRANS
+	---help---
+	  Put learned items into transaction with this number. The
+	  transaction is created, if it does not exist. The default
+	  value 0 means do not use transactions, all extra rights
+	  get added immediately.
+
+	  Note: As the additional rights only appear in the transaction,
+	        the same rights may seem to be added repeatedly, until
+	        the transaction is committed.
+	  Note: All transactions have a maximum lifetime, after which
+	        all data is lost, unless you commit or refresh in time,
+		e.g. with the rsbac_list_ta command line tool.
+	        Increase RSBAC_LIST_TRANS_MAX_TTL as desired.
+endif
+
+menuconfig RSBAC_JAIL
+	bool 'JAIL policy support'
+	default y
+	---help---
+	  The JAIL module gives you an extended chroot facility, similar to
+	  FreeBSD Jails. To put a process into a jail, start it with the
+	  rsbac_jail wrapper or make it call the sys_rsbac_jail syscall
+	  directly.
+
+	  With RSBAC network object support, jailed processes can only use a
+	  designated IP address (if designated address is not 0.0.0.0), and
+	  UNIX or INET sockets of type STREAM, DGRAM or RDM. All other families
+	  and types, e.g. RAW network access, are generally prohibited.
+
+	  From within a jail, only processes and IPC objects of the same jail
+	  can be accessed. Jails can be created from within jails, but get
+	  limited to the parent jail's filesystem root, IP and flags.
+
+	  Additionally, most kernel based administration tasks are forbidden,
+	  e.g. creating device special files, setting network addresses,
+	  getting or setting RSBAC attributes, changing system settings like
+	  name or rlimits etc.
+
+	  Several sys_rsbac_jail flags change the jail behaviour:
+	    - allow_external_ipc: allow to access IPC objects outside this jail
+	    - allow_rlimit: allow to change rlimit
+	    - allow_all_net_family: allow to use all network families, not only
+	      UNIX and INET (IPv4)
+	    - allow_inet_raw: allow to use RAW INET sockets, e.g. for ping
+	    - auto_adjust_inet_any: also allow to bind to INET ANY address
+	      (0.0.0.0), but always change it to specified address
+	      (requires CONFIG_RSBAC_JAIL_NET_ADJUST)
+
+if RSBAC_JAIL
+config RSBAC_JAIL_NET_ADJUST
+	bool 'JAIL allow to auto-adjust INET ANY (0.0.0.0) address'
+	default y
+	depends on RSBAC_NET_OBJ
+	---help---
+	  Turn this option on to allow automatic adjusting of the INET ANY
+	  address 0.0.0.0 to the specified address with the
+	  auto_adjust_inet_any syscall flag.
+
+config RSBAC_JAIL_NET_DEV_PROT
+	bool 'JAIL network device protection'
+	default y
+	depends on RSBAC_NET_DEV
+	---help---
+	  Only with this option enabled can the JAIL module prevent network
+	  device configuration from within a jail. Recommended.
+
+config RSBAC_JAIL_LOG_MISSING
+	bool 'Log missing capabilities in capable()'
+	---help---
+	  If checked, the Linux capability check function capable() can log
+	  all queries for capabilities, which are missing from the effective
+	  set. Enable with the rsbac_jail_log_missing kernel parameter, or at
+	  runtime via proc interface.
+
+	  Background: If you limit Linux capabilities for users or programs
+	  within a JAIL, some programs fail in secure mode without
+	  "NOT_GRANTED" RSBAC log messages, because this Linux internal check
+	  failed.
+
+	  Please check
+	  <http://www.rsbac.org/documentation>
+	  for more info about how the JAIL module works.
+endif
+
+config RSBAC_RES
+	bool 'RES (System Resources) policy support'
+	default y
+	---help---
+	  The Linux Resources (RES) module allows to set minimum and maximum
+	  Linux resource sets for single users and programs. These boundaries
+	  are applied at CHANGE_OWNER on processes (setuid) and EXECUTE.
+
+	  Minimum settings have precedence over maximums, and program settings
+	  have precedence over user settings.
+
+	  Default values for all users can be set at user RSBAC_ALL_USER with
+	  uid 4294967292 ((rsbac_uid_t) -4).
+
+	  If softmode is enabled and turned on, only the minimum sets are
+	  applied.
+
+menuconfig RSBAC_FF
+	bool 'FF policy support'
+	default y
+	---help---
+	  The File Flag module adds some flags for files and dirs to the
+	  system. Current flags are:
+
+	  execute_only (files): Only request EXECUTE is granted
+
+	  read_only (files and dirs): Only non-modifying requests are granted
+
+	  search_only (dirs): All file/subdir accesses need full path, no
+	    listing or modification of dir is granted.
+
+	  write_only (files): Only writing requests are granted, useful for
+	    logging etc. Specially good if inherited to new files from a dir.
+
+	  no_execute (files): No execution of this file allowed.
+
+	  add_inherited (files and dirs): Add (or) flags of parent dir to own
+	    flags. This last flag makes the file flags powerful: simply set
+	    a file flag for a dir (e.g. no_execute on /home), and the whole
+	    subtree is affected.
+
+	  no_rename_or_delete (files and dirs, not inherited): Prevents renaming
+	    or deleting an object, e.g to keep a directory structure fixed.
+
+	  append_only (files): the only write access allowed is APPEND_OPEN.
+	    Good for log files.
+
+if RSBAC_FF
+config RSBAC_FF_AUTH_PROT
+    depends on RSBAC_AUTH
+	bool 'FF protection for AUTH module'
+	---help---
+	  This option makes FF care for AUTH module settings, e.g. attributes
+	  auth_may_setuid, auth_may_set_cap and the kernel-only pseudo
+	  attributes auth_add_f_cap, auth_remove_f_cap, auth_get_caplist. Those
+	  settings are treated like FF settings.
+
+	  See AUTH model description for details.
+
+config RSBAC_FF_UM_PROT
+	bool 'FF protection for User Management'
+	depends on RSBAC_UM
+	default y
+	---help---
+	  This option makes FF care for User Management settings, e.g. creation,
+	  change or deletion of users or groups.
+
+	  See User Management description for details.
+
+config RSBAC_FF_GEN_PROT
+	bool 'FF protection for GENeral attributes'
+	---help---
+	  If on, FF protects general attributes (GEN module) like its own, i.e.,
+	  only security officers may change them.
+endif
+
+menuconfig RSBAC_UDF
+	bool 'UDF policy support'
+	---help---
+	  User Space Decision Facility (UDF) allows to register a user
+	  space program (checker) through RSBAC proc interface or kernel
+	  parameter rsbac_udf_checker=/path/to/prog to be called for
+	  decisions, e.g. a virus scanner wrapper.
+	  The request types leading to a check are listed in
+	  include/rsbac/adf_main.h in the macro RSBAC_UDF_REQUEST_VECTOR.
+	  Checking results may optionally be cached, see
+	  CONFIG_RSBAC_UDF_CACHE below.
+
+	  To avoid loops, the checker program should be marked as
+	  udf_checker to bypass checking for this program.
+	  Only UDF security administrators are allowed to modify udf_checker
+	  or udf_checked.
+
+	  The checker program has to exit with 0 for "allow", 1 for "deny",
+	  254 for "temporary failure, allow" (do not cache) or 255 for
+	  "temporary failure, deny" (do not cache). Any other exit code is
+	  undefined, but for now treated as "deny". If the checker got
+	  killed by a signal, it is treated as "temporary failure, deny".
+
+	  Please note that the checker is started as user mode process,
+	  but with attributes inherited from kernel context. E.g. its RC
+	  role is the kernel role, explicitly set a force role for the
+	  checker to have different rights.
+
+if RSBAC_UDF
+config RSBAC_UDF_CACHE
+	bool 'Cache checking results'
+	default y
+	---help---
+	  With this option, all checking results get cached for the time
+	  specified below. Cache entries get removed immediately on every
+	  write access to the file.
+
+config RSBAC_UDF_TTL
+	int 'Checking result lifetime in seconds'
+	default 86400
+	depends on RSBAC_UDF_CACHE
+	---help---
+	  Specify the time in seconds a checking result is kept. After this time
+	  the object will be rechecked on the next access.
+
+	  Use 0 for unlimited, default is 86400 (1 day). Set to 1 to force a
+	  fast recheck.
+
+config RSBAC_UDF_PERSIST
+	bool 'Keep checking results over reboot'
+	depends on RSBAC_UDF_CACHE
+	---help---
+	  If on, file checking results, which are younger than their life time
+	  limit, are kept persistently during reboots.
+
+	  Using this option can reduce the amount of checking, but it cannot
+	  protect against file modifications while another kernel is booted.
+
+config RSBAC_UDF_ON_CLOSE
+	bool 'Check after closing written file'
+	default n
+	depends on RSBAC_UDF_CACHE
+	---help---
+	  Enable this to check a file after close, if it has been opened
+	  for writing. This fills the cache so that there is no delay at
+	  the next read open or execute, but it delays the close.
+
+config RSBAC_UDF_UDF_PROT
+	bool 'UDF module and attribute protection'
+	default y
+	---help---
+	  Only, if this option is on, the UDF module cares for its own
+	  protection, otherwise it fully depends on other modules
+	  (CONFIG_RSBAC_XX_UDF_PROT).
+	  This is meant for more sophisticated access control than a simple
+	  system_role setting to security_officer.
+
+	  See UDF model description for details.
+
+endif
+
+endmenu
+# Policies
+
+
+menu 'Softmode and switching'
+	depends on RSBAC
+
+config RSBAC_SOFTMODE
+	default y
+	bool 'RSBAC soft mode'
+	---help---
+	  This option enables RSBAC softmode support. In softmode, all
+	  decisions and logging are performed, but the result that is returned
+	  to enforcement is always DO_NOT_CARE. This means that access control
+	  is effectively off!
+
+	  Single exception: even in softmode, all access to rsbac attribute dirs
+	  is always NOT_GRANTED.
+
+	  After boot, softmode will be off, unless kernel parameter
+	  'rsbac_softmode' has been given. It can be turned on via proc
+	  interface with
+
+	       echo debug softmode <value> > /proc/rsbac-info/debug,
+
+	  where <value> is 1 (on) or 0 (off).
+	  If policy switching is enabled, you can also use sys_rsbac_switch,
+	  e.g. via switch_module command line tool.
+
+	  Switching softmode on or off is access controlled with an ADF request
+	  SWITCH_MODULE for module SOFTMODE. The RSBAC builtin modules only
+	  allow softmode under the same conditions as switching themselves off.
+
+	  WARNING: For security reasons, this option should only be used for
+	  debugging of your RSBAC administration settings!
+
+	  Additionally, you might get strange effects during the notification
+	  call rsbac_adf_set_attr(), because the request should not have been
+	  granted in the first place. Unexpected access decisions might occur,
+	  because attributes might have misleading values!
+
+config RSBAC_SOFTMODE_SYSRQ
+	bool 'Toggle soft mode with SysRq-X'
+	depends on RSBAC_SOFTMODE
+	---help---
+	  If this setting and kernel SysRq are enabled, you can toggle softmode
+	  with SysRq-X (char can be changed in rsbac/debug.h).
+	  This makes debugging of your RSBAC administration settings much
+	  easier.
+
+	  WARNING: This is dangerous, because everyone with physical access to
+	           your keyboard can effectively turn off access control!
+
+	  Do not use in production systems!
+
+	  If unsure, say N.
+
+config RSBAC_SOFTMODE_IND
+	bool 'Individual module softmode support'
+	default y
+	depends on RSBAC_SOFTMODE
+	---help---
+	  If on, you can toggle softmode individually for each module.
+	  Softmode for a module can be switched via proc interface with
+
+	       echo debug ind_softmode <module> <value> > /proc/rsbac-info/debug
+
+	  where <module> is the module short name in capitals, e.g. RC, and
+	  <value> is 1 (on) or 0 (off).
+	  If policy switching is enabled, you can also use sys_rsbac_switch,
+	  e.g. via switch_module command line tool.
+
+config RSBAC_SWITCH
+	default y
+	bool 'RSBAC policies switchable'
+	---help---
+	  If enabled, the configured policies can be switched on or off by
+	  syscall sys_rsbac_switch().
+
+	  Of course, switching modules off is performed under their own control.
+
+	  Warning: Though switching off is access controlled itself, any way to
+	  switch off access control is always dangerous!
+
+config RSBAC_SWITCH_ON
+	bool 'Allow to switch stateful modules back on'
+	depends on RSBAC_SWITCH
+	---help---
+	  Some modules must be active all the time to keep their state intact,
+	  e.g. to have correct process roles or security levels. This means
+	  that after turning such a module off, it is in an inconsistent state
+	  and can block the whole system when turned back on. Most prominent
+	  examples are RC and MAC. Some modules only loose part of their
+	  ability to protect the system, e.g. JAIL does not jail new processes.
+
+	  By default, modules that can block the system may never be turned on,
+	  only off. Enable this switch to be able to turn them back on - you
+	  have been warned!
+
+config RSBAC_SWITCH_BOOT_OFF
+	bool 'Allow to switch modules off with kernel parameter'
+	depends on RSBAC_SWITCH
+	---help---
+	  Enable this to allow switching modules off by kernel parameter
+	  rsbac_switch_off_xyz with xyz = module name in small letters,
+	  e.g. rc or auth. Module needs to be set switchable below.
+
+config RSBAC_SWITCH_REG
+	default y
+	bool 'Switch REG modules'
+	depends on RSBAC_SWITCH && RSBAC_REG
+	---help---
+	  Select to switch REG modules on and off at runtime.
+
+config RSBAC_SWITCH_AUTH
+	bool 'Switch AUTH policy'
+	depends on RSBAC_SWITCH && RSBAC_AUTH
+	---help---
+	  Select to switch AUTH module on and off at runtime.
+
+config RSBAC_SWITCH_RC
+	bool 'Switch RC policy'
+	depends on RSBAC_SWITCH && RSBAC_RC
+	---help---
+	  Select to switch RC module on and off at runtime.
+
+config RSBAC_SWITCH_ACL
+	bool 'Switch ACL policy'
+	depends on RSBAC_SWITCH && RSBAC_ACL
+	---help---
+	  Select to switch ACL module on and off at runtime.
+
+config RSBAC_SWITCH_MAC
+	bool 'Switch MAC policy'
+	depends on RSBAC_SWITCH && RSBAC_MAC
+	---help---
+	  Select to switch MAC module on and off at runtime.
+
+config RSBAC_SWITCH_PAX
+	bool 'Switch PAX policy'
+	depends on RSBAC_SWITCH && RSBAC_PAX
+	---help---
+	  Select to switch PAX module on and off at runtime.
+
+config RSBAC_SWITCH_DAZ
+	bool 'Switch DAZ policy'
+	depends on RSBAC_SWITCH && RSBAC_DAZ
+	---help---
+	  Select to switch DAZ module on and off at runtime.
+
+config RSBAC_SWITCH_CAP
+	bool 'Switch CAP policy'
+	depends on RSBAC_SWITCH && RSBAC_CAP
+	---help---
+	  Select to switch CAP module on and off at runtime.
+
+config RSBAC_SWITCH_JAIL
+	bool 'Switch JAIL policy'
+	depends on RSBAC_SWITCH && RSBAC_JAIL
+	---help---
+	  Select to switch JAIL module on and off at runtime.
+
+config RSBAC_SWITCH_RES
+	bool 'Switch RES policy'
+	depends on RSBAC_SWITCH && RSBAC_RES
+	---help---
+	  Select to switch RES module on and off at runtime.
+
+config RSBAC_SWITCH_FF
+	bool 'Switch FF policy'
+	depends on RSBAC_SWITCH && RSBAC_FF
+	---help---
+	  Select to switch FF module on and off at runtime.
+
+config RSBAC_SWITCH_UDF
+	bool 'Switch UDF policy'
+	depends on RSBAC_SWITCH && RSBAC_UDF
+	---help---
+	  Select to switch UDF module on and off at runtime.
+endmenu
+
+menu 'Logging'
+	depends on RSBAC
+
+config RSBAC_IND_LOG
+	bool 'Individual file/dir/dev object logging'
+	default y
+	---help---
+	  Enable individual log levels for every request type for every file,
+	  dir and device. Log levels are none, denied requests, full, request
+	  based. Default value is request based for all request types.
+
+	  If this option is off, only general log levels for requests are used
+	  (same as individual logging for all objects set to request based).
+
+config RSBAC_IND_USER_LOG
+	bool 'Individual user logging'
+	default y
+	---help---
+	  When enabled, you can specify for every single user, which request
+	  type(s) will always be logged.
+
+config RSBAC_IND_PROG_LOG
+	bool 'Individual program logging'
+	default y
+	---help---
+	  When enabled, you can specify for every single program file, which
+	  request type(s) will always be logged.
+
+config RSBAC_LOG_PROGRAM_FILE
+	bool 'Log program file'
+	default y
+	---help---
+	  Enable this option to get the full program file path logged together
+	  with the process name.
+
+config RSBAC_LOG_FULL_PATH
+	bool 'Log full path'
+	default y
+	---help---
+	  If this is turned on, logging messages for file and dir targets will
+	  contain the full path. This makes the log significantly longer and
+	  takes some extra CPU time, but also increases log usability.
+
+config RSBAC_MAX_PATH_LEN
+	int 'Maximum path length (256 - 2000)'
+	default 512
+	depends on RSBAC_LOG_FULL_PATH
+	---help---
+	  If the full path is longer than CONFIG_RSBAC_MAX_PATH_LEN, the 
+	  leading dirnames will be left out until it fits. The bigger this
+	  value, the more memory will be allocated in the logging routine.
+
+config RSBAC_LOG_PSEUDO
+	bool 'Pseudonymous logging support'
+	default n
+	---help---
+	  Enable to get pseudo values for users honoured in all request logging
+	  entries. If a pseudo value is not 0, it is logged instead of the uid.
+
+config RSBAC_LOG_PSEUDO_FS
+	bool 'Pseudonymize filesystem objects'
+	default n
+	        depends on RSBAC_LOG_PSEUDO
+	---help---
+	  If enabled, the logging code exchanges filesystem object names with
+	  their owner's pseudo, if the pseudo value is not 0 and the parent
+	  object has another owner.
+
+config RSBAC_SYSLOG_RATE
+	bool 'Syslog rate limit'
+	default y
+	---help---
+	  Enable the limiting of the number of log message lines sent to syslog
+	  per second.
+
+config RSBAC_SYSLOG_RATE_DEF
+	int 'Default allowed message lines per second'
+	depends on RSBAC_SYSLOG_RATE
+	default 1000
+	---help---
+	  Number of allowed syslog message lines per second. This value can be
+	  changed with kernel parameter rsbac_syslog_rate=<n> or at runtime via
+	  the proc interface.
+
+	  Default value is 1000.
+
+config RSBAC_RMSG
+	bool 'RSBAC own logging facility'
+	default y
+	---help---
+	  Add logging of requests with extra facility, which is basically a
+	  clone of printk/sys_syslog. If proc is supported, a file rmsg appears
+	  in rsbac-info and can be used like kmsg, e.g. with a patched klogd,
+	  cat or tail -f.
+	  This file is protected by RSBAC with object type SCD/rsbac_log.
+	  A new syscall sys_rsbac_log, similar to sys_syslog, also gives access
+	  to logging stuff.
+
+config RSBAC_RMSG_MAXENTRIES
+	int 'Maximum number of messages in the log buffer'
+	depends on RSBAC_RMSG
+	default 200
+	---help---
+	  Number of allowed messages in the RSBAC log buffer. Each message
+	  takes from 32 to 2048 bytes of memory.
+
+	  Default value is 200.
+
+config RSBAC_RMSG_NOSYSLOG
+	bool 'Allow to disable logging to syslog'
+	default y
+	depends on RSBAC_RMSG
+	---help---
+	  When on, you can temporarily disable logging to syslog with kernel
+	  parameter rsbac_nosyslog or via /proc/rsbac-info/debug. Useful for
+	  initial configuration on system installation or if you need a clean
+	  separation.
+
+	  If unsure, say Y.
+
+config RSBAC_LOG_REMOTE
+	bool 'Log to remote UDP network socket'
+	depends on RSBAC_RMSG
+	---help---
+	  If enabled, copies of every message in the RSBAC log facility will be
+	  sent to a remote system over network.
+
+if RSBAC_LOG_REMOTE=y
+
+config RSBAC_LOG_REMOTE_TCP
+	bool 'Use TCP for remote logging'
+	depends on RSBAC_RMSG
+	---help---
+	  If enabled, use more reliable TCP protocol to transfer logs.
+
+config RSBAC_LOG_REMOTE_MAXENTRIES
+	int 'Maximum number of messages in the remote log buffer'
+	depends on RSBAC_RMSG
+	default 200
+	---help---
+	  Number of allowed messages in the RSBAC remote log buffer. Each
+	  message takes from 32 to 2048 bytes of memory.
+
+	  Default value is 200.
+
+#config RSBAC_LOG_REMOTE_SYNC
+#	bool 'Immediate remote logging'
+
+config RSBAC_LOG_INTERVAL
+	int 'Logging interval in timer ticks'
+	default 100
+#	depends on RSBAC_LOG_REMOTE_SYNC=n
+
+config RSBAC_LOG_LOCAL_ADDR
+	string 'Local UDP address'
+	default "0.0.0.0"
+
+config RSBAC_LOG_LOCAL_PORT
+	int 'Local UDP port'
+	default 0
+
+config RSBAC_LOG_REMOTE_ADDR
+	string 'Remote UDP address'
+	default "0.0.0.0"
+
+config RSBAC_LOG_REMOTE_PORT
+	int 'Remote UDP port'
+	default 514
+
+endif
+
+endmenu
+
+config RSBAC_SYM_REDIR
+	bool 'RSBAC symlink redirection'
+	depends on RSBAC
+	---help---
+	  This feature optionally changes the contents of a symlink, based on
+	  the owner ID, the current MAC security level or the current RC role
+	  ID of the process accessing it.
+
+	  NOTE: For technical reasons, all numeric characters at the end of the
+	        original symlink contents will be replaced, not appended to.
+	        This can be used to e.g. get the uid itself as final name and
+	        the parent dir (or nothing...), if redirection is off.
+
+if RSBAC_SYM_REDIR
+
+config RSBAC_SYM_REDIR_REMOTE_IP
+	bool 'Add remote IP address'
+	depends on RSBAC_NET_OBJ
+	---help---
+	  With this option enabled, every read from a symlink, which has a
+	  symlink_add_remote_ip value > 0, gets this number of bytes added
+	  in dot notation, e.g. 192.168.0 with value 3.
+
+	  This option is e.g. useful, if you want to provide different user
+	  shells, depending on the origin of a connection:
+	  Set user shell to /bin/linkshell. Make this a symlink to
+	  /bin/usershell-, provide /bin/usershell-192.168.0 for users from
+	  that network and /bin/usershell-0.0.0 for local users.
+
+	  As a side effect, users connecting from other networks have no
+	  valid shell at all.
+
+config RSBAC_SYM_REDIR_UID
+	bool 'Add user ID number'
+	---help---
+	  With this option enabled, every read from a symlink, which has the
+	  symlink_add_uid flag set, gets the caller uid added in decimal
+	  notation.
+
+	  This feature can e.g. be used to setup individual /tmp dirs for all
+	  users, as root call:
+	  
+	  cd /
+	  mkdir tmpdirs && chmod 777 tmpdirs && chmod o+t tmpdirs
+	  # stay compatible, if redirection is off, by reusing old /tmp
+	  mv tmp tmpdirs
+	  ln -s tmpdirs/tmp tmp
+	  mkdir tmpdirs/tmp0 ; chmod 700 tmpdirs/tmp0
+	  echo 'mkdir /tmpdirs/tmp$UID && chmod 700 /tmpdirs/tmp$UID' \
+	    >>/etc/profile
+
+	  As user with modify right for general attributes (e.g. user 400), set
+	  symlink_add_uid to on for /tmp:
+	  attr_set_file_dir SYMLINK /tmp symlink_add_uid 1
+
+	  From now on, root accesses to /tmp show /tmpdirs/tmp0, user 400
+	  accesses show /tmpdir/tmp400, etc. It is of course advisable to
+	  protect the individual dirs against root.
+
+config RSBAC_SYM_REDIR_MAC
+	bool 'Add MAC current security level'
+	depends on RSBAC_MAC
+	---help---
+	  With this option enabled, every read from a symlink, which has the
+	  symlink_add_mac_level flag set, gets the calling process's current
+	  MAC security level added in decimal notation.
+
+	  It can be used to e.g. provide separate /tmp dirs for all MAC levels
+	  and thus avoid unwanted flow of information.
+	  See 'Add user ID number' help to get an idea of how to do this.
+
+config RSBAC_SYM_REDIR_MAC_CAT
+	bool 'Also add MAC current category vector'
+	depends on RSBAC_SYM_REDIR_MAC
+	---help---
+	  If enabled, the redirected symlink contents will not only contain the
+	  process current MAC security level, but also its current category set
+	  as the usual string of 0 and 1, separated by a colon.
+
+	  WARNING: This will result in more possible values than your
+	           filesystem can handle names and inodes, so please be
+		   careful.
+
+config RSBAC_SYM_REDIR_RC
+	bool 'Add RC role number'
+	depends on RSBAC_SYM_REDIR && RSBAC_RC
+	---help---
+	  With this option enabled, every read from a symlink, which has the
+	  symlink_add_rc_role flag set, gets the calling process's current RC
+	  role ID added in decimal notation.
+
+	  It can be used to e.g. provide individual /tmp dirs for all roles.
+	  See 'Add user ID number' help to get an idea of how to do this.
+endif
+
+config RSBAC_ALLOW_DAC_DISABLE
+	bool 'Allow disabling of Linux filesystem access control'
+	depends on RSBAC
+	---help---
+	  Turn this on to get access to Linux DAC disabling switches.
+
+if RSBAC_ALLOW_DAC_DISABLE
+
+config RSBAC_ALLOW_DAC_DISABLE_FULL
+	bool 'Allow full disabling (DANGEROUS!)'
+	---help---
+	  With this option you can allow turning off Linux discretionary access
+	  control for all filesystem objects, except where the filesystem
+	  provides its own access control function.
+
+	  In most cases it should be sufficient to set the DAC_OVERRIDE Linux
+	  capability with the DAC module for single users or programs instead.
+
+	  To disable Linux access control, use the kernel param
+	  rsbac_dac_disable, syscall sys_rsbac_switch (utility switch_module)
+	  for switch target DAC_DISABLE or
+	  
+	       echo debug dac_disable 1 >/proc/rsbac-info/debug.
+
+	  For security reasons, Linux access control is still enabled by
+	  default, even with this option active!
+
+	  DANGER! Do not use, unless you really know what you are doing!
+
+config RSBAC_ALLOW_DAC_DISABLE_PART
+	bool 'Allow partial (dir tree based) disabling'
+	---help---
+	  If enabled, you can turn off Linux discretionary access control for
+	  individual filesystem objects and directory trees.
+	  
+	  This option is useful, if you want to rely on RSBAC access control
+	  instead of standard Linux style, without giving full access in case
+	  RSBAC is not running.
+	  
+	  NOTE: You can use the linux2acl command line tool to get your old
+	        Linux rights converted to ACL settings.
+endif
+
+menu 'Other RSBAC options'
+	depends on RSBAC
+
+config RSBAC_SECDEL
+	bool 'Support secure_delete'
+    depends on EXT2_FS || EXT3_FS || EXT4_FS || MSDOS_FS || VFAT_FS
+	---help---
+	  This option enables secure deletion and truncation of all files.
+	  The decision whether to overwrite is dispatched to all modules,
+	  if one says yes, the file is overwritten. Currently only FF
+	  supports this.
+
+	  FF returns yes, if file is marked with ff_flag secure_delete. This
+	  flag can, as usual, be inherited from parent dir, if flag
+	  add_inherited is set (default, if option 'Inherit as default' has
+	  been chosen).
+
+	  Secure deletion and truncation is currently done by overwriting once
+	  with zeros, because this is enough against hackers and standard level
+	  analysers. Against well-fed organisations who got hold of your disk
+	  there is no protection anyway.
+
+	  This mechanism is currently only supported for ext2, ext3, minix,
+	  msdos and vfat, but could be extended to other file systems, if
+	  needed.
+
+config RSBAC_RW
+	bool 'Intercept sys_read and sys_write'
+	default y
+	---help---
+	  If enabled, the syscalls sys_read() and sys_write() for reading from
+	  and writing to opened files, fifos and devices are also intercepted.
+	  This slows down the system a bit, but allows more control of object
+	  accesses to adapt to configuration changes.
+
+	  Please note that the interception for sockets only takes place, if
+	  net support and socket read/write interception are also enabled
+	  (CONFIG_RSBAC_NET and CONFIG_RSBAC_NET_RW).
+
+config RSBAC_IPC_SEM
+	bool 'Intercept Semaphore IPC operations'
+	default y
+	---help---
+	  If on, System V IPC Semaphores are also protected. As there is no
+	  direct data flow over semaphores, they can mostly be misused for
+	  denial of service attacks. Turn on for special needs, keep off
+	  otherwise.
+
+config RSBAC_DAC_OWNER
+	bool 'Control DAC process owner (seteuid, setfsuid)'
+	---help---
+	  Usually, only set*uid calls, which affect the real user ID used for
+	  RSBAC decisions, issue a decision request CHANGE_OWNER for processes.
+	  With this option, changes to the effective (CHANGE_DAC_EFF_OWNER) and
+	  the filesystem (CHANGE_DAC_FS_OWNER) owner are also controlled.
+
+	  Please also see AUTH option 'AUTH support for effective and fs owner
+	  control'.
+
+config RSBAC_DAC_GROUP
+	bool 'Control DAC process group (setegid, setfsgid)'
+	---help---
+	  Usually, set*gid calls issue only the decision request CHANGE_GROUP
+	  for changes to the process group.
+	  With this option, changes to the effective (CHANGE_DAC_EFF_GROUP) and
+	  the filesystem (CHANGE_DAC_FS_GROUP) group are also controlled.
+
+	  Please also see AUTH option 'AUTH support for effective and fs group
+	  control'.
+
+
+config RSBAC_PROC_HIDE
+	bool 'Hide processes in /proc'
+	---help---
+	  If enabled, a process is also hidden in /proc listing, if the reading
+	  process has no GET_STATUS_DATA right to it.
+	  This option adds a significant amount of requests, when reading
+	  /proc, so it is off by default.
+
+config RSBAC_FSOBJ_HIDE
+	bool 'Hide filesystem objects'
+	---help---
+	  If enabled, every filesystem object (file, dir, named pipe,
+          unix socket) will be completely hidden from every process that
+          has no SEARCH right to it.
+
+	  WARNING! You need to remove all rights to that object you are
+          trying to hide to make it fully protected! Otherwise
+          overwriting may be possible by a process that knows this
+          object's name!
+
+config RSBAC_FREEZE
+	bool 'Support freezing of RSBAC configuration'
+	default y
+	---help---
+	  If enabled, the kernel parameter rsbac_freeze disables all
+	  administrative system calls, which change settings.
+
+config RSBAC_FREEZE_UM
+	bool 'Also freeze User Management'
+	depends on RSBAC_FREEZE && RSBAC_UM
+	---help---
+	  If enabled, the RSBAC User Management gets frozen, too.
+
+config RSBAC_SYSLOG
+	bool 'RSBAC check sys_syslog'
+	---help---
+	  If enabled, the syscall sys_syslog() for system log is also checked,
+	  leading to less performance for a minor security issue.
+
+config RSBAC_IOCTL
+	bool 'Generic check in sys_ioctl'
+	default y
+	---help---
+	  Enable this switch to get all calls to sys_ioctl for DEV and NETOBJ
+	  targets checked by RSBAC. In any case, some important sys_ioctl calls
+	  will also be checked as GET_STATUS_DATA or MODIFY_SYSTEM_DATA
+	  requests.
+
+	  This interception produces some overhead on desktop systems, so it
+	  should be considered to turn it off on such systems.
+
+config RSBAC_USER_CHOWN
+	bool 'Check CHANGE_OWNER on PROCESS against USER target'
+	default n
+	---help---
+	  With this option, each CHANGE_OWNER request on PROCESS targets
+	  creates an additional CHANGE_OWNER request on the new owner as
+	  USER target.
+
+	  The additional check allows modules to control user changes
+	  depending on the current state of the process attributes,
+	  e.g. current role or owner.
+
+config RSBAC_DAT_VISIBLE
+	bool 'Make RSBAC data files visible'
+	---help---
+	  By default, the rsbac.dat directories containing the list data
+	  backups are unreadable for any user. Unfortunately, some programs
+	  must be able to read all directories, e.g. the quota tools.
+
+	  This option enables read and status access to the rsbac.dat
+	  directories, but the files themselves are kept unreadable.
+
+config RSBAC_NO_DECISION_ON_NETMOUNT
+	bool 'No decision on net mounts'
+	---help---
+	  If this option is turned on, no decisions are made and no attributes
+	  are set for all accesses to files and dirs on network mounts. For
+	  these targets, RSBAC behaves like a maintenance kernel. So even 
+	  Dazuko is turned off. Attribute saving or restoring is not done
+	  anyway.
+
+	  Use this option, if you cannot access your network files properly,
+	  and keep it off otherwise.
+
+config RSBAC_ENFORCE_CLOSE 
+	bool 'Enforce denied close access'
+	---help---
+	  By default, RSBAC only logs denied CLOSE access on filesystem
+	  objects and still performs the close, because many broken
+	  programs rely on close to always succeed. With this switch on,
+	  RSBAC really returns -EPERM and keeps the object opened.
+
+config RSBAC_MOVETO
+	bool 'Use MOVETO requests when writing to DIR'
+	default n
+	---help---
+	  When moving an object into a directory, use request
+	  MOVETO, not the old WRITE.
+	  Default is n for backwards compatibility.
+
+config RSBAC_MOVETO_EXDEV
+	bool 'Treat denied MOVETO on DIR like different device'
+	default n
+	---help---
+	  By default, RSBAC just returns -EPERM, if moving an object
+	  into a dir is denied because of missing WRITE or MOVETO right.
+	  With this option on, it will instead return -EXDEV, as if
+	  the new dir was on a different partition. Most tools will
+	  then try to copy the old item and delete it afterwards.
+
+config RSBAC_USER_MOD_IOPERM
+	bool 'X support (normal user MODIFY_PERM access to ST_ioports)'
+	---help---
+	  Normally, MODIFY_PERMISSIONS_DATA access to SCD target ST_ioports is
+	  not granted for normal users, because this would allow direct
+	  hardware access. Unfortunately, X servers depend on this. So if you
+	  need X on your system, enable this, otherwise keep it off.
+
+	  This switch enables the following changes:
+	    - MAC, FC, SIM and AUTH hardwired policies are adjusted to allow
+	      this access type for every user.
+	    - RC and ACL default settings are adjusted accordingly, but
+	      existing or later settings are not affected.
+
+config RSBAC_FAKE_ROOT_UID
+	bool 'Faked root uid'
+	---help---
+	  With this turned on, programs can optionally get uid 0 returned from
+	  every getuid() and/or geteuid() call.
+
+	  Some programs check, whether they really run as root, although they
+	  already have sufficient rights to do their jobs. This forces users
+	  to keep them running under the dangerous root account.
+
+
+config RSBAC_XSTATS
+	bool 'RSBAC extra statistics'
+	default y
+	depends on RSBAC_PROC
+	---help---
+	  If enabled, extended RSBAC statistics are collected. Currently these
+	  are mostly count matrices of adf_request and adf_set_attr calls by
+	  target type and request type. These matrices give a detailed overview
+	  of the request and thus the system call behaviour.
+
+	  Also, there is an access count for calls to data structures by target
+	  type.
+
+	  The extra data can be read from another proc file called xstats.
+endmenu
+
+endif
diff --git a/rsbac/Makefile b/rsbac/Makefile
new file mode 100644
index 0000000..c4e0385
--- /dev/null
+++ b/rsbac/Makefile
@@ -0,0 +1,11 @@
+#
+# Main Makefile for the Rule Set Based Access Control subsystem.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+
+obj-y     := help/ data_structures/ adf/
+obj-m     := adf/
+
+clean:	Makefile
+	rm -f `find . -name modules.builtin -o -name modules.order -name '*.o' -o -name '*.o.cmd' -o -name '*.ko' -o -name '*.ko.cmd' -print`
+
diff --git a/rsbac/adf/Makefile b/rsbac/adf/Makefile
new file mode 100644
index 0000000..5fed80e
--- /dev/null
+++ b/rsbac/adf/Makefile
@@ -0,0 +1,54 @@
+#
+# File: rsbac/adf/Makefile
+#
+# Makefile for the Linux RSBAC Access Control Decision Facility (ADF)
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+obj-y   := adf_main.o
+
+ifeq ($(CONFIG_RSBAC_DEBUG),y)
+obj-y   += adf_check.o
+endif
+
+# Adding policies
+subdir-$(CONFIG_RSBAC_MAC) += mac
+obj-$(CONFIG_RSBAC_MAC) += mac/
+
+subdir-$(CONFIG_RSBAC_DAZ) += daz
+obj-$(CONFIG_RSBAC_DAZ) += daz/
+
+subdir-$(CONFIG_RSBAC_FF) += ff
+obj-$(CONFIG_RSBAC_FF) += ff/
+
+subdir-$(CONFIG_RSBAC_RC) += rc
+obj-$(CONFIG_RSBAC_RC) += rc/
+
+subdir-$(CONFIG_RSBAC_AUTH) += auth
+obj-$(CONFIG_RSBAC_AUTH) += auth/
+
+subdir-$(CONFIG_RSBAC_ACL) += acl
+obj-$(CONFIG_RSBAC_ACL) += acl/
+
+subdir-$(CONFIG_RSBAC_CAP) += cap
+obj-$(CONFIG_RSBAC_CAP) += cap/
+
+subdir-$(CONFIG_RSBAC_JAIL) += jail
+obj-$(CONFIG_RSBAC_JAIL) += jail/
+
+subdir-$(CONFIG_RSBAC_PAX) += pax
+obj-$(CONFIG_RSBAC_PAX) += pax/
+
+subdir-$(CONFIG_RSBAC_RES) += res
+obj-$(CONFIG_RSBAC_RES) += res/
+
+subdir-$(CONFIG_RSBAC_UDF) += udf
+obj-$(CONFIG_RSBAC_UDF) += udf/
+
+subdir-$(CONFIG_RSBAC_REG) += reg
+obj-$(CONFIG_RSBAC_REG) += reg/
+ifeq ($(CONFIG_RSBAC_REG_SAMPLES),y)
+subdir-m += reg
+endif
+
diff --git a/rsbac/adf/acl/Makefile b/rsbac/adf/acl/Makefile
new file mode 100644
index 0000000..448fe53
--- /dev/null
+++ b/rsbac/adf/acl/Makefile
@@ -0,0 +1,10 @@
+#
+# File: rsbac/adf/auth/Makefile
+#
+# Makefile for the Linux rsbac auth decision module.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := acl_syscalls.o acl_main.o
+
diff --git a/rsbac/adf/acl/acl_main.c b/rsbac/adf/acl/acl_main.c
new file mode 100644
index 0000000..a7e3b47
--- /dev/null
+++ b/rsbac/adf/acl/acl_main.c
@@ -0,0 +1,532 @@
+/**************************************************** */
+/* Rule Set Based Access Control                      */
+/* Implementation of the Access Control Decision      */
+/* Facility (ADF) - Access Control Lists (ACL)        */
+/* File: rsbac/adf/acl/acl_main.c                     */
+/*                                                    */
+/* Author and (c) 1999-2013: Amon Ott <ao@rsbac.org>  */
+/*                                                    */
+/* Last modified: 27/Nov/2013                         */
+/**************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/aci.h>
+#include <rsbac/acl.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/adf_syshelpers.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/debug.h>
+#include <rsbac/lists.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_ACL_LEARN)
+#ifdef CONFIG_RSBAC_ACL_LEARN_TA
+rsbac_list_ta_number_t acl_learn_ta = CONFIG_RSBAC_ACL_LEARN_TA;
+#else
+rsbac_list_ta_number_t acl_learn_ta = 0;
+#endif
+#endif
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/* in acl_syscalls.c */
+rsbac_boolean_t rsbac_acl_check_super(enum  rsbac_target_t target,
+                              union rsbac_target_id_t tid,
+                                    rsbac_uid_t user);
+
+rsbac_boolean_t rsbac_acl_check_right(enum  rsbac_target_t target,
+                              union rsbac_target_id_t tid,
+                                    rsbac_uid_t user,
+                                    rsbac_pid_t caller_pid,
+                              enum  rsbac_adf_request_t request)
+  {
+    rsbac_boolean_t                   result = FALSE;
+    int                       err=0, tmperr;
+    int                       i;
+    rsbac_acl_group_id_t    * group_p;
+    #if defined(CONFIG_RSBAC_RC)
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    #endif
+
+    /* Only check implemented targets */
+    switch(target)
+      {
+        case T_FILE:
+        case T_DIR:
+        case T_FIFO:
+        case T_SYMLINK:
+        case T_UNIXSOCK:
+        case T_DEV:
+        case T_IPC:
+        case T_SCD:
+        case T_USER:
+        case T_PROCESS:
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+        case T_GROUP:
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+        case T_NETDEV:
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+        case T_NETTEMP_NT:
+        case T_NETTEMP:
+        case T_NETOBJ:
+#endif
+          break;
+        default:
+          return TRUE;
+      }
+    /* inherited own rights */
+    err = rsbac_acl_get_single_right(target,
+                                     tid,
+                                     ACLS_USER,
+                                     (rsbac_acl_subject_id_t) user,
+                                     request,
+                                     &result);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return FALSE;
+      }
+    if(result)
+      return TRUE;
+
+    /* add group and role rights */
+    /* group everyone */
+    err = rsbac_acl_get_single_right(target,
+                                     tid,
+                                     ACLS_GROUP,
+                                     RSBAC_ACL_GROUP_EVERYONE,
+                                     request,
+                                     &result);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return FALSE;
+      }
+    if(result)
+      return TRUE;
+
+    #if defined(CONFIG_RSBAC_RC)
+    /* use process role */
+    /* first get role */
+    i_tid.process = caller_pid;
+    if (rsbac_get_attr(SW_RC,
+                       T_PROCESS,
+                       i_tid,
+                       A_rc_role,
+                       &i_attr_val1,
+                       FALSE))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_acl_check_right(): rsbac_get_attr() for process rc_role returned error!\n");
+      }
+    else
+      {
+        err = rsbac_acl_get_single_right(target,
+                                         tid,
+                                         ACLS_ROLE,
+                                         i_attr_val1.rc_role,
+                                         request,
+                                         &result);
+        if(err)
+          {
+            char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                get_error_name(tmp,err);
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
+                       tmp);
+                rsbac_kfree(tmp);
+              }
+            return FALSE;
+          }
+        if(result)
+          return TRUE;
+      }
+    #endif
+
+    /* other groups */
+    /* first get user groups */
+    group_p = NULL;
+    err = rsbac_acl_get_user_groups(0, user, &group_p, NULL);
+    if(err<0)
+      {
+        char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_right(): rsbac_acl_get_user_groups() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return err;
+      }
+    for(i=0; i<err; i++)
+      {
+        tmperr = rsbac_acl_get_single_right(target,
+                                            tid,
+                                            ACLS_GROUP,
+                                            group_p[i],
+                                            request,
+                                            &result);
+        if(tmperr)
+          {
+            char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_check_right(): rsbac_acl_get_single_right() returned error %s!\n",
+                       get_error_name(tmp, tmperr));
+                rsbac_kfree(tmp);
+              }
+            if(group_p)
+              rsbac_kfree(group_p);
+            return FALSE;
+          }
+        if(result)
+          {
+            if(group_p)
+              rsbac_kfree(group_p);
+            return TRUE;
+          }
+      }
+    if(group_p)
+      rsbac_kfree(group_p);
+
+    /* SUPERVISOR? */
+#ifdef CONFIG_RSBAC_ACL_LEARN
+    result = rsbac_acl_check_super(target, tid, user);
+    if(   !result
+       && (request < R_NONE)
+      )
+      {
+        switch(target)
+          {
+            case T_FILE:
+            case T_DIR:
+            case T_FIFO:
+            case T_SYMLINK:
+            case T_UNIXSOCK:
+              if(rsbac_acl_learn_fd)
+                {
+                  char * tmp;
+                  enum rsbac_acl_subject_type_t  subj_type;
+                       rsbac_acl_subject_id_t    subj_id;
+                       rsbac_acl_rights_vector_t rights;
+                       rsbac_time_t              ttl;
+
+#ifdef CONFIG_RSBAC_ACL_LEARN_TA
+		  if (!rsbac_list_ta_exist(acl_learn_ta))
+			rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+					&acl_learn_ta,
+					RSBAC_ALL_USERS,
+					RSBAC_ACL_LEARN_TA_NAME,
+					NULL);
+#endif
+                  tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                  if(tmp)
+                    {
+                      char * target_type_name;
+
+                      target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                      if(target_type_name)
+                        {
+                          char * target_id_name;
+
+                          #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                          target_id_name
+                           = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                          /* max. path name len + some extra */
+                          #else
+                          target_id_name = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+                          /* max. file name len + some extra */
+                          #endif
+                          if(target_id_name)
+                            {
+                              get_request_name(tmp,request);
+                              get_target_name(target_type_name, target, target_id_name, tid);
+                              rsbac_printk(KERN_INFO
+                                           "rsbac_acl_check_right(): auto_learn_fd: granting right %s for user %u to target_type %s, tid %s, transaction %u!\n",
+                                           tmp,
+                                           user,
+                                           target_type_name,
+                                           target_id_name,
+                                           acl_learn_ta);
+                              rsbac_kfree(target_id_name);
+                            }
+                          rsbac_kfree(target_type_name);
+                        }
+                    }
+                  subj_type = ACLS_USER;
+                  subj_id = user;
+                  rights = RSBAC_REQUEST_VECTOR(request);
+                  ttl = 0;
+                  err = rsbac_acl_add_to_acl_entry(acl_learn_ta, target, tid, subj_type, subj_id, rights, ttl);
+                  if(tmp)
+                    {
+                      if(err)
+                        {
+                          rsbac_printk(KERN_WARNING
+                                       "rsbac_acl_check_right(): rsbac_acl_add_to_acl_entry() returned error %s!\n",
+                                       get_error_name(tmp,err));
+                        }
+                      rsbac_kfree(tmp);
+                    }
+                  result = TRUE;
+                }
+              break;
+
+            default:
+              break;
+          }
+      }
+    return result;
+#else
+    return rsbac_acl_check_super(target, tid, user);
+#endif
+  }
+
+rsbac_boolean_t rsbac_acl_check_forward(enum  rsbac_target_t target,
+                                union rsbac_target_id_t tid,
+                                      rsbac_uid_t user,
+                                      rsbac_acl_rights_vector_t rights)
+  {
+    rsbac_acl_rights_vector_t i_rights = 0;
+    rsbac_acl_rights_vector_t i_rvec = ((rsbac_acl_rights_vector_t) 1 << ACLR_FORWARD) | rights;
+    int                       err=0;
+
+
+    /* Only check implemented targets */
+    switch(target)
+      {
+        case T_FILE:
+        case T_DIR:
+        case T_FIFO:
+        case T_SYMLINK:
+        case T_UNIXSOCK:
+        case T_DEV:
+        case T_IPC:
+        case T_SCD:
+        case T_USER:
+        case T_PROCESS:
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+        case T_GROUP:
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+        case T_NETDEV:
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+        case T_NETTEMP_NT:
+        case T_NETTEMP:
+        case T_NETOBJ:
+#endif
+          break;
+        default:
+          return TRUE;
+      }
+    /* get effective rights */
+    err = rsbac_acl_sys_get_rights(0, target, tid, ACLS_USER, (rsbac_acl_subject_id_t) user, &i_rights, TRUE);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_forward(): rsbac_acl_sys_get_rights() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return FALSE;
+      }
+    if((i_rights & i_rvec) == i_rvec)
+      return TRUE;
+    else
+      return FALSE;
+  }
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request_acl (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)
+  {
+    switch (request)
+      {
+        case R_READ_ATTRIBUTE:
+        case R_MODIFY_ATTRIBUTE:
+            switch(attr)
+              { /* owner must be changed by other request to prevent inconsistency */
+                case A_owner:
+                  if(request == R_READ_ATTRIBUTE)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* Only protect AUTH, if asked to by configuration */
+                #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
+                case A_auth_may_setuid:
+                case A_auth_may_set_cap:
+                case A_auth_start_uid:
+                case A_auth_start_euid:
+                case A_auth_start_gid:
+                case A_auth_start_egid:
+                case A_auth_learn:
+                case A_auth_add_f_cap:
+                case A_auth_remove_f_cap:
+                  tid.scd = AST_auth_administration;
+                  if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                #endif
+
+                #ifdef CONFIG_RSBAC_ACL_GEN_PROT
+                case A_pseudo:
+                case A_log_array_low:
+                case A_log_array_high:
+                case A_log_program_based:
+                case A_log_user_based:
+                case A_symlink_add_remote_ip:
+                case A_symlink_add_uid:
+                case A_symlink_add_rc_role:
+                case A_linux_dac_disable:
+                case A_fake_root_uid:
+                case A_audit_uid:
+                case A_auid_exempt:
+                case A_remote_ip:
+                case A_vset:
+                case A_program_file:
+                  if (!rsbac_acl_check_right(target, tid, owner, caller_pid, request))
+                    return NOT_GRANTED;
+                  else
+                    return GRANTED;
+                #endif
+
+                /* Only protect UDF, if asked to by configuration */
+                #ifdef CONFIG_RSBAC_ACL_UDF_PROT
+		case A_udf_role:
+		case A_udf_checker:
+		case A_udf_checked:
+		case A_udf_do_check:
+                  tid.scd = AST_udf_administration;
+                  if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                #endif
+
+                #ifdef CONFIG_RSBAC_ACL_LEARN
+                case A_acl_learn:
+                  /* check supervisor on target */
+                  if(rsbac_acl_check_super(target,
+                                           tid,
+                                           owner))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                #endif
+
+                /* All attributes (remove target!) */
+                case A_none:
+                  if (!rsbac_acl_check_right(target, tid, owner, caller_pid, request))
+                    return NOT_GRANTED;
+                  #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
+                  tid.scd = AST_auth_administration;
+                  if (!rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
+                    return NOT_GRANTED;
+                  #endif
+                  #ifdef CONFIG_RSBAC_ACL_UDF_PROT
+                  tid.scd = AST_udf_administration;
+                  if (!rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
+                    return NOT_GRANTED;
+                  #endif
+                  return GRANTED;
+
+                default:
+                  return DO_NOT_CARE;
+              }
+
+        case R_SWITCH_MODULE:
+            switch(target)
+              {
+                case T_NONE:
+                    if(   (attr_val.switch_target != SW_ACL)
+                       #ifdef CONFIG_RSBAC_SOFTMODE
+                       && (attr_val.switch_target != SW_SOFTMODE)
+                       #endif
+                       #ifdef CONFIG_RSBAC_FREEZE
+                       && (attr_val.switch_target != SW_FREEZE)
+                       #endif
+                       #ifdef CONFIG_RSBAC_ACL_AUTH_PROT
+                       && (attr_val.switch_target != SW_AUTH)
+                       #endif
+                       #ifdef CONFIG_RSBAC_ACL_UDF_PROT
+                       && (attr_val.switch_target != SW_UDF)
+                       #endif
+                      )
+                      return DO_NOT_CARE;
+
+                    tid.scd = ST_other;
+                    if (rsbac_acl_check_right(T_SCD, tid, owner, caller_pid, request))
+                      return GRANTED;
+                    else
+                      return NOT_GRANTED;
+
+                /* all other cases are unknown */
+                default:
+                  return DO_NOT_CARE;
+              }
+
+/*********************/
+        default:
+          if(target == T_NONE)
+            {
+              target = T_SCD;
+              tid.scd = ST_other;
+            }
+          if (rsbac_acl_check_right(target, tid, owner, caller_pid, request))
+            return GRANTED;
+          else
+            return NOT_GRANTED;
+      }
+  } /* end of rsbac_adf_request_acl() */
+
+/* end of rsbac/adf/acl/main.c */
diff --git a/rsbac/adf/acl/acl_syscalls.c b/rsbac/adf/acl/acl_syscalls.c
new file mode 100644
index 0000000..9aface0
--- /dev/null
+++ b/rsbac/adf/acl/acl_syscalls.c
@@ -0,0 +1,1699 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - ACL module                       */
+/* File: rsbac/adf/acl/syscalls.c                    */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/error.h>
+#include <rsbac/acl.h>
+#include <rsbac/getname.h>
+#include <rsbac/acl_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/debug.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/adf_main.h>
+#ifdef CONFIG_RSBAC_NET_OBJ
+#include <net/sock.h>
+#endif
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+rsbac_boolean_t rsbac_acl_check_super(enum  rsbac_target_t target,
+                              union rsbac_target_id_t tid,
+                                    rsbac_uid_t user)
+{
+    rsbac_boolean_t                   i_result = FALSE;
+    int                       err=0, tmperr;
+    int                       i;
+    rsbac_acl_group_id_t    * group_p;
+    #if defined(CONFIG_RSBAC_RC)
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    #endif
+
+    /* Only check implemented targets */
+    switch(target)
+      {
+        case T_FILE:
+        case T_DIR:
+        case T_FIFO:
+        case T_SYMLINK:
+        case T_DEV:
+        case T_IPC:
+        case T_SCD:
+        case T_USER:
+        case T_PROCESS:
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+        case T_GROUP:
+#endif
+        case T_NETDEV:
+        case T_NETTEMP_NT:
+        case T_NETTEMP:
+        case T_NETOBJ:
+          break;
+        default:
+          return TRUE;
+      }
+    /* own right */
+    err = rsbac_acl_get_single_right(target,
+                                     tid,
+                                     ACLS_USER,
+                                     (rsbac_acl_subject_id_t) user,
+                                     ACLR_SUPERVISOR,
+                                     &i_result);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_super(): rsbac_acl_get_single_right() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return FALSE;
+      }
+    if(i_result)
+      return(TRUE);
+
+    /* try SUPERVISOR for group and role */
+    /* group everyone */
+    err = rsbac_acl_get_single_right(target,
+                                     tid,
+                                     ACLS_GROUP,
+                                     RSBAC_ACL_GROUP_EVERYONE,
+                                     ACLR_SUPERVISOR,
+                                     &i_result);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_super(): rsbac_acl_get_single_right() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return FALSE;
+      }
+    if(i_result)
+      return(TRUE);
+
+    #if defined(CONFIG_RSBAC_RC)
+    /* use process role */
+    /* first get role */
+    i_tid.process = task_pid(current);
+    if (rsbac_get_attr(SW_RC,
+                       T_PROCESS,
+                       i_tid,
+                       A_rc_role,
+                       &i_attr_val1,
+                       FALSE))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_acl_check_super(): rsbac_get_attr() for process rc_role returned error!\n");
+      }
+    else
+      {
+        err = rsbac_acl_get_single_right(target,
+                                         tid,
+                                         ACLS_ROLE,
+                                         i_attr_val1.rc_role,
+                                         ACLR_SUPERVISOR,
+                                         &i_result);
+        if(err)
+          {
+            char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                get_error_name(tmp,err);
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_check_super(): rsbac_acl_get_single_right() returned error %s!\n",
+                       tmp);
+                rsbac_kfree(tmp);
+              }
+            return FALSE;
+          }
+        if(i_result)
+          return(TRUE);
+      }
+    #endif
+
+    /* other groups */
+    /* first get user groups */
+    group_p = NULL;
+    err = rsbac_acl_get_user_groups(0, user, &group_p, NULL);
+    if(err<0)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_check_super(): rsbac_acl_get_user_groups() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+        return err;
+      }
+    for(i=0; i<err; i++)
+      {
+        tmperr = rsbac_acl_get_single_right(target,
+                                            tid,
+                                            ACLS_GROUP,
+                                            group_p[i],
+                                            ACLR_SUPERVISOR,
+                                            &i_result);
+        if(tmperr)
+          {
+            char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_check_super(): rsbac_acl_get_single_right() returned error %s!\n",
+                       get_error_name(tmp,tmperr));
+                rsbac_kfree(tmp);
+              }
+            if(group_p)
+              rsbac_kfree(group_p);
+            return FALSE;
+          }
+        if(i_result)
+          {
+            if(group_p)
+              rsbac_kfree(group_p);
+            return(TRUE);
+          }
+      }
+    if(group_p)
+      rsbac_kfree(group_p);
+
+    /* give up */
+    return FALSE;
+}
+
+
+rsbac_boolean_t rsbac_acl_check_forward(enum  rsbac_target_t target,
+                                union rsbac_target_id_t tid,
+                                      rsbac_uid_t user,
+                                      rsbac_acl_rights_vector_t rights);
+
+rsbac_boolean_t rsbac_acl_check_super(enum  rsbac_target_t target,
+                              union rsbac_target_id_t tid,
+                                    rsbac_uid_t user);
+
+rsbac_boolean_t rsbac_acl_check_right(enum  rsbac_target_t target,
+                              union rsbac_target_id_t tid,
+                                    rsbac_uid_t user,
+                                    rsbac_pid_t caller_pid,
+                              enum  rsbac_adf_request_t request);
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+int rsbac_acl_sys_set_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t   rights,
+         rsbac_time_t                ttl)
+  {
+    int err=0;
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+      /* sanity check before using pointer */
+      if(   (target == T_NETOBJ)
+         && tid.netobj.sock_p
+         && (   tid.netobj.remote_addr
+             || !tid.netobj.sock_p->file
+             || !tid.netobj.sock_p->file->f_path.dentry
+             || !tid.netobj.sock_p->file->f_path.dentry->d_inode
+             || (SOCKET_I(tid.netobj.sock_p->file->f_path.dentry->d_inode) != tid.netobj.sock_p)
+            )
+        )
+        return -RSBAC_EINVALIDTARGET;
+#endif
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        rsbac_uid_t user;
+
+        if(rsbac_get_owner(&user))
+          return -RSBAC_EREADFAILED;
+        /* first try access control right (SUPERVISOR try is included) */
+        if(!rsbac_acl_check_right(target, tid, user, task_pid(current), ACLR_ACCESS_CONTROL))
+          {
+            /* no access control -> try forward for these rights */
+            /* but only, if no ttl requested */
+            if(   (ttl != RSBAC_LIST_TTL_KEEP)
+               || !rsbac_acl_check_forward(target, tid, user, rights)
+              )
+              {
+                char * rights_string = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                char * target_id_name
+                  = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                /* max. path name len + some extra */
+                #else
+                char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+                /* max. file name len + some extra */
+                #endif
+
+                u64tostracl(rights_string, rights);
+                get_acl_subject_type_name(subject_type_name, subj_type);
+                get_target_name(target_type_name, target, target_id_name, tid);
+                rsbac_printk(KERN_INFO
+                       "rsbac_acl_sys_set_acl_entry(): setting rights %s for %s %u to %s %s denied for user %u!\n",
+                       rights_string,
+                       subject_type_name,
+                       subj_id,
+                       target_type_name,
+                       target_id_name,
+                       user);
+                rsbac_kfree(rights_string);
+                rsbac_kfree(subject_type_name);
+                rsbac_kfree(target_type_name);
+                rsbac_kfree(target_id_name);
+
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_ACL]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+          }
+        if(rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
+          {
+            /* you must have SUPERVISOR to set SUPERVISOR */
+            if(!rsbac_acl_check_super(target, tid, user))
+              {
+                char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                char * target_id_name
+                  = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                /* max. path name len + some extra */
+                #else
+                char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+                /* max. file name len + some extra */
+                #endif
+
+                get_acl_subject_type_name(subject_type_name, subj_type);
+                get_target_name(target_type_name, target, target_id_name, tid);
+                rsbac_printk(KERN_INFO
+                       "rsbac_acl_sys_set_acl_entry(): setting SUPERVISOR for %s %u to %s %s denied for user %u!\n",
+                       subject_type_name,
+                       subj_id,
+                       target_type_name,
+                       target_id_name,
+                       user);
+                rsbac_kfree(subject_type_name);
+                rsbac_kfree(target_type_name);
+                rsbac_kfree(target_id_name);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_ACL]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+          }
+      }
+
+    /* OK, check passed. Set ACL. */
+    err = rsbac_acl_set_acl_entry(ta_number, target, tid, subj_type, subj_id, rights, ttl);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_set_acl_entry(): rsbac_acl_set_acl_entry() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_remove_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id)
+  {
+    int err=0;
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+      /* sanity check before using pointer */
+      if(   (target == T_NETOBJ)
+         && tid.netobj.sock_p
+         && (   tid.netobj.remote_addr
+             || !tid.netobj.sock_p->file
+             || !tid.netobj.sock_p->file->f_path.dentry
+             || !tid.netobj.sock_p->file->f_path.dentry->d_inode
+             || (SOCKET_I(tid.netobj.sock_p->file->f_path.dentry->d_inode) != tid.netobj.sock_p)
+            )
+        )
+        return -RSBAC_EINVALIDTARGET;
+#endif
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        rsbac_uid_t user;
+        rsbac_acl_rights_vector_t res_rights = 0;
+
+        if(rsbac_get_owner(&user))
+          return -RSBAC_EREADFAILED;
+        /* first try access control right (SUPERVISOR is included) */
+        if(!rsbac_acl_check_right(target, tid, user, task_pid(current), ACLR_ACCESS_CONTROL))
+          {
+            char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+            char * target_id_name
+              = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+            /* max. path name len + some extra */
+            #else
+            char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+            /* max. file name len + some extra */
+            #endif
+
+            get_acl_subject_type_name(subject_type_name, subj_type);
+            get_target_name(target_type_name, target, target_id_name, tid);
+            rsbac_printk(KERN_INFO
+                   "rsbac_acl_sys_remove_acl_entry(): removing ACL entry for %s %u at %s %s denied for user %u!\n",
+                   subject_type_name,
+                   subj_id,
+                   target_type_name,
+                   target_id_name,
+                   user);
+            rsbac_kfree(subject_type_name);
+            rsbac_kfree(target_type_name);
+            rsbac_kfree(target_id_name);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_ACL]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+
+        err = rsbac_acl_get_rights(0, target, tid, subj_type, subj_id, &res_rights, FALSE);
+        if(err)
+          {
+            char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_sys_remove_acl_entry(): rsbac_acl_get_rights() returned error %s!\n",
+                       get_error_name(tmp,err));
+                rsbac_kfree(tmp);
+              }
+            return err;
+          }
+        if(res_rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
+          {
+            /* you must have SUPERVISOR to remove an entry with SUPERVISOR */
+            if(!rsbac_acl_check_super(target, tid, user))
+              {
+                char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                char * target_id_name
+                  = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                /* max. path name len + some extra */
+                #else
+                char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+                /* max. file name len + some extra */
+                #endif
+
+                get_acl_subject_type_name(subject_type_name, subj_type);
+                get_target_name(target_type_name, target, target_id_name, tid);
+                rsbac_printk(KERN_INFO
+                       "rsbac_acl_sys_remove_acl_entry(): removing ACL entry with SUPERVISOR for %s %u at %s %s denied for user %u!\n",
+                       subject_type_name,
+                       subj_id,
+                       target_type_name,
+                       target_id_name,
+                       user);
+                rsbac_kfree(subject_type_name);
+                rsbac_kfree(target_type_name);
+                rsbac_kfree(target_id_name);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_ACL]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+               }
+           }
+      }
+
+    /* OK, check passed. Set ACL. */
+    err = rsbac_acl_remove_acl_entry(ta_number, target, tid, subj_type, subj_id);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_remove_acl_entry(): rsbac_acl_remove_acl_entry() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_remove_acl(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid)
+  {
+    int err=0;
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        rsbac_uid_t user;
+
+        if(rsbac_get_owner(&user))
+          return -RSBAC_EREADFAILED;
+        /* check SUPERVISOR */
+        if(!rsbac_acl_check_super(target, tid, user))
+          {
+            char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+            char * target_id_name
+              = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+            /* max. path name len + some extra */
+            #else
+            char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+            /* max. file name len + some extra */
+            #endif
+
+            get_target_name(target_type_name, target, target_id_name, tid);
+            rsbac_printk(KERN_INFO
+                   "rsbac_acl_sys_remove_acl(): removing ACL from %s %s denied for user %u!\n",
+                   target_type_name,
+                   target_id_name,
+                   user);
+            rsbac_kfree(target_type_name);
+            rsbac_kfree(target_id_name);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_ACL]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    /* OK, check passed. Set ACL. */
+    err = rsbac_acl_remove_acl(ta_number, target, tid);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_remove_acl(): rsbac_acl_remove_acl() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_add_to_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t   rights,
+         rsbac_time_t                ttl)
+  {
+    int err=0;
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+      /* sanity check before using pointer */
+      if(   (target == T_NETOBJ)
+         && tid.netobj.sock_p
+         && (   tid.netobj.remote_addr
+             || !tid.netobj.sock_p->file
+             || !tid.netobj.sock_p->file->f_path.dentry
+             || !tid.netobj.sock_p->file->f_path.dentry->d_inode
+             || (SOCKET_I(tid.netobj.sock_p->file->f_path.dentry->d_inode) != tid.netobj.sock_p)
+            )
+        )
+        return -RSBAC_EINVALIDTARGET;
+#endif
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        rsbac_uid_t user;
+
+        if(rsbac_get_owner(&user))
+          return -RSBAC_EREADFAILED;
+        /* first try access control right (SUPERVISOR is included) */
+        if(!rsbac_acl_check_right(target, tid, user, task_pid(current), ACLR_ACCESS_CONTROL))
+          {
+            /* no access control -> try forward for these rights */
+            /* but only, if no ttl requested */
+            if(   (ttl != RSBAC_LIST_TTL_KEEP)
+               || !rsbac_acl_check_forward(target, tid, user, rights)
+              )
+              {
+                char * rights_string = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                char * target_id_name
+                  = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                /* max. path name len + some extra */
+                #else
+                char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+                /* max. file name len + some extra */
+                #endif
+
+                u64tostracl(rights_string, rights);
+                get_acl_subject_type_name(subject_type_name, subj_type);
+                get_target_name(target_type_name, target, target_id_name, tid);
+                rsbac_printk(KERN_INFO
+                       "rsbac_acl_sys_add_to_acl_entry(): adding rights %s for %s %u to %s %s denied for user %u!\n",
+                       rights_string,
+                       subject_type_name,
+                       subj_id,
+                       target_type_name,
+                       target_id_name,
+                       user);
+                rsbac_kfree(rights_string);
+                rsbac_kfree(subject_type_name);
+                rsbac_kfree(target_type_name);
+                rsbac_kfree(target_id_name);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_ACL]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+          }
+        if(rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
+          {
+            /* you must have SUPERVISOR to add SUPERVISOR */
+            if(!rsbac_acl_check_super(target, tid, user))
+              {
+                char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                char * target_id_name
+                  = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                /* max. path name len + some extra */
+                #else
+                char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+                /* max. file name len + some extra */
+                #endif
+
+                get_acl_subject_type_name(subject_type_name, subj_type);
+                get_target_name(target_type_name, target, target_id_name, tid);
+                rsbac_printk(KERN_INFO
+                       "rsbac_acl_sys_add_to_acl_entry(): adding SUPERVISOR for %s %u to %s %s denied for user %u!\n",
+                       subject_type_name,
+                       subj_id,
+                       target_type_name,
+                       target_id_name,
+                       user);
+                rsbac_kfree(subject_type_name);
+                rsbac_kfree(target_type_name);
+                rsbac_kfree(target_id_name);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_ACL]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+          }
+      }
+
+    /* OK, check passed. Set ACL. */
+    err = rsbac_acl_add_to_acl_entry(ta_number, target, tid, subj_type, subj_id, rights, ttl);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_add_to_acl_entry(): rsbac_acl_add_to_acl_entry() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_remove_from_acl_entry(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t   rights)
+  {
+    int err=0;
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+      /* sanity check before using pointer */
+      if(   (target == T_NETOBJ)
+         && tid.netobj.sock_p
+         && (   tid.netobj.remote_addr
+             || !tid.netobj.sock_p->file
+             || !tid.netobj.sock_p->file->f_path.dentry
+             || !tid.netobj.sock_p->file->f_path.dentry->d_inode
+             || (SOCKET_I(tid.netobj.sock_p->file->f_path.dentry->d_inode) != tid.netobj.sock_p)
+            )
+        )
+        return -RSBAC_EINVALIDTARGET;
+#endif
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        rsbac_uid_t user;
+
+        if(rsbac_get_owner(&user))
+          return -RSBAC_EREADFAILED;
+        /* first try access control right (SUPERVISOR is included) */
+        if(!rsbac_acl_check_right(target, tid, user, task_pid(current), ACLR_ACCESS_CONTROL))
+          {
+            char * rights_string = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+            char * target_id_name
+              = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+            /* max. path name len + some extra */
+            #else
+            char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+            /* max. file name len + some extra */
+            #endif
+
+            u64tostracl(rights_string, rights);
+            get_acl_subject_type_name(subject_type_name, subj_type);
+            get_target_name(target_type_name, target, target_id_name, tid);
+            rsbac_printk(KERN_INFO
+                   "rsbac_acl_sys_remove_from_acl_entry(): removing rights %s for %s %u to %s %s denied for user %u!\n",
+                   rights_string,
+                   subject_type_name,
+                   subj_id,
+                   target_type_name,
+                   target_id_name,
+                   user);
+            rsbac_kfree(rights_string);
+            rsbac_kfree(subject_type_name);
+            rsbac_kfree(target_type_name);
+            rsbac_kfree(target_id_name);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_ACL]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+        if(rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
+          {
+            /* you must have SUPERVISOR to revoke SUPERVISOR */
+            if(!rsbac_acl_check_super(target, tid, user))
+              {
+                char * subject_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+                #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+                char * target_id_name
+                  = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+                /* max. path name len + some extra */
+                #else
+                char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+                /* max. file name len + some extra */
+                #endif
+
+                get_acl_subject_type_name(subject_type_name, subj_type);
+                get_target_name(target_type_name, target, target_id_name, tid);
+                rsbac_printk(KERN_INFO
+                       "rsbac_acl_sys_remove_from_acl_entry(): removing SUPERVISOR for %s %u to %s %s denied for user %u!\n",
+                       subject_type_name,
+                       subj_id,
+                       target_type_name,
+                       target_id_name,
+                       user);
+                rsbac_kfree(subject_type_name);
+                rsbac_kfree(target_type_name);
+                rsbac_kfree(target_id_name);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_ACL]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+          }
+      }
+
+    /* OK, check passed. Remove ACL. */
+    err = rsbac_acl_remove_from_acl_entry(ta_number, target, tid, subj_type, subj_id, rights);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_remove_from_acl_entry(): rsbac_acl_remove_from_acl_entry() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_set_mask(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+         rsbac_acl_rights_vector_t   mask)
+  {
+    int err=0;
+
+    rsbac_uid_t user;
+
+    if(rsbac_get_owner(&user))
+      return -RSBAC_EREADFAILED;
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+      /* sanity check before using pointer */
+      if(   (target == T_NETOBJ)
+         && tid.netobj.sock_p
+         && (   tid.netobj.remote_addr
+             || !tid.netobj.sock_p->file
+             || !tid.netobj.sock_p->file->f_path.dentry
+             || !tid.netobj.sock_p->file->f_path.dentry->d_inode
+             || (SOCKET_I(tid.netobj.sock_p->file->f_path.dentry->d_inode) != tid.netobj.sock_p)
+            )
+        )
+        return -RSBAC_EINVALIDTARGET;
+#endif
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        /* first try access control right (SUPERVISOR is included) */
+        if(!rsbac_acl_check_right(target, tid, user, task_pid(current), ACLR_ACCESS_CONTROL))
+          {
+            char * rights_string = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            char * target_type_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+            #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+            char * target_id_name
+              = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+            /* max. path name len + some extra */
+            #else
+            char * target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+            /* max. file name len + some extra */
+            #endif
+
+            u64tostracl(rights_string, mask);
+            get_target_name(target_type_name, target, target_id_name, tid);
+            rsbac_printk(KERN_INFO
+                         "rsbac_acl_sys_set_mask(): setting mask %s for %s %s denied for user %u!\n",
+                         rights_string,
+                         target_type_name,
+                         target_id_name,
+                         user);
+            rsbac_kfree(rights_string);
+            rsbac_kfree(target_type_name);
+            rsbac_kfree(target_id_name);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_ACL]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+#ifdef CONFIG_RSBAC_ACL_SUPER_FILTER
+    if(!(mask & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR))
+      { /* trial to mask out SUPERVISOR */
+        rsbac_acl_rights_vector_t res_rights = 0;
+
+        /* you must have direct SUPERVISOR as a USER to set a mask without SUPERVISOR */
+        /* get direct own rights (still uses default_fd_rights) */
+        err = rsbac_acl_get_rights(0, target, tid, ACLS_USER, user, &res_rights, FALSE);
+        if(err)
+          return -RSBAC_EREADFAILED;
+        if(!(res_rights & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR))
+          mask |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
+      }
+#else
+    /* SUPERVISOR must never be masked out */
+    mask |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
+#endif
+
+    /* OK, checks passed. Set mask. */
+    err = rsbac_acl_set_mask(ta_number, target, tid, mask);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_set_mask(): rsbac_acl_set_mask() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_remove_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid)
+  {
+    int err=0;
+
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+    if(rsbac_switch_acl)
+#endif
+      {
+        rsbac_uid_t user;
+        union rsbac_target_id_t tid;
+
+        if(rsbac_get_owner(&user))
+          return -RSBAC_EREADFAILED;
+        tid.user = uid;
+        /* first try access control right (SUPERVISOR is included) */
+        if(!rsbac_acl_check_right(T_USER, tid, user, task_pid(current), R_DELETE))
+          {
+            rsbac_printk(KERN_INFO
+                         "rsbac_acl_sys_remove_user(): removing all data for user %u denied for user %u!\n",
+                         uid,
+                         user);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_ACL]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    rsbac_printk(KERN_INFO
+                 "rsbac_acl_sys_remove_user(): removing all data for user %u!\n",
+                 uid);
+    /* OK, checks passed. Set mask. */
+    err = rsbac_acl_remove_user(ta_number, uid);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_remove_user(): rsbac_acl_remove_user() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+/*********/
+
+int rsbac_acl_sys_get_mask(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+         rsbac_acl_rights_vector_t * mask_p)
+  {
+    int err=0;
+
+/* no check */
+
+    /* OK, check passed. Get mask. */
+    err = rsbac_acl_get_mask(ta_number, target, tid, mask_p);
+    if(err)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_acl_sys_get_mask(): rsbac_acl_get_mask() returned error %s!\n",
+                   get_error_name(tmp,err));
+            rsbac_kfree(tmp);
+          }
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_get_rights(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t           tid,
+  enum   rsbac_acl_subject_type_t    subj_type,
+         rsbac_acl_subject_id_t      subj_id,
+         rsbac_acl_rights_vector_t * rights_p,
+         rsbac_boolean_t                     effective)
+  {
+    int err=0;
+    rsbac_acl_rights_vector_t res_rights;
+    #if defined(CONFIG_RSBAC_RC)
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    #endif
+
+    /* no check (Attention: rsbac_acl_check_forward depends on this to be allowed!) */
+
+    if(   (subj_type == ACLS_USER)
+       && (subj_id == RSBAC_NO_USER)
+      )
+      rsbac_get_owner((rsbac_uid_t *) &subj_id);
+    /* OK, check passed. Call ACL. */
+    if(effective)
+      {
+        /* inherited own rights */
+        res_rights = 0;
+        err = rsbac_acl_get_rights(ta_number, target, tid, subj_type, subj_id, &res_rights, TRUE);
+        if(err)
+          {
+            char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
+                       get_error_name(tmp,err));
+                rsbac_kfree(tmp);
+              }
+            return err;
+          }
+        *rights_p = res_rights;
+        /* add group and role rights, if normal user */
+        if(subj_type == ACLS_USER)
+          {
+            rsbac_acl_group_id_t * group_p;
+            int                    i;
+            int                    tmperr;
+
+            /* group everyone */
+            res_rights = 0;
+            err = rsbac_acl_get_rights(ta_number, target, tid,
+                                       ACLS_GROUP, RSBAC_ACL_GROUP_EVERYONE,
+                                       &res_rights, TRUE);
+            if(err)
+              {
+                char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+                if(tmp)
+                  {
+                    rsbac_printk(KERN_WARNING
+                           "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
+                           get_error_name(tmp,err));
+                    rsbac_kfree(tmp);
+                  }
+                return err;
+              }
+            *rights_p |= res_rights;
+
+            /* other groups */
+            /* first get user groups */
+            group_p = NULL;
+            err = rsbac_acl_get_user_groups(ta_number, subj_id, &group_p, NULL);
+            if(err<0)
+              {
+                char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+                if(tmp)
+                  {
+                    rsbac_printk(KERN_WARNING
+                           "rsbac_acl_sys_get_rights(): rsbac_acl_get_user_groups() returned error %s!\n",
+                           get_error_name(tmp,err));
+                    rsbac_kfree(tmp);
+                  }
+                return err;
+              }
+            for(i=0; i<err; i++)
+              {
+                res_rights = 0;
+                tmperr = rsbac_acl_get_rights(ta_number, target, tid, ACLS_GROUP, group_p[i],
+                                              &res_rights, TRUE);
+                if(tmperr)
+                  {
+                    char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+                    if(tmp)
+                      {
+                        rsbac_printk(KERN_WARNING
+                               "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
+                               get_error_name(tmp,err));
+                        rsbac_kfree(tmp);
+                      }
+                    if(group_p)
+                      rsbac_kfree(group_p);
+                    return tmperr;
+                  }
+                *rights_p |= res_rights;
+              }
+            err = 0;
+            if(group_p)
+              rsbac_kfree(group_p);
+
+            #if defined(CONFIG_RSBAC_RC)
+            /* use user role */
+            /* first get role */
+            i_tid.user = subj_id;
+            if (rsbac_get_attr(SW_RC,
+                               T_USER,
+                               i_tid,
+                               A_rc_def_role,
+                               &i_attr_val1,
+                               FALSE))
+              {
+                rsbac_printk(KERN_WARNING
+                       "rsbac_acl_sys_get_rights(): rsbac_get_attr() for process rc_role returned error!\n");
+              }
+            else
+              {
+                res_rights = 0;
+                err = rsbac_acl_get_rights(ta_number, target, tid,
+                                           ACLS_ROLE, i_attr_val1.rc_role,
+                                           &res_rights, TRUE);
+                if(err)
+                  {
+                    char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+                    if(tmp)
+                      {
+                        get_error_name(tmp,err);
+                        rsbac_printk(KERN_WARNING
+                               "rsbac_acl_sys_get_rights(): rsbac_acl_get_rights() returned error %s!\n",
+                               tmp);
+                        rsbac_kfree(tmp);
+                      }
+                    return err;
+                  }
+                *rights_p |= res_rights;
+              }
+            #endif
+
+            /* check for SUPERVISOR right, if not yet there */
+            if(   !(*rights_p & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR)
+               && rsbac_acl_check_super(target, tid, subj_id)
+              )
+              *rights_p |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
+          }
+        else /* not ACLS_USER */
+          {
+            if(!(*rights_p & RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR))
+              {
+                rsbac_boolean_t i_result = FALSE;
+
+                /* check for SUPERVISOR right */
+                /* own right */
+                err = rsbac_acl_get_single_right(target,
+                                                 tid,
+                                                 subj_type,
+                                                 subj_id,
+                                                 ACLR_SUPERVISOR,
+                                                 &i_result);
+                if(err)
+                  {
+                    char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+                    if(tmp)
+                      {
+                        rsbac_printk(KERN_WARNING
+                               "rsbac_acl_sys_get_rights(): rsbac_acl_get_right() returned error %s!\n",
+                               get_error_name(tmp,err));
+                        rsbac_kfree(tmp);
+                      }
+                  }
+                else
+                  if(i_result)
+                    *rights_p |= RSBAC_ACL_SUPERVISOR_RIGHT_VECTOR;
+              }
+          }
+      }
+    else /* not effective = direct */
+      {
+        /* direct own rights (still uses default_fd_rights) */
+        res_rights = 0;
+        err = rsbac_acl_get_rights(ta_number, target, tid, subj_type, subj_id, &res_rights, FALSE);
+        if(!err)
+          *rights_p = res_rights;
+      }
+    return err;
+  }
+
+int rsbac_acl_sys_get_tlist(
+         rsbac_list_ta_number_t    ta_number,
+  enum   rsbac_target_t            target,
+  union  rsbac_target_id_t         tid,
+  struct rsbac_acl_entry_t      ** entry_pp,
+         rsbac_time_t           ** ttl_pp)
+  {
+    int err=0;
+
+    /* no check */
+
+    /* OK, check passed. Call ACL. */
+    err = rsbac_acl_get_tlist(ta_number, target, tid, entry_pp, ttl_pp);
+    if(err == -RSBAC_ENOTFOUND)
+      err = 0;
+    else
+      if(err<0)
+        {
+          char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+          if(tmp)
+            {
+              rsbac_printk(KERN_WARNING
+                     "rsbac_acl_sys_get_tlist(): rsbac_acl_get_tlist() returned error %s!\n",
+                     get_error_name(tmp,err));
+              rsbac_kfree(tmp);
+            }
+        }
+    return err;
+  }
+
+/*********** Groups ***********/
+
+int rsbac_acl_sys_group(
+        rsbac_list_ta_number_t         ta_number,
+  enum  rsbac_acl_group_syscall_type_t call,
+  union rsbac_acl_group_syscall_arg_t  arg)
+  {
+    int err = -RSBAC_EINVALIDREQUEST;
+    struct filename * k_name;
+    rsbac_acl_group_id_t k_group;
+    struct rsbac_acl_group_entry_t entry;
+    rsbac_uid_t caller;
+
+    if(call >= ACLGS_none)
+      return -RSBAC_EINVALIDREQUEST;
+    if(rsbac_get_owner(&caller))
+      return -RSBAC_EREADFAILED;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if(rsbac_debug_aef_acl)
+      {
+        char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+        if(tmp)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_acl_sys_group(): %s called\n",
+                   get_acl_group_syscall_name(tmp,call));
+            rsbac_kfree(tmp);
+          }
+      }
+#endif
+    
+    switch(call)
+      {
+        case ACLGS_add_group:
+          if(arg.add_group.type >= ACLG_NONE)
+            {
+              err = -RSBAC_EINVALIDVALUE;
+              break;
+            }
+          k_name = rsbac_getname(arg.add_group.name);
+          if(!k_name)
+            {
+              err = -RSBAC_EINVALIDVALUE;
+              break;
+            }
+          err = rsbac_get_user(&k_group, arg.add_group.group_id_p, sizeof(k_group));
+          if(err)
+            break;
+          err = rsbac_acl_add_group(ta_number,
+                                    caller,
+                                    arg.add_group.type,
+                                    k_name->name,
+                                    &k_group);
+          rsbac_putname(k_name);
+          if(!err)
+            err = rsbac_put_user(&k_group, arg.add_group.group_id_p, sizeof(k_group));
+          break;
+
+        case ACLGS_change_group:
+          if(arg.change_group.type >= ACLG_NONE)
+            {
+              err = -RSBAC_EINVALIDVALUE;
+              break;
+            }
+          err = rsbac_acl_get_group_entry(ta_number, arg.change_group.id, &entry);
+          if(err)
+            break;
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+          if(rsbac_switch_acl)
+#endif
+            {
+              if(entry.owner != caller)
+                {
+                  rsbac_printk(KERN_INFO
+                               "rsbac_acl_group(): changing group %u denied for user %u - not owner!\n",
+                               entry.id,
+                               caller);
+                  err = -EPERM;
+                  break;
+                }
+            }
+          {
+            struct filename * k_name;
+
+            k_name = rsbac_getname(arg.change_group.name);
+            if(k_name)
+              {
+                err = rsbac_acl_change_group(ta_number,
+                                             arg.change_group.id,
+                                             arg.change_group.owner,
+                                             arg.change_group.type,
+                                             k_name->name);
+                putname(k_name);
+              }
+            else
+              err = -RSBAC_EINVALIDVALUE;
+          }
+          break;
+
+        case ACLGS_remove_group:
+          err = rsbac_acl_get_group_entry(ta_number, arg.remove_group.id, &entry);
+          if(err)
+            break;
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+          if(rsbac_switch_acl)
+#endif
+            {
+              if(entry.owner != caller)
+                {
+                  rsbac_printk(KERN_INFO
+                               "rsbac_acl_group(): removing group %u denied for user %u - not owner!\n",
+                               entry.id,
+                               caller);
+                  err = -EPERM;
+                  break;
+                }
+            }
+          err = rsbac_acl_remove_group(ta_number, arg.remove_group.id);
+          break;
+
+        case ACLGS_get_group_entry:
+          if(!arg.get_group_entry.entry_p)
+            {
+              err = -RSBAC_EINVALIDPOINTER;
+              break;
+            }
+          if(!arg.get_group_entry.id)
+            { /* Everyone -> fill by hand */
+              entry.id=0;
+              entry.owner=RSBAC_NO_USER;
+              entry.type=ACLG_GLOBAL;
+              strcpy(entry.name, "Everyone");
+              err=0;
+            }
+          else
+            {
+              err = rsbac_acl_get_group_entry(ta_number,
+                                              arg.get_group_entry.id,
+                                              &entry);
+            }
+          if(!err)
+            {
+              if(  (entry.owner != caller)
+                 &&(entry.type != ACLG_GLOBAL)
+                )
+                {
+                  rsbac_printk(KERN_INFO
+                               "rsbac_acl_group(): getting group entry %u denied for user %u - neither owner nor global!\n",
+                               entry.id,
+                               caller);
+                  err = -EPERM;
+                }
+              else
+                err = rsbac_put_user(&entry, arg.get_group_entry.entry_p, sizeof(entry));
+            }
+          break;
+
+        case ACLGS_list_groups:
+          if(arg.list_groups.maxnum <= 0)
+            {
+              err = -RSBAC_EINVALIDVALUE;
+              break;
+            }
+          if(!arg.list_groups.group_entry_array)
+            {
+              err = -RSBAC_EINVALIDPOINTER;
+              break;
+            }
+          {
+            struct rsbac_acl_group_entry_t * entry_p;
+            int tmperr=0;
+
+            if(arg.list_groups.include_global)
+              {
+                struct rsbac_acl_group_entry_t   entry_0;
+
+                entry_0.id=0;
+                entry_0.owner=RSBAC_NO_USER;
+                entry_0.type=ACLG_GLOBAL;
+                strcpy(entry_0.name, "Everyone");
+                tmperr = rsbac_put_user(&entry_0,
+                                        arg.list_groups.group_entry_array,
+                                        sizeof(entry_0));
+                if(tmperr)
+                  {
+                    err = tmperr;
+                    break;
+                  }
+                else
+                  err = 1;
+                arg.list_groups.maxnum--;
+                arg.list_groups.group_entry_array++;
+              }
+            else
+              err = 0;
+
+            if(arg.list_groups.maxnum)
+              {
+                long count;
+
+                count = rsbac_acl_list_groups(ta_number,
+                                              caller,
+                                              arg.list_groups.include_global,
+                                              &entry_p);
+                if(count>0)
+                  {
+                    if(count > arg.list_groups.maxnum)
+                      count = arg.list_groups.maxnum;
+                    err+=count;
+                    tmperr = rsbac_put_user(entry_p,
+                                            arg.list_groups.group_entry_array,
+                                            count * sizeof(*entry_p));
+                    if(tmperr)
+                      err=tmperr;
+                    rsbac_kfree(entry_p);
+                  }
+                else
+                  if(count < 0)
+                    err=count;
+              }
+          }
+          break;
+
+        case ACLGS_add_member:
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+          if(rsbac_switch_acl)
+#endif
+            {
+              err = rsbac_acl_get_group_entry(ta_number, arg.add_member.group, &entry);
+              if(err)
+                break;
+              if(entry.owner != caller)
+                {
+                  rsbac_printk(KERN_INFO
+                               "rsbac_acl_group(): adding group member to group %u denied for user %u - not owner!\n",
+                               entry.id,
+                               caller);
+                  err = -EPERM;
+                  break;
+                }
+            }
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_UID_SET(arg.add_member.user) == RSBAC_UM_VIRTUAL_KEEP)
+            arg.add_member.user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(arg.add_member.user));
+          else
+            if (RSBAC_UID_SET(arg.add_member.user) > RSBAC_UM_VIRTUAL_MAX)
+              return -RSBAC_EINVALIDVALUE;
+#else
+          arg.add_member.user = RSBAC_UID_NUM(arg.add_member.user);
+#endif
+          err = rsbac_acl_add_group_member(ta_number,
+                                           arg.add_member.group,
+                                           arg.add_member.user,
+                                           arg.add_member.ttl);
+          break;
+
+        case ACLGS_remove_member:
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+          if(rsbac_switch_acl)
+#endif
+            {
+              err = rsbac_acl_get_group_entry(ta_number, arg.remove_member.group, &entry);
+              if(err)
+                break;
+              if(entry.owner != caller)
+                {
+                  rsbac_printk(KERN_INFO
+                               "rsbac_acl_group(): removing group member from group %u denied for user %u - not owner!\n",
+                               entry.id,
+                               caller);
+                  err = -EPERM;
+                  break;
+                }
+            }
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_UID_SET(arg.remove_member.user) == RSBAC_UM_VIRTUAL_KEEP)
+            arg.remove_member.user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(arg.remove_member.user));
+          else
+            if (RSBAC_UID_SET(arg.remove_member.user) > RSBAC_UM_VIRTUAL_MAX)
+              return -RSBAC_EINVALIDVALUE;
+#else
+          arg.remove_member.user = RSBAC_UID_NUM(arg.remove_member.user);
+#endif
+          err = rsbac_acl_remove_group_member(ta_number, arg.remove_member.group, arg.remove_member.user);
+          break;
+
+        case ACLGS_get_user_groups:
+          {
+            rsbac_acl_group_id_t * group_p = NULL;
+            rsbac_time_t * ttl_p = NULL;
+
+            if(arg.get_user_groups.maxnum <= 0)
+              {
+                err = -RSBAC_EINVALIDVALUE;
+                break;
+              }
+            if(!arg.get_user_groups.group_array)
+              {
+                err = -RSBAC_EINVALIDPOINTER;
+                break;
+              }
+            if(arg.get_user_groups.user == RSBAC_NO_USER)
+              arg.get_user_groups.user = caller;
+            else
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+              if(rsbac_switch_acl)
+#endif
+                {
+                  if(arg.get_user_groups.user != caller)
+                    {
+                      rsbac_printk(KERN_INFO
+                                   "rsbac_acl_group(): getting user groups for user %u denied for user %u!\n",
+                                   arg.get_user_groups.user,
+                                   caller);
+                      err = -EPERM;
+                      break;
+                    }
+                }
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(arg.get_user_groups.user) == RSBAC_UM_VIRTUAL_KEEP)
+              arg.get_user_groups.user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(arg.get_user_groups.user));
+            else
+              if (RSBAC_UID_SET(arg.get_user_groups.user) > RSBAC_UM_VIRTUAL_MAX)
+                return -RSBAC_EINVALIDVALUE;
+#else
+            arg.get_user_groups.user = RSBAC_UID_NUM(arg.get_user_groups.user);
+#endif
+            err = rsbac_acl_get_user_groups(ta_number, arg.get_user_groups.user, &group_p, &ttl_p);
+            if(err>0)
+              {
+                int tmperr;
+
+                err = rsbac_min(err, arg.get_user_groups.maxnum);
+                tmperr = rsbac_put_user(group_p,
+                                        arg.get_user_groups.group_array,
+                                        err * sizeof(*group_p));
+                if(tmperr)
+                  err=tmperr;
+                if(arg.get_user_groups.ttl_array)
+                  {
+                    tmperr = rsbac_put_user(ttl_p,
+                                            arg.get_user_groups.ttl_array,
+                                            err * sizeof(*ttl_p));
+                    if(tmperr)
+                      err=tmperr;
+                  }
+              }
+            if(group_p)
+              rsbac_kfree(group_p);
+            if(ttl_p)
+              rsbac_kfree(ttl_p);
+            break;
+          }
+
+        case ACLGS_get_group_members:
+          if(   (arg.get_group_members.maxnum <= 0)
+             || !arg.get_group_members.group
+            )
+            {
+              err = -RSBAC_EINVALIDVALUE;
+              break;
+            }
+          if(arg.get_group_members.maxnum > RSBAC_ACL_MAX_MAXNUM)
+            arg.get_group_members.maxnum = RSBAC_ACL_MAX_MAXNUM;
+          if(!arg.get_group_members.user_array)
+            {
+              err = -RSBAC_EINVALIDPOINTER;
+              break;
+            }
+          err = rsbac_acl_get_group_entry(ta_number,
+                                          arg.get_group_members.group,
+                                          &entry);
+          if(err)
+            break;
+          if(  (entry.owner != caller)
+             &&(entry.type != ACLG_GLOBAL)
+            )
+            {
+              rsbac_printk(KERN_INFO
+                           "rsbac_acl_group(): getting group members of group %u denied for user %u - neither owner nor global!\n",
+                           entry.id,
+                           caller);
+              err = -EPERM;
+              break;
+            }
+          {
+            rsbac_uid_t * user_array;
+            rsbac_time_t * ttl_array;
+            
+            user_array = rsbac_kmalloc_unlocked(sizeof(*user_array) * arg.get_group_members.maxnum);
+            if(!user_array)
+              return -RSBAC_ENOMEM;
+            ttl_array = rsbac_kmalloc_unlocked(sizeof(*ttl_array) * arg.get_group_members.maxnum);
+            if(!ttl_array)
+              {
+                rsbac_kfree(user_array);
+                return -RSBAC_ENOMEM;
+              }
+
+            err = rsbac_acl_get_group_members(ta_number,
+                                              arg.get_group_members.group,
+                                              user_array,
+                                              ttl_array,
+                                              arg.get_group_members.maxnum);
+            if(err>0)
+              {
+                int tmperr;
+
+                tmperr = rsbac_put_user(user_array,
+                                        arg.get_group_members.user_array,
+                                        err * sizeof(*user_array));
+                if(tmperr)
+                  err=tmperr;
+                if(arg.get_group_members.ttl_array)
+                  {
+                    tmperr = rsbac_put_user(ttl_array,
+                                            arg.get_group_members.ttl_array,
+                                            err * sizeof(*ttl_array));
+                    if(tmperr)
+                      err=tmperr;
+                  }
+              }
+            rsbac_kfree(user_array);
+            rsbac_kfree(ttl_array);
+          }
+          break;
+
+        default:
+          break;
+      }
+    #ifdef CONFIG_RSBAC_SOFTMODE
+    if(   (   rsbac_softmode
+    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+           || rsbac_ind_softmode[SW_ACL]
+    #endif
+          )
+       && (err == -EPERM)
+      )
+      return 0;
+    else
+    #endif
+      return err;
+  }
+/* end of rsbac/adf/acl/syscalls.c */
diff --git a/rsbac/adf/adf_check.c b/rsbac/adf/adf_check.c
new file mode 100644
index 0000000..04685f5
--- /dev/null
+++ b/rsbac/adf/adf_check.c
@@ -0,0 +1,1037 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - check for well defined requests  */
+/* File: rsbac/adf/check.c                           */
+/*                                                   */
+/* Author and (c) 1999-2014: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 10/Feb/2014                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+enum rsbac_adf_req_ret_t
+rsbac_adf_request_check(enum rsbac_adf_request_t request,
+			rsbac_pid_t caller_pid,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t *tid_p,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *attr_val_p,
+			rsbac_uid_t owner)
+{
+	switch (request) {
+	case R_SEARCH:
+		switch (target) {
+		case T_DIR:
+		case T_FILE:
+		case T_SYMLINK:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_NETOBJ:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_CLOSE:		/* only notifying for clean-up of opened-tables */
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+		case T_NETOBJ:
+			return DO_NOT_CARE;
+		default:
+			return UNDEFINED;
+		}
+
+	case R_GET_STATUS_DATA:
+		switch (target) {
+		case T_PROCESS:
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+		case T_SCD:
+		case T_NETDEV:
+		case T_NETOBJ:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+		default:
+			return UNDEFINED;
+		}
+
+	case R_READ:
+		switch (target) {
+		case T_DIR:
+#ifdef CONFIG_RSBAC_RW
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETTEMP:
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ_RW)
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_GET_PERMISSIONS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+		case T_SCD:
+		case T_DEV:
+		case T_NETOBJ:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+		default:
+			return UNDEFINED;
+		};
+
+	case R_MAP_EXEC:
+		switch (target) {
+		case T_FILE:
+		case T_NONE:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_SEND:
+		switch (target) {
+		case T_DEV:
+                case T_UNIXSOCK:
+                case T_IPC:
+		case T_PROCESS:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_RECEIVE:
+		switch (target) {
+		case T_UNIXSOCK:
+		case T_IPC:
+		case T_PROCESS:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_LISTEN:
+	case R_ACCEPT:
+	case R_CONNECT:
+	case R_NET_SHUTDOWN:
+		switch (target) {
+		case T_UNIXSOCK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_EXECUTE:
+		switch (target) {
+		case T_FILE:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_READ_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_IPC:
+		case T_DEV:
+		case T_UNIXSOCK:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_WRITE:
+		switch (target) {
+		case T_DIR:
+                case T_UNIXSOCK:
+		case T_SCD:
+		case T_IPC:
+#ifdef CONFIG_RSBAC_RW
+		case T_FILE:
+		case T_FIFO:
+		case T_DEV:
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETTEMP:
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ_RW)
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_APPEND_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_DEV:
+                case T_UNIXSOCK:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_READ_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_IPC:
+		case T_DEV:
+		case T_UNIXSOCK:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_IPC:
+		case T_DEV:
+		case T_UNIXSOCK:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_IOCTL:
+		switch (target) {
+                case T_UNIXSOCK:
+                case T_IPC:
+		case T_DEV:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_MOVETO:
+		switch (target) {
+                case T_DIR:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_ADD_TO_KERNEL:
+		switch (target) {
+		case T_FILE:
+		case T_DEV:
+		case T_NONE:
+			return DO_NOT_CARE;
+		default:
+			return UNDEFINED;
+		}
+
+	case R_ALTER:
+		/* only for IPC */
+		if (target == T_IPC)
+			return DO_NOT_CARE;
+		else
+			/* all other targets are undefined */
+			return UNDEFINED;
+		break;
+
+	case R_CHANGE_GROUP:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+		case T_PROCESS:
+		case T_NONE:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+#ifdef CONFIG_RSBAC_DAC_GROUP
+	case R_CHANGE_DAC_EFF_GROUP:
+	case R_CHANGE_DAC_FS_GROUP:
+		switch (target) {
+		case T_PROCESS:
+			/* there must be a new group specified */
+			if (attr == A_group)
+				return DO_NOT_CARE;
+			/* fall through */
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+#endif
+
+	case R_CHANGE_OWNER:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+			return DO_NOT_CARE;
+		case T_PROCESS:
+			/* there must be a new owner specified */
+			if (attr == A_owner)
+				return DO_NOT_CARE;
+			else
+				return UNDEFINED;
+			/* all other cases are undefined */
+#ifdef CONFIG_RSBAC_USER_CHOWN
+		case T_USER:
+			/* there must be a new owner specified */
+			if (attr == A_process)
+				return DO_NOT_CARE;
+			else
+				return UNDEFINED;
+			/* all other cases are undefined */
+#endif
+		default:
+			return UNDEFINED;
+		}
+
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	case R_CHANGE_DAC_EFF_OWNER:
+	case R_CHANGE_DAC_FS_OWNER:
+		switch (target) {
+		case T_PROCESS:
+			/* there must be a new owner specified */
+			if (attr == A_owner)
+				return DO_NOT_CARE;
+			/* fall through */
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+#endif
+
+	case R_CHDIR:
+		switch (target) {
+		case T_DIR:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_CLONE:
+		if (target == T_PROCESS)
+			return DO_NOT_CARE;
+		else
+			return UNDEFINED;
+
+	case R_CREATE:
+		switch (target) {
+			/* Creating dir or (pseudo) file IN target dir! */
+		case T_DIR:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETTEMP:
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_DELETE:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETTEMP:
+		case T_NETOBJ:
+#endif
+			return DO_NOT_CARE;
+		default:
+			return UNDEFINED;
+		}
+
+	case R_LINK_HARD:
+		switch (target) {
+		case T_FILE:
+		case T_UNIXSOCK:
+		case T_FIFO:
+		case T_SYMLINK:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_MODIFY_ACCESS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_AUTHENTICATE:
+		switch (target) {
+		case T_USER:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_MODIFY_ATTRIBUTE:
+		return DO_NOT_CARE;
+
+	case R_MODIFY_PERMISSIONS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+		case T_IPC:
+		case T_SCD:
+		case T_DEV:
+		case T_NETOBJ:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+		case T_NONE:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_MODIFY_SYSTEM_DATA:
+		switch (target) {
+                case T_UNIXSOCK:
+                case T_IPC:
+		case T_SCD:
+		case T_DEV:
+		case T_NETDEV:
+		case T_PROCESS:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_MOUNT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_DEV:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_READ_ATTRIBUTE:
+		return DO_NOT_CARE;
+
+	case R_REMOVE_FROM_KERNEL:
+		switch (target) {
+		case T_FILE:
+		case T_DEV:
+		case T_NONE:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_RENAME:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_SEND_SIGNAL:
+		switch (target) {
+		case T_PROCESS:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_SHUTDOWN:
+		switch (target) {
+		case T_NONE:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+
+	case R_SWITCH_LOG:
+		switch (target) {
+		case T_NONE:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_SWITCH_MODULE:
+		switch (target) {
+		case T_NONE:
+			/* there must be a switch target specified */
+			if (attr == A_switch_target)
+				return DO_NOT_CARE;
+			/* fall through */
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+		/* notify only, handled by adf-dispatcher */
+	case R_TERMINATE:
+		if (target == T_PROCESS)
+			return DO_NOT_CARE;
+		else
+			return UNDEFINED;
+
+	case R_TRACE:
+		switch (target) {
+		case T_PROCESS:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_TRUNCATE:
+		switch (target) {
+		case T_FILE:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_UMOUNT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_DEV:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+
+	case R_BIND:
+		switch (target) {
+		case T_IPC:
+			return DO_NOT_CARE;
+#if defined(CONFIG_RSBAC_NET_DEV)
+		case T_NETDEV:
+			return DO_NOT_CARE;
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+			return DO_NOT_CARE;
+#endif
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+	case R_LOCK:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+                case T_IPC:
+			return DO_NOT_CARE;
+			/* all other cases are undefined */
+		default:
+			return UNDEFINED;
+		}
+
+/*********************/
+	default:
+		return UNDEFINED;
+	}
+
+	return UNDEFINED;
+}				/* end of rsbac_adf_request_check() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up. Because of this, the write boundary is not adjusted - there  */
+/* is no user-level writing anyway...                                        */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+int rsbac_adf_set_attr_check(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)
+{
+	switch (request) {
+	case R_CLOSE:		/* only notifying for clean-up of opened-tables */
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+		case T_NETOBJ:
+			return 0;
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		};
+
+	case R_APPEND_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_CHANGE_OWNER:
+		switch (target) {
+			/*  Changing process owner affects access decisions, */
+			/*  so attributes have to be adjusted.               */
+		case T_PROCESS:
+			/* there must be a new owner specified */
+			if (attr != A_owner)
+				return -RSBAC_EINVALIDATTR;
+			/* fall through */
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+		case T_NONE:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+#ifdef CONFIG_RSBAC_DAC_OWNER
+	case R_CHANGE_DAC_EFF_OWNER:
+	case R_CHANGE_DAC_FS_OWNER:
+		switch (target) {
+			/*  Changing process owner affects access decisions, */
+			/*  so attributes have to be adjusted.               */
+		case T_PROCESS:
+			/* there must be a new owner specified */
+			if (attr != A_owner)
+				return -RSBAC_EINVALIDATTR;
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+#endif
+
+	case R_CHDIR:
+		switch (target) {
+		case T_DIR:
+			return 0;
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		};
+
+	case R_CLONE:
+		if (target == T_PROCESS)
+			return 0;
+		else
+			return -RSBAC_EINVALIDTARGET;
+
+	case R_CREATE:
+		switch (target) {
+			/* Creating dir or (pseudo) file IN target dir! */
+		case T_DIR:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+		/* removal of targets is done in main adf dispatcher! */
+	case R_DELETE:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_UM)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_EXECUTE:
+		switch (target) {
+		case T_FILE:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_SEND:
+	case R_RECEIVE:
+		switch (target) {
+                case T_UNIXSOCK:
+                case T_IPC:
+                case T_PROCESS:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_BIND:
+	case R_LISTEN:
+	case R_ACCEPT:
+	case R_CONNECT:
+	case R_NET_SHUTDOWN:
+		switch (target) {
+                case T_UNIXSOCK:
+                case T_IPC:
+#if defined(CONFIG_RSBAC_NET_OBJ)
+		case T_NETOBJ:
+#endif
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_MODIFY_SYSTEM_DATA:
+		switch (target) {
+		case T_SCD:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_MOUNT:
+		switch (target) {
+		case T_DIR:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_READ:
+		switch (target) {
+		case T_DIR:
+#ifdef CONFIG_RSBAC_RW
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ_RW) || defined(CONFIG_RSBAC_MS_SOCK)
+		case T_NETOBJ:
+#endif
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_READ_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_IPC:
+		case T_DEV:
+		case T_UNIXSOCK:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_READ_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_IPC:
+		case T_DEV:
+		case T_UNIXSOCK:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_RENAME:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_SEARCH:
+		switch (target) {
+                case T_DIR:
+		case T_FILE:
+		case T_SYMLINK:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_NETOBJ:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	case R_SHUTDOWN:
+		switch (target) {
+		case T_NETOBJ:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+#endif
+
+	case R_TRACE:
+		switch (target) {
+		case T_PROCESS:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_TRUNCATE:
+		switch (target) {
+		case T_FILE:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+#ifdef CONFIG_RSBAC_RW
+	case R_WRITE:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_DEV:
+		case T_UNIXSOCK:
+		case T_IPC:
+		case T_NETOBJ:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+#endif
+
+	case R_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_DEV:
+		case T_UNIXSOCK:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case R_MAP_EXEC:
+		switch (target) {
+		case T_FILE:
+		case T_NONE:
+			return 0;
+			/* all other cases are undefined */
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+
+	return -RSBAC_EINVALIDTARGET;
+}
diff --git a/rsbac/adf/adf_main.c b/rsbac/adf/adf_main.c
new file mode 100644
index 0000000..85c1ff2
--- /dev/null
+++ b/rsbac/adf/adf_main.c
@@ -0,0 +1,3374 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Main file main.c                 */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 25/Jan/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+#include <uapi/linux/magic.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/cap_getname.h>
+#include <rsbac/jail_getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/network.h>
+#if defined(CONFIG_RSBAC_UM_EXCL)
+#include <rsbac/um.h>
+#endif
+
+#ifdef CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT
+#include <linux/magic.h>
+#endif
+
+#ifdef CONFIG_RSBAC_SECDEL
+#include <linux/types.h>
+#include <linux/dcache.h>
+#include <asm/uaccess.h>
+#include <linux/buffer_head.h>
+#endif /* SECDEL */
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+__u64 rsbac_adf_request_count[T_NONE+1] = {0,0,0,0,0,0,0,0};
+__u64 rsbac_adf_set_attr_count[T_NONE+1] = {0,0,0,0,0,0,0,0};
+#ifdef CONFIG_RSBAC_XSTATS
+__u64 rsbac_adf_request_xcount[T_NONE+1][R_NONE];
+__u64 rsbac_adf_set_attr_xcount[T_NONE+1][R_NONE];
+#endif
+
+/******* MAC ********/
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+rsbac_boolean_t rsbac_switch_mac = TRUE;
+#endif  /* MAC */
+
+/******* DAZ ********/
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+rsbac_boolean_t rsbac_switch_daz = TRUE;
+#endif  /* DAZ */
+
+/******* FF ********/
+#ifdef CONFIG_RSBAC_SWITCH_FF
+rsbac_boolean_t rsbac_switch_ff = TRUE;
+#endif  /* FF */
+
+/******* RC ********/
+#ifdef CONFIG_RSBAC_SWITCH_RC
+rsbac_boolean_t rsbac_switch_rc = TRUE;
+#endif  /* RC */
+
+/****** AUTH *******/
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+rsbac_boolean_t rsbac_switch_auth = TRUE;
+#endif  /* AUTH */
+
+/****** ACL *******/
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+rsbac_boolean_t rsbac_switch_acl = TRUE;
+#endif  /* ACL */
+
+/****** CAP *******/
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+rsbac_boolean_t rsbac_switch_cap = TRUE;
+#endif  /* CAP */
+
+/****** JAIL *******/
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+rsbac_boolean_t rsbac_switch_jail = TRUE;
+#endif  /* JAIL */
+
+/****** PAX ********/
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+rsbac_boolean_t rsbac_switch_pax = TRUE;
+#endif  /* PAX */
+
+/****** RES *******/
+#ifdef CONFIG_RSBAC_SWITCH_RES
+rsbac_boolean_t rsbac_switch_res = TRUE;
+#endif  /* RES */
+
+/******* UDF ********/
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+rsbac_boolean_t rsbac_switch_udf = TRUE;
+#endif  /* UDF */
+
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+/* Init function, calls inits for all sub-modules  */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+void rsbac_init_adf(void)
+#else
+void __init rsbac_init_adf(void)
+#endif
+  {
+    #if defined(CONFIG_RSBAC_REG)
+    rsbac_reg_init();
+    #endif
+  }
+
+enum rsbac_adf_req_ret_t
+    adf_and_plus(enum rsbac_adf_req_ret_t res1,
+                 enum rsbac_adf_req_ret_t res2)
+  {
+    switch (res1)
+      {
+        case DO_NOT_CARE: return (res2);
+        case GRANTED:     if (res2 == DO_NOT_CARE)
+                            return (GRANTED);
+                          else
+                            return (res2);
+        case NOT_GRANTED: if (res2 == UNDEFINED)
+                            return (UNDEFINED);
+                          else
+                            return (NOT_GRANTED);
+        default:          return (UNDEFINED);
+      }
+  }
+
+/*
+ * rsbac_adf_request_int()
+ * This function is the main decision function, called though the
+ * rsbac_adf_request wrapper from the AEF.
+ */
+
+EXPORT_SYMBOL(rsbac_adf_request_int);
+enum rsbac_adf_req_ret_t
+   rsbac_adf_request_int(enum  rsbac_adf_request_t     request,
+                               rsbac_pid_t             caller_pid,
+                         enum  rsbac_target_t          target,
+                         union rsbac_target_id_t     * tid_p,
+                         enum  rsbac_attribute_t       attr,
+                         union rsbac_attribute_value_t * attr_val_p,
+                         enum  rsbac_switch_target_t   ignore_module)
+  {
+    union rsbac_target_id_t        i_tid;
+    union rsbac_attribute_value_t  i_attr_val;
+          rsbac_uid_t              owner=0;
+    int tmperr=0;
+    rsbac_request_vector_t	request_vector;
+    enum rsbac_adf_req_ret_t   result = DO_NOT_CARE;
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+    enum rsbac_adf_req_ret_t   ret_result = DO_NOT_CARE;
+#endif
+    rsbac_enum_t mod_result[SW_NONE + 1] = {
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE,
+                                   DO_NOT_CARE
+                                 };
+    rsbac_boolean_t do_log = FALSE;
+    rsbac_boolean_t log_on_request = TRUE;
+/* only if individual logging is enabled */
+#if defined(CONFIG_RSBAC_IND_LOG) || defined(CONFIG_RSBAC_IND_NETDEV_LOG) || defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+    union rsbac_attribute_value_t  i_attr_val2;
+    enum rsbac_log_level_t log_level;
+#endif
+    struct vfsmount * mnt_p;
+#ifdef CONFIG_RSBAC_SOFTMODE
+    rsbac_boolean_t rsbac_internal = FALSE;
+#endif
+
+/* No decision possible before init (called at boot time) -> don't care */
+    if (unlikely(!rsbac_is_initialized()))
+      return DO_NOT_CARE;
+
+/* Always granted for kernel (pid 0) and logging daemon */
+    if (   !pid_nr(caller_pid)
+        #if defined(CONFIG_RSBAC_LOG_REMOTE)
+        || (pid_nr(caller_pid) == pid_nr(rsbaclogd_pid))
+        #endif
+       )
+      return GRANTED;
+
+/* Checking base values */
+    if(unlikely(   request >= R_NONE
+                || target > T_NONE
+                || attr > A_none)
+               )
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_adf_request_int(): called with invalid request, target or attribute\n");
+        return NOT_GRANTED;
+      }
+    request_vector = RSBAC_REQUEST_VECTOR(request);
+
+    if (unlikely(in_interrupt()))
+      {
+        char * request_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+        if(request_name)
+          {
+            get_request_name(request_name, request);
+            printk(KERN_WARNING "rsbac_adf_request_int(): called from interrupt: request %s, pid %u(%s), attr_val %u!\n",
+                   request_name, pid_nr(caller_pid), current->comm, attr_val_p->dummy);
+            rsbac_kfree(request_name);
+          }
+        else
+          {
+            printk(KERN_WARNING "rsbac_adf_request_int(): called from interrupt: request %u, pid %u(%s)!\n",
+                   request, pid_nr(caller_pid), current->comm);
+          }
+        dump_stack();
+        return DO_NOT_CARE;
+      }
+
+/* Getting basic information about this request */
+
+    /* only useful for real process, not idle or init */
+    if (pid_nr(caller_pid) > 1)
+      {
+        tmperr = rsbac_get_owner(&owner);
+        if(tmperr)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_adf_request_int(): caller_pid %i, RSBAC not initialized, returning DO_NOT_CARE\n",
+                   pid_nr(caller_pid));
+            return DO_NOT_CARE;      /* Startup-Sequence (see above) */
+          }
+      }
+    else  /* caller_pid = 1 -> init, always owned by root */
+    {
+      owner = 0;
+    }
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if ((attr == A_owner) && (RSBAC_UID_SET(attr_val_p->owner) > RSBAC_UM_VIRTUAL_MAX))
+      attr_val_p->owner = RSBAC_GEN_UID(RSBAC_UID_SET(owner), attr_val_p->owner);
+    else
+    if ((attr == A_group) && (RSBAC_GID_SET(attr_val_p->group) > RSBAC_UM_VIRTUAL_MAX))
+      attr_val_p->group = RSBAC_GEN_GID(RSBAC_UID_SET(owner), attr_val_p->group);
+#else
+    if (attr == A_owner)
+      attr_val_p->owner = RSBAC_UID_NUM(attr_val_p->owner);
+    else
+    if (attr == A_group)
+      attr_val_p->group = RSBAC_GID_NUM(attr_val_p->group);
+#endif
+
+/******************************************************/
+/* General work for all modules - before module calls */
+    /* test target on rsbac_internal */
+    switch(target)
+      {
+        case T_FILE:
+        case T_DIR:
+        case T_FIFO:
+        case T_SYMLINK:
+#ifdef CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT
+          if (   ((mnt_p = rsbac_get_vfsmount(tid_p->file.device)))
+              && (   (mnt_p->mnt_sb->s_magic == NFS_SUPER_MAGIC)
+                  || (mnt_p->mnt_sb->s_magic == CODA_SUPER_MAGIC)
+                  || (mnt_p->mnt_sb->s_magic == NCP_SUPER_MAGIC)
+                  || (mnt_p->mnt_sb->s_magic == SMB_SUPER_MAGIC)
+                 )
+             )
+            {
+              result = DO_NOT_CARE;
+              goto log;
+            }
+#endif
+          /* No decision on pseudo pipefs */
+          if(   (target == T_FIFO)
+             && ((mnt_p = rsbac_get_vfsmount(tid_p->file.device)))
+             && (mnt_p->mnt_sb->s_magic == PIPEFS_MAGIC)
+            )
+            return DO_NOT_CARE;
+
+          switch(request)
+            {
+              case R_GET_STATUS_DATA:
+              case R_GET_PERMISSIONS_DATA:
+              case R_READ_ATTRIBUTE:
+#ifdef CONFIG_RSBAC_DAT_VISIBLE
+              case R_SEARCH:
+              case R_READ:
+              case R_CLOSE:
+              case R_CHDIR:
+#endif
+                break;
+
+              default:
+                if ((tmperr = rsbac_get_attr(SW_GEN,
+                                             target,
+                                             *tid_p,
+                                             A_internal,
+                                             &i_attr_val,
+                                             TRUE) ))
+                  {
+                    if(tmperr == -RSBAC_EINVALIDDEV)
+                      {
+//                        rsbac_ds_get_error_num("rsbac_adf_request()", A_internal, tmperr);
+                        return DO_NOT_CARE;  /* last calls on shutdown */
+                      }
+                    else
+                      {
+                        rsbac_ds_get_error_num("rsbac_adf_request()", A_internal, tmperr);
+                        return NOT_GRANTED;  /* something weird happened */
+                      }
+                  }
+                /* no access to rsbac_internal objects is granted in any case */
+                if (i_attr_val.internal)
+                  {
+                    rsbac_printk(KERN_WARNING
+                           "rsbac_adf_request(): trial to access object declared RSBAC-internal!\n");
+                    result = NOT_GRANTED;
+                    mod_result[SW_NONE] = NOT_GRANTED;
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                    ret_result = NOT_GRANTED;
+                    #endif
+                    rsbac_internal = TRUE;
+                    #endif
+                  }
+            }
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL_ISOLATE)
+          if (attr == A_vset && (RSBAC_UID_SET(owner))) {
+            result = adf_and_plus(result, NOT_GRANTED);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+            ret_result = adf_and_plus(ret_result, NOT_GRANTED);
+#endif
+          }
+#endif
+
+          break;
+
+#if defined(CONFIG_RSBAC_UM_EXCL) || defined(CONFIG_RSBAC_UM_VIRTUAL_ISOLATE)
+        case T_PROCESS:
+#if defined(CONFIG_RSBAC_UM_EXCL)
+          switch(request)
+            {
+              case R_CHANGE_OWNER:
+#ifdef CONFIG_RSBAC_DAC_OWNER
+              case R_CHANGE_DAC_EFF_OWNER:
+              case R_CHANGE_DAC_FS_OWNER:
+#endif
+                if(   (attr == A_owner)
+                   && !rsbac_um_no_excl
+                   && !rsbac_um_user_exists(0, attr_val_p->owner)
+                  )
+                  {
+                    rsbac_printk(KERN_INFO
+                                 "rsbac_adf_request(): uid %u not known to RSBAC User Management!\n",
+                                 attr_val_p->owner);
+                    result = adf_and_plus(result, NOT_GRANTED);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                    ret_result = adf_and_plus(ret_result, NOT_GRANTED);
+#endif
+                  }
+                break;
+
+              case R_CHANGE_GROUP:
+#ifdef CONFIG_RSBAC_DAC_OWNER
+              case R_CHANGE_DAC_EFF_GROUP:
+              case R_CHANGE_DAC_FS_GROUP:
+#endif
+                if(   (attr == A_group)
+                   && !rsbac_um_no_excl
+                   && !rsbac_um_group_exists(0, attr_val_p->group)
+                  )
+                  {
+                    rsbac_printk(KERN_INFO
+                                 "rsbac_adf_request(): gid %u not known to RSBAC User Management!\n",
+                                 attr_val_p->group);
+                    result = adf_and_plus(result, NOT_GRANTED);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                    ret_result = adf_and_plus(ret_result, NOT_GRANTED);
+#endif
+                  }
+                break;
+
+              default:
+                break;
+            }
+#endif
+#if defined(CONFIG_RSBAC_UM_VIRTUAL_ISOLATE)
+          if (attr == A_vset && (RSBAC_UID_SET(owner))) {
+            result = adf_and_plus(result, NOT_GRANTED);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+            ret_result = adf_and_plus(ret_result, NOT_GRANTED);
+#endif
+          }
+#endif
+          break;
+#endif /* UM_EXCL || UM_VIRTUAL_ISOLATE */
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL_ISOLATE)
+        case T_USER:
+          if(   RSBAC_UID_SET(owner)
+             && (RSBAC_UID_SET(owner) != RSBAC_UID_SET(tid_p->user))
+            ) {
+                    if (RSBAC_UID_SET(tid_p->user) == RSBAC_UM_VIRTUAL_ALL)
+                            tid_p->user = RSBAC_GEN_UID(RSBAC_UID_SET(owner), tid_p->user);
+                    else {
+                            result = adf_and_plus(result, NOT_GRANTED);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                            ret_result = adf_and_plus(ret_result, NOT_GRANTED);
+#endif
+                    }
+          }
+          break;
+        case T_GROUP:
+          if(   RSBAC_UID_SET(owner)
+             && (RSBAC_UID_SET(owner) != RSBAC_GID_SET(tid_p->group))
+            ) {
+                    if (RSBAC_UID_SET(tid_p->user) == RSBAC_UM_VIRTUAL_ALL)
+                            tid_p->user = RSBAC_GEN_UID(RSBAC_UID_SET(owner), tid_p->user);
+                    else {
+                            result = adf_and_plus(result, NOT_GRANTED);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                            ret_result = adf_and_plus(ret_result, NOT_GRANTED);
+#endif
+                    }
+          }
+          break;
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG) || defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC)
+	case T_NETOBJ:
+		if(rsbac_net_remote_request(request)) {
+			tid_p->netobj.local_temp = 0;
+			rsbac_ta_net_lookup_templates(0,
+						      &tid_p->
+						      netobj, NULL,
+						      &tid_p->netobj.remote_temp);
+		} else {
+			tid_p->netobj.remote_temp = 0;
+			rsbac_ta_net_lookup_templates(0,
+						      &tid_p->
+						      netobj,
+						      &tid_p->netobj.local_temp,
+						      NULL);
+		}
+#endif
+#endif
+
+        default:
+          break;
+      }
+      
+/**********************************************************/
+/* calling all decision modules, building a common result */
+
+#ifdef CONFIG_RSBAC_DEBUG
+/* first, check for valid request/target combination      */
+/* (undefined should only happen in _check and means a real bug!) */
+  result = adf_and_plus(result,rsbac_adf_request_check(request,
+                                                       caller_pid,
+                                                       target,
+                                                       tid_p,
+                                                       attr,
+                                                       attr_val_p,
+                                                       owner) );
+#endif
+
+/******* MAC ********/
+#if defined(CONFIG_RSBAC_MAC)
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+if (rsbac_switch_mac)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_MAC && (request_vector & RSBAC_MAC_REQUEST_VECTOR)) {
+        mod_result[SW_MAC] = rsbac_adf_request_mac(request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+        result = adf_and_plus(result, mod_result[SW_MAC]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+        if(!rsbac_ind_softmode[SW_MAC])
+          ret_result = adf_and_plus(ret_result, mod_result[SW_MAC]);
+#endif
+    }
+#endif  /* MAC */
+
+/******* DAZ ********/
+#if defined(CONFIG_RSBAC_DAZ)
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+if (rsbac_switch_daz)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_DAZ && (request_vector & RSBAC_DAZ_REQUEST_VECTOR))
+    {
+      mod_result[SW_DAZ]  = rsbac_adf_request_daz (request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_DAZ]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_DAZ])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_DAZ]);
+#endif
+    }
+#endif  /* DAZ */
+
+/******* FF ********/
+#if defined(CONFIG_RSBAC_FF)
+#ifdef CONFIG_RSBAC_SWITCH_FF
+if (rsbac_switch_ff)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_FF && (request_vector & RSBAC_FF_REQUEST_VECTOR))
+    {
+      mod_result[SW_FF]  = rsbac_adf_request_ff (request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_FF]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_FF])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_FF]);
+#endif
+    }
+#endif  /* FF */
+
+/******* RC ********/
+#if defined(CONFIG_RSBAC_RC)
+#ifdef CONFIG_RSBAC_SWITCH_RC
+if (rsbac_switch_rc)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_RC)
+    {
+      mod_result[SW_RC]  = rsbac_adf_request_rc (request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_RC]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_RC])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_RC]);
+#endif
+    }
+#endif  /* RC */
+
+/****** AUTH *******/
+#if defined(CONFIG_RSBAC_AUTH)
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+if (rsbac_switch_auth)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_AUTH && (request_vector & RSBAC_AUTH_REQUEST_VECTOR))
+    {
+      mod_result[SW_AUTH]= rsbac_adf_request_auth(request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_AUTH]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_AUTH])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_AUTH]);
+#endif
+    }
+#endif  /* AUTH */
+
+/****** ACL *******/
+#if defined(CONFIG_RSBAC_ACL)
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+if (rsbac_switch_acl)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_ACL)
+    {
+      mod_result[SW_ACL] = rsbac_adf_request_acl(request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_ACL]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_ACL])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_ACL]);
+#endif
+    }
+#endif  /* ACL */
+
+/****** CAP *******/
+#if defined(CONFIG_RSBAC_CAP)
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+if (rsbac_switch_cap)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_CAP && (request_vector & RSBAC_CAP_REQUEST_VECTOR))
+    {
+      mod_result[SW_CAP] = rsbac_adf_request_cap(request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_CAP]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_CAP])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_CAP]);
+#endif
+    }
+#endif  /* CAP */
+
+/****** JAIL *******/
+#if defined(CONFIG_RSBAC_JAIL)
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+if (rsbac_switch_jail)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_JAIL && (request_vector & RSBAC_JAIL_REQUEST_VECTOR))
+    {
+      mod_result[SW_JAIL]= rsbac_adf_request_jail(request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_JAIL]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_JAIL])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_JAIL]);
+#endif
+    }
+#endif  /* JAIL */
+
+/******* PAX ********/
+#if defined(CONFIG_RSBAC_PAX)
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+if (rsbac_switch_pax)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_PAX && (request_vector & RSBAC_PAX_REQUEST_VECTOR))
+    {
+      mod_result[SW_PAX]  = rsbac_adf_request_pax (request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_PAX]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_PAX])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_PAX]);
+#endif
+    }
+#endif  /* PAX */
+
+/****** RES *******/
+#if defined(CONFIG_RSBAC_RES)
+#ifdef CONFIG_RSBAC_SWITCH_RES
+if (rsbac_switch_res)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_RES && (request_vector & RSBAC_RES_REQUEST_VECTOR))
+    {
+      mod_result[SW_RES] = rsbac_adf_request_res(request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_RES]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_RES])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_RES]);
+#endif
+    }
+#endif  /* RES */
+
+/******* UDF ********/
+#if defined(CONFIG_RSBAC_UDF)
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+if (rsbac_switch_udf)
+#endif
+  /* no need to call module, if to be ignored */
+  if(ignore_module != SW_UDF && (request_vector & RSBAC_UDF_REQUEST_VECTOR))
+    {
+      mod_result[SW_UDF]  = rsbac_adf_request_udf (request,
+                                              caller_pid,
+                                              target,
+                                              *tid_p,
+                                              attr,
+                                              *attr_val_p,
+                                              owner);
+      result = adf_and_plus(result, mod_result[SW_UDF]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+      if(!rsbac_ind_softmode[SW_UDF])
+        ret_result = adf_and_plus(ret_result, mod_result[SW_UDF]);
+#endif
+    }
+#endif  /* UDF */
+
+/****** REG *******/
+#if defined(CONFIG_RSBAC_REG)
+if(ignore_module != SW_REG)
+  {
+    mod_result[SW_REG]= rsbac_adf_request_reg (request,
+                                            caller_pid,
+                                            target,
+                                            *tid_p,
+                                            attr,
+                                            *attr_val_p,
+                                            owner);
+    result = adf_and_plus(result, mod_result[SW_REG]);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+    if(!rsbac_ind_softmode[SW_REG])
+      ret_result = adf_and_plus(ret_result, mod_result[SW_REG]);
+#endif
+  }
+#endif  /* REG */
+
+/****************************/
+
+#if defined(CONFIG_RSBAC_DEBUG) && defined(CONFIG_RSBAC_NET)
+    if(    rsbac_debug_adf_net
+       && (   (target == T_NETDEV)
+           || (target == T_NETTEMP)
+           || (target == T_NETOBJ)
+          )
+      )
+      do_log = TRUE;
+#endif
+
+/* log based on process owner */
+#ifdef CONFIG_RSBAC_IND_USER_LOG
+    i_tid.user = owner;
+    if (rsbac_get_attr(SW_GEN,
+                       T_USER,
+                       i_tid,
+                       A_log_user_based,
+                       &i_attr_val,
+                       FALSE))
+      {
+        rsbac_ds_get_error("rsbac_adf_request()", A_log_user_based);
+      }
+    else
+      {
+        if(((rsbac_request_vector_t) 1 << request) & i_attr_val.log_user_based)
+          do_log = TRUE;
+      }
+#endif /* CONFIG_RSBAC_IND_USER_LOG */
+
+/* log based on program */
+#ifdef CONFIG_RSBAC_IND_PROG_LOG
+    if(!do_log)
+      {
+        i_tid.process = caller_pid;
+        if (rsbac_get_attr(SW_GEN,
+                           T_PROCESS,
+                           i_tid,
+                           A_log_program_based,
+                           &i_attr_val,
+                           FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_log_program_based);
+          }
+        else
+          {
+            if(((rsbac_request_vector_t) 1 << request) & i_attr_val.log_program_based) 
+              do_log = TRUE;
+          }
+      }
+#endif /* CONFIG_RSBAC_IND_PROG_LOG */
+
+/*****************************************************/
+/* General work for all modules - after module calls */
+/* Note: the process' individual logging attributes are needed above */
+    switch(request)
+      {
+        case R_TERMINATE:
+            if (target == T_PROCESS)
+              rsbac_remove_target(T_PROCESS,*tid_p);
+            break;
+
+#ifdef CONFIG_RSBAC_USER_CHOWN
+	case R_CHANGE_OWNER:
+		if (target == T_PROCESS) {
+			i_tid.user = attr_val_p->owner;
+			i_attr_val.process = tid_p->process;
+			result = adf_and_plus(result,
+				rsbac_adf_request_int(request,
+					caller_pid,
+					T_USER,
+					&i_tid,
+					A_process,
+					&i_attr_val,
+					ignore_module));
+		}
+		break;
+#endif
+
+        default:
+            break;
+      }
+
+/* logging request on info level, if requested by file/dir/dev attributes */
+/* log_array_low/high, or, if that is requested, if enabled for this request */
+/* type (attributes state level, or that request based level is to be taken) */
+/* loglevel 2: log everything */
+/* loglevel 1: log, if denied */
+/* loglevel 0: log nothing */
+
+#ifdef CONFIG_RSBAC_IND_LOG /* only if individual logging is enabled */
+    /* if file/dir/dev, depend log on log_arrays */
+    /* (but not for file.device = 0) */
+    /* log_on_request is TRUE */
+    if(   !do_log
+       && (   (   (   (target == T_FILE)
+                   || (target == T_DIR)
+                   || (target == T_FIFO)
+                   || (target == T_SYMLINK)
+                   || (target == T_UNIXSOCK)
+                  )
+               && RSBAC_MAJOR(tid_p->file.device)
+               && RSBAC_MINOR(tid_p->file.device)
+              )
+           || (target == T_DEV)
+          )
+      )
+      {
+        if (rsbac_get_attr(SW_GEN,
+                           target,
+                           *tid_p,
+                           A_log_array_low,
+                           &i_attr_val,
+                           FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_log_array_low);
+          }
+        else
+          {
+            if (rsbac_get_attr(SW_GEN,
+                               target,
+                               *tid_p,
+                               A_log_array_high,
+                               &i_attr_val2,
+                               FALSE))
+              {
+                rsbac_ds_get_error("rsbac_adf_request()", A_log_array_high);
+              }
+            else
+              { /* ll = low-bit for request | (high-bit for request as bit 1) */
+                /* WARNING: we deal with u64 here, only logical operations and */
+                /* shifts work correctly! */
+                log_level =   ((i_attr_val.log_array_low   >> request) & 1)
+                          | ( ((i_attr_val2.log_array_high >> request) & 1) << 1);
+                if (   log_level == LL_full
+                    || (   log_level == LL_denied
+                        && (result == NOT_GRANTED
+                            || result == UNDEFINED)) )
+                  {
+                    do_log = TRUE;
+                  }
+                if(log_level != LL_request)
+                  log_on_request = FALSE;
+              }
+          }
+      }
+#endif /* CONFIG_RSBAC_IND_LOG */
+
+#ifdef CONFIG_RSBAC_IND_NETDEV_LOG /* only if individual logging for netdev is enabled */
+    /* if netdev, depend log on log_arrays */
+    /* log_on_request is TRUE */
+    if(   !do_log
+       && (target == T_NETDEV)
+      )
+      {
+        if (rsbac_get_attr(SW_GEN,
+                           target,
+                           *tid_p,
+                           A_log_array_low,
+                           &i_attr_val,
+                           FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_log_array_low);
+          }
+        else
+          {
+            if (rsbac_get_attr(SW_GEN,
+                               target,
+                               *tid_p,
+                               A_log_array_high,
+                               &i_attr_val2,
+                               FALSE))
+              {
+                rsbac_ds_get_error("rsbac_adf_request()", A_log_array_high);
+              }
+            else
+              { /* ll = low-bit for request | (high-bit for request as bit 1) */
+                /* WARNING: we deal with u64 here, only logical operations and */
+                /* shifts work correctly! */
+                log_level =   ((i_attr_val.log_array_low   >> request) & 1)
+                          | ( ((i_attr_val2.log_array_high >> request) & 1) << 1);
+                if (   log_level == LL_full
+                    || (   log_level == LL_denied
+                        && (result == NOT_GRANTED
+                            || result == UNDEFINED)) )
+                  {
+                    do_log = TRUE;
+                  }
+                if(log_level != LL_request)
+                  log_on_request = FALSE;
+              }
+          }
+      }
+#endif /* CONFIG_RSBAC_IND_NETDEV_LOG */
+
+#ifdef CONFIG_RSBAC_IND_NETOBJ_LOG /* only if individual logging for net objects is enabled */
+    /* if nettemp, netobj, depend log on log_arrays */
+    /* (but not for file.device = 0) */
+    /* log_on_request is TRUE */
+    if(   !do_log
+       && (   (target == T_NETTEMP)
+           || (target == T_NETOBJ)
+          )
+      )
+      {
+        enum rsbac_attribute_t i_attr1, i_attr2;
+
+        if(target == T_NETOBJ)
+          {
+            if(rsbac_net_remote_request(request))
+              {
+                i_attr1 = A_remote_log_array_low;
+                i_attr2 = A_remote_log_array_high;
+              }
+            else
+              {
+                i_attr1 = A_local_log_array_low;
+                i_attr2 = A_local_log_array_high;
+              }
+          }
+        else
+          {
+            i_attr1 = A_log_array_low;
+            i_attr2 = A_log_array_high;
+          }
+        if (rsbac_get_attr(SW_GEN,
+                           target,
+                           *tid_p,
+                           i_attr1,
+                           &i_attr_val,
+                           FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", i_attr1);
+          }
+        else
+          {
+            if (rsbac_get_attr(SW_GEN,
+                               target,
+                               *tid_p,
+                               i_attr2,
+                               &i_attr_val2,
+                               FALSE))
+              {
+                rsbac_ds_get_error("rsbac_adf_request()", i_attr2);
+              }
+            else
+              { /* ll = low-bit for request | (high-bit for request as bit 1) */
+                /* WARNING: we deal with u64 here, only logical operations and */
+                /* shifts work correctly! */
+                log_level =   ((i_attr_val.log_array_low   >> request) & 1)
+                          | ( ((i_attr_val2.log_array_high >> request) & 1) << 1);
+                if (   log_level == LL_full
+                    || (   log_level == LL_denied
+                        && (result == NOT_GRANTED
+                            || result == UNDEFINED)) )
+                  {
+                    do_log = TRUE;
+                  }
+                if(log_level != LL_request)
+                  log_on_request = FALSE;
+              }
+          }
+      }
+#endif /* CONFIG_RSBAC_IND_NETOBJ_LOG */
+
+#ifdef CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT
+log:
+#endif
+    /* if enabled, try request based log level */
+    if (   !do_log
+        && log_on_request
+        && (   rsbac_log_levels[request][target] == LL_full
+            || (   rsbac_log_levels[request][target] == LL_denied
+                && (result == NOT_GRANTED
+                    || result == UNDEFINED)) ) )
+      do_log = TRUE;
+
+    if(do_log)
+      {
+        char * request_name;
+        char * res_name;
+        char * res_mods;
+        char * target_type_name;
+        char * target_id_name;
+        char * attr_name;
+        char * attr_val_name;
+#ifdef CONFIG_RSBAC_NET_OBJ
+        char * remote_ip_name;
+#else
+        char remote_ip_name[1];
+#endif
+        char * audit_uid_name;
+        char  command[17];
+        rsbac_pid_t parent_pid = NULL;
+        rsbac_uid_t audit_uid;
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+        rsbac_pseudo_t  pseudo = 0;
+#endif
+        char * program_path;
+
+	/* parent pid */
+	if(current->parent)
+	  parent_pid = get_task_pid(current->parent, PIDTYPE_PID);
+
+        /* rsbac_kmalloc all memory */
+        request_name = rsbac_kmalloc(32);
+        res_name = rsbac_kmalloc(32);
+        res_mods = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+        target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+        target_id_name
+         = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+           /* max. path name len + some extra */
+        #else
+        target_id_name = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+           /* max. file name len + some extra */
+        #endif
+        #ifdef CONFIG_RSBAC_LOG_PROGRAM_FILE
+        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+        program_path
+         = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+           /* max. path name len + some extra */
+        #else
+        program_path = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+           /* max. file name len + some extra */
+        #endif
+        #else
+        program_path = rsbac_kmalloc(2);
+        #endif
+        attr_name = rsbac_kmalloc(32);
+        attr_val_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+#ifdef CONFIG_RSBAC_NET_OBJ
+        remote_ip_name = rsbac_kmalloc(32);
+#endif
+        audit_uid_name = rsbac_kmalloc(32);
+
+        request_name[0] = (char) 0;
+        target_type_name[0] = (char) 0;
+        target_id_name[0] = (char) 0;
+        program_path[0] = (char) 0;
+        attr_name[0] = (char) 0;
+        attr_val_name[0] = (char) 0;
+        remote_ip_name[0] = (char) 0;
+        audit_uid_name[0] = (char) 0;
+        res_name[0] = (char) 0;
+        res_mods[0] = (char) 0;
+        command[0] = (char) 0;
+        get_request_name(request_name, request);
+/*
+        if(result == mod_result[SW_NONE])
+          {
+            strcat(res_mods, " SW_GEN");
+          }
+*/
+    #if defined(CONFIG_RSBAC_MAC)
+        if(result == mod_result[SW_MAC])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_MAC])
+              strcat(res_mods, " MAC(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " MAC");
+          }
+    #endif
+    #if defined(CONFIG_RSBAC_DAZ)
+        if(result == mod_result[SW_DAZ])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_DAZ])
+              strcat(res_mods, " DAZ(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " DAZ");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_FF
+        if(result == mod_result[SW_FF])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_FF])
+              strcat(res_mods, " FF(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " FF");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_RC
+        if(result == mod_result[SW_RC])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_RC])
+              strcat(res_mods, " RC(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " RC");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_AUTH
+        if(result == mod_result[SW_AUTH])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_AUTH])
+              strcat(res_mods, " AUTH(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " AUTH");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_ACL
+        if(result == mod_result[SW_ACL])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_ACL])
+              strcat(res_mods, " ACL(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " ACL");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_CAP
+        if(result == mod_result[SW_CAP])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_CAP])
+              strcat(res_mods, " CAP(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " CAP");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_JAIL
+        if(result == mod_result[SW_JAIL])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_JAIL])
+              strcat(res_mods, " JAIL(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " JAIL");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_RES
+        if(result == mod_result[SW_RES])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_RES])
+              strcat(res_mods, " RES(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " RES");
+          }
+    #endif
+    #if defined(CONFIG_RSBAC_UDF)
+        if(result == mod_result[SW_UDF])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_UDF])
+              strcat(res_mods, " UDF(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " UDF");
+          }
+    #endif
+    #ifdef CONFIG_RSBAC_REG
+        if(result == mod_result[SW_REG])
+          {
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+            if(rsbac_ind_softmode[SW_REG])
+              strcat(res_mods, " REG(Softmode)");
+            else
+            #endif
+              strcat(res_mods, " REG");
+          }
+    #endif
+        if(!res_mods[0])
+          strcat(res_mods, " ADF");
+
+        /* Get process audit_uid */
+        i_tid.process = caller_pid;
+        if (rsbac_get_attr(SW_GEN,T_PROCESS,i_tid,A_audit_uid,&i_attr_val,FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_audit_uid);
+            return NOT_GRANTED;  /* something weird happened */
+          }
+        audit_uid = i_attr_val.audit_uid;
+        if(audit_uid == RSBAC_NO_USER)
+          audit_uid = owner;
+        else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_UID_SET(audit_uid))
+            sprintf(audit_uid_name, "audit uid %u/%u, ",
+                    RSBAC_UID_SET(audit_uid),
+                    RSBAC_UID_NUM(audit_uid));
+          else
+#endif
+          sprintf(audit_uid_name, "audit uid %u, ", RSBAC_UID_NUM(audit_uid));
+        }
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+        /* Get owner's logging pseudo */
+        i_tid.user = audit_uid;
+        if (rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val,FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_pseudo);
+            return NOT_GRANTED;  /* something weird happened */
+          }
+        /* if pseudo is not registered, return attribute value is 0 (see later) */
+        pseudo = i_attr_val.pseudo;
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+        /* Get process remote_ip */
+        i_tid.process = caller_pid;
+        if (rsbac_get_attr(SW_GEN,T_PROCESS,i_tid,A_remote_ip,&i_attr_val,FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_remote_ip);
+            return NOT_GRANTED;  /* something weird happened */
+          }
+        if(i_attr_val.remote_ip)
+          sprintf(remote_ip_name, "remote ip %u.%u.%u.%u, ", NIPQUAD(i_attr_val.remote_ip));
+#endif
+
+#ifdef CONFIG_RSBAC_LOG_PROGRAM_FILE
+        i_tid.process = caller_pid;
+        if (rsbac_get_attr(SW_GEN,T_PROCESS,i_tid,A_program_file,&i_attr_val,FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_request()", A_program_file);
+            return NOT_GRANTED;  /* something weird happened */
+          }
+        if(   i_attr_val.program_file.dentry_p
+           && i_attr_val.program_file.dentry_p->d_name.name
+           && i_attr_val.program_file.dentry_p->d_name.len
+          )
+          {
+            char * p = program_path;
+
+            p += sprintf(program_path, ", prog_file ");
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+            rsbac_get_full_path(i_attr_val.program_file.dentry_p, p, CONFIG_RSBAC_MAX_PATH_LEN);
+#else
+            int namelen = rsbac_min(i_attr_val.program_file.dentry_p->d_name.len, RSBAC_MAXNAMELEN);
+
+            strncpy(p, i_attr_val.program_file.dentry_p->d_name.name, namelen);
+            p[namelen]=0;
+#endif
+          }
+#endif
+
+        get_target_name(target_type_name, target, target_id_name, *tid_p);
+        get_attribute_name(attr_name, attr);
+        get_attribute_value_name(attr_val_name, attr, attr_val_p);
+        get_result_name(res_name, result);
+        if ((current) && (current->comm))
+          {
+            strncpy(command,current->comm,16);          
+            command[16] = (char) 0;
+          }
+
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+        /* if pseudo is set, its value is != 0, else -> use id */
+        if (pseudo)
+          {
+#ifdef CONFIG_RSBAC_SOFTMODE
+            if(rsbac_softmode)
+              rsbac_printk(KERN_INFO "rsbac_adf_request(): request %s, pid %u, ppid %u, prog_name %s%s, pseudo %u, %starget_type %s, tid %s, attr %s, value %s, result %s (Softmode) by%s\n",
+                           request_name, pid_nr(caller_pid), parent_pid, command, program_path, pseudo, remote_ip_name, target_type_name, target_id_name, attr_name, attr_val_name, res_name, res_mods);
+            else
+#endif
+              rsbac_printk(KERN_INFO "rsbac_adf_request(): request %s, pid %u, ppid %u, prog_name %s%s, pseudo %u, %starget_type %s, tid %s, attr %s, value %s, result %s by%s\n",
+                           request_name, pid_nr(caller_pid), parent_pid, command, program_path, pseudo, remote_ip_name, target_type_name, target_id_name, attr_name, attr_val_name, res_name, res_mods);
+          }
+        else
+#endif
+          {
+            char * owner_name;
+                    
+            owner_name = rsbac_kmalloc(32);
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(owner))
+              sprintf(owner_name, "%u/%u",
+                      RSBAC_UID_SET(owner),
+                      RSBAC_UID_NUM(owner));
+            else
+#endif
+              sprintf(owner_name, "%u", RSBAC_UID_NUM(owner));
+    #ifdef CONFIG_RSBAC_SOFTMODE
+            if(rsbac_softmode)
+              rsbac_printk(KERN_INFO "rsbac_adf_request(): request %s, pid %u, ppid %u, prog_name %s%s, uid %s, %s%starget_type %s, tid %s, attr %s, value %s, result %s (Softmode) by%s\n",
+                           request_name, pid_nr(caller_pid), pid_nr(parent_pid), command, program_path, owner_name, audit_uid_name, remote_ip_name, target_type_name, target_id_name, attr_name, attr_val_name, res_name, res_mods);
+            else
+    #endif
+              rsbac_printk(KERN_INFO "rsbac_adf_request(): request %s, pid %u, ppid %u, prog_name %s%s, uid %s, %s%starget_type %s, tid %s, attr %s, value %s, result %s by%s\n",
+                           request_name, pid_nr(caller_pid), pid_nr(parent_pid), command, program_path, owner_name, audit_uid_name, remote_ip_name, target_type_name, target_id_name, attr_name, attr_val_name, res_name, res_mods);
+            rsbac_kfree(owner_name);
+          }
+        if (parent_pid)
+          put_pid(parent_pid);
+        /* rsbac_kfree all helper mem */
+        rsbac_kfree(request_name);
+        rsbac_kfree(res_name);
+        rsbac_kfree(res_mods);
+        rsbac_kfree(target_type_name);
+        rsbac_kfree(target_id_name);
+        rsbac_kfree(program_path);
+        rsbac_kfree(attr_name);
+        rsbac_kfree(attr_val_name);
+#ifdef CONFIG_RSBAC_NET_OBJ
+        rsbac_kfree(remote_ip_name);
+#endif
+        rsbac_kfree(audit_uid_name);
+      }
+
+/* UNDEFINED must never be returned -> change result */
+    if(result == UNDEFINED)
+      result = NOT_GRANTED;
+
+/* count */
+    rsbac_adf_request_count[target]++;
+#ifdef CONFIG_RSBAC_XSTATS
+    rsbac_adf_request_xcount[target][request]++;
+#endif
+
+/* return result */
+    #ifdef CONFIG_RSBAC_SOFTMODE
+    if(rsbac_softmode && !rsbac_internal)
+      return DO_NOT_CARE;
+    else
+    #endif
+    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+      return ret_result;
+    #else
+      return result; /* change for debugging! */
+    #endif
+  } /* end of rsbac_adf_request_int() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function is called by the AEF to get all aci set correctly. */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* It returns 0 on success and an error from error.h otherwise.              */
+
+EXPORT_SYMBOL(rsbac_adf_set_attr);
+int  rsbac_adf_set_attr(
+                      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)
+  {
+    union rsbac_target_id_t i_tid;
+    rsbac_uid_t owner;
+    int   error = 0;
+    rsbac_request_vector_t	request_vector;
+    rsbac_boolean_t do_log = FALSE;
+    rsbac_boolean_t log_on_request = TRUE;
+    union rsbac_attribute_value_t i_attr_val;
+#ifdef CONFIG_RSBAC_IND_LOG
+    union rsbac_attribute_value_t i_attr_val2;
+    enum rsbac_log_level_t log_level;
+#endif
+#ifdef CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT
+    struct vfsmount * mnt_p;
+#endif
+
+/* No attribute setting possible before init (called at boot time) */
+
+   if (unlikely(!rsbac_is_initialized()))
+      return 0;
+
+/* kernel (pid 0) is ignored */
+    if (   !pid_nr(caller_pid)
+        #if defined(CONFIG_RSBAC_LOG_REMOTE)
+        || (caller_pid == rsbaclogd_pid)
+        #endif
+       )
+      return 0;
+/* Checking base values */
+    if(unlikely(   request >= R_NONE
+                || target > T_NONE
+                || new_target > T_NONE
+                || attr > A_none)
+               )
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_adf_set_attr(): called with invalid request, target or attribute\n");
+        return(-RSBAC_EINVALIDVALUE);
+      }
+
+    if (unlikely(in_interrupt()))
+      {
+        char * request_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+        if(request_name)
+          {
+            get_request_name(request_name, request);
+            printk(KERN_WARNING "rsbac_adf_set_attr(): called from interrupt: request %s, pid %u(%s), attr_val %u!\n",
+                   request_name, pid_nr(caller_pid), current->comm, attr_val.dummy);
+            rsbac_kfree(request_name);
+          }
+        else
+          {
+            printk(KERN_WARNING "rsbac_adf_set_attr(): called from interrupt: request %u, pid %u(%s)!\n",
+                   request, pid_nr(caller_pid), current->comm);
+          }
+        dump_stack();
+        return -RSBAC_EFROMINTERRUPT;
+      }
+
+    request_vector = RSBAC_REQUEST_VECTOR(request);
+
+/* Getting basic information about this adf_set_attr-call */
+
+    owner = RSBAC_NO_USER;
+    /* only useful for real process, not idle or init */
+    if (pid_nr(caller_pid) > 1)
+      {
+        error = rsbac_get_owner(&owner);
+        if(error)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_adf_set_attr(): caller_pid %i, RSBAC not initialized, returning 0",
+                   pid_nr(caller_pid));
+            return 0;      /* Startup-Sequence (see above) */
+          }
+      }
+    else /* caller_pid = 1  -> init -> owner = root */
+      owner = 0;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if ((attr == A_owner) && (RSBAC_UID_SET(attr_val.owner) > RSBAC_UM_VIRTUAL_MAX))
+      attr_val.owner = RSBAC_GEN_UID(RSBAC_UID_SET(owner), attr_val.owner);
+    else
+    if ((attr == A_group) && (RSBAC_GID_SET(attr_val.group) > RSBAC_UM_VIRTUAL_MAX))
+      attr_val.group = RSBAC_GEN_GID(RSBAC_UID_SET(owner), attr_val.group);
+#else
+    if (attr == A_owner)
+      attr_val.owner = RSBAC_UID_NUM(attr_val.owner);
+    else
+    if (attr == A_group)
+      attr_val.group = RSBAC_GID_NUM(attr_val.group);
+#endif
+
+/*************************************************/
+/* General work for all modules - before modules */
+#if defined(CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT) || defined(CONFIG_RSBAC_FD_CACHE)
+    switch (target) {
+      case T_DIR:
+#if defined(CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT)
+        if ((mnt_p = rsbac_get_vfsmount(tid.file.device))
+            && (   (mnt_p->mnt_sb->s_magic == NFS_SUPER_MAGIC)
+                || (mnt_p->mnt_sb->s_magic == CODA_SUPER_MAGIC)
+                || (mnt_p->mnt_sb->s_magic == NCP_SUPER_MAGIC)
+                || (mnt_p->mnt_sb->s_magic == SMB_SUPER_MAGIC)
+               )
+        ) {
+          error = 0;
+          goto log;
+        }
+#endif
+
+/* Ensure that there are no leftover attributes */
+        if (request == R_CREATE) {
+          rsbac_remove_target(new_target, new_tid);
+        }
+
+#if defined(CONFIG_RSBAC_FD_CACHE)
+        else if (request == R_RENAME && RSBAC_MAJOR(tid.file.device) > 1) {
+          /* invalidate FD cache for this device, if parent dir has changed */
+          if (   attr == A_old_dir_inode_p
+              && attr_val.old_dir_inode_p
+              && tid.file.dentry_p
+              && tid.file.dentry_p->d_parent
+              && tid.file.dentry_p->d_parent->d_inode) {
+            if (attr_val.old_dir_inode_p->i_ino != tid.file.dentry_p->d_parent->d_inode->i_ino) {
+              rsbac_pr_debug(fdcache, "moved DIR item device %02u:%02u inode %lu from dir %u to dir %u, invalidate cache for device\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode, attr_val.old_dir_inode_p->i_ino, tid.file.dentry_p->d_parent->d_inode->i_ino);
+              rsbac_fd_cache_invalidate_device(tid.file.device);
+            } else {
+              rsbac_pr_debug(fdcache, "renamed DIR item device %02u:%02u inode %lu inside dir %u, do not invalidate cache for device\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode, attr_val.old_dir_inode_p->i_ino);
+            }
+          } else {
+            rsbac_pr_debug(fdcache, "moved DIR item device %02u:%02u inode %lu without parent dir info, invalidate cache for device\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode);
+            rsbac_fd_cache_invalidate_device(tid.file.device);
+          }
+        }
+#endif
+        break;
+
+      case T_FILE:
+      case T_FIFO:
+      case T_SYMLINK:
+      case T_UNIXSOCK:
+#if defined(CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT)
+        if ((mnt_p = rsbac_get_vfsmount(tid.file.device))
+            && (   (mnt_p->mnt_sb->s_magic == NFS_SUPER_MAGIC)
+                || (mnt_p->mnt_sb->s_magic == CODA_SUPER_MAGIC)
+                || (mnt_p->mnt_sb->s_magic == NCP_SUPER_MAGIC)
+                || (mnt_p->mnt_sb->s_magic == SMB_SUPER_MAGIC)
+               )
+          ) {
+          error = 0;
+          goto log;
+        }
+#endif
+
+#if defined(CONFIG_RSBAC_FD_CACHE)
+        if (request == R_RENAME && RSBAC_MAJOR(tid.file.device) > 1) {
+          /* invalidate FD cache entry, if parent dir has changed */
+          if (   attr == A_old_dir_inode_p
+              && attr_val.old_dir_inode_p
+              && tid.file.dentry_p
+              && tid.file.dentry_p->d_parent
+              && tid.file.dentry_p->d_parent->d_inode) {
+            if (attr_val.old_dir_inode_p->i_ino != tid.file.dentry_p->d_parent->d_inode->i_ino) {
+              rsbac_pr_debug(fdcache, "moved FD item device %02u:%02u inode %lu from dir %u to dir %u, invalidate cache item\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode, attr_val.old_dir_inode_p->i_ino, tid.file.dentry_p->d_parent->d_inode->i_ino);
+              rsbac_fd_cache_invalidate(&tid.file);
+            } else {
+              rsbac_pr_debug(fdcache, "renamed FD item device %02u:%02u inode %lu inside dir %u, do not invalidate cache item\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode, attr_val.old_dir_inode_p->i_ino);
+            }
+          } else {
+            rsbac_pr_debug(fdcache, "moved FD item device %02u:%02u inode %lu without parent dir info, invalidate cache item\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode);
+            rsbac_fd_cache_invalidate(&tid.file);
+          }
+        }
+#endif
+        break;
+
+      case T_PROCESS:
+        if (   (request == R_CLONE)
+            && !new_tid.process
+           ) {
+		rsbac_printk(KERN_WARNING "rsbac_adf_set_attr(): tid for new process in CLONE is NULL!\n");
+		return -RSBAC_EINVALIDTARGET;
+        }
+        break;
+
+      default:
+        break;
+    }
+#endif
+
+/**********************************************************/
+/* calling all decision modules, building a common result */
+
+
+#ifdef CONFIG_RSBAC_DEBUG
+/* first, check for valid request/target combination      */
+error |= rsbac_adf_set_attr_check(request,
+                                  caller_pid,
+                                  target,
+                                  tid,
+                                  new_target,
+                                  new_tid,
+                                  attr,
+                                  attr_val,
+                                  owner);
+if(error)
+  goto general_work;
+#endif
+
+/******* MAC ********/
+#if defined(CONFIG_RSBAC_MAC)
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+if (rsbac_switch_mac)
+#endif
+  if(request_vector & RSBAC_MAC_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_mac(request,
+                                  caller_pid,
+                                  target,
+                                  tid,
+                                  new_target,
+                                  new_tid,
+                                  attr,
+                                  attr_val,
+                                  owner);
+#endif  /* MAC */
+
+/******* DAZ ********/
+#ifdef CONFIG_RSBAC_DAZ
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+if (rsbac_switch_daz)
+#endif
+  if(request_vector & RSBAC_DAZ_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_daz (request,
+                                  caller_pid,
+                                  target,
+                                  tid,
+                                  new_target,
+                                  new_tid,
+                                  attr,
+                                  attr_val,
+                                  owner);
+#endif  /* DAZ */
+
+/******* RC ********/
+#ifdef CONFIG_RSBAC_RC
+#ifdef CONFIG_RSBAC_SWITCH_RC
+if (rsbac_switch_rc)
+#endif
+  error |= rsbac_adf_set_attr_rc (request,
+                                  caller_pid,
+                                  target,
+                                  tid,
+                                  new_target,
+                                  new_tid,
+                                  attr,
+                                  attr_val,
+                                  owner);
+#endif  /* RC */
+
+/****** AUTH *******/
+#ifdef CONFIG_RSBAC_AUTH
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+if (rsbac_switch_auth)
+#endif
+  if(request_vector & RSBAC_AUTH_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_auth(request,
+                                   caller_pid,
+                                   target,
+                                   tid,
+                                   new_target,
+                                   new_tid,
+                                   attr,
+                                   attr_val,
+                                   owner);
+#endif  /* AUTH */
+
+/****** CAP *******/
+#ifdef CONFIG_RSBAC_CAP
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+if (rsbac_switch_cap)
+#endif
+  if(request_vector & RSBAC_CAP_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_cap (request,
+                                   caller_pid,
+                                   target,
+                                   tid,
+                                   new_target,
+                                   new_tid,
+                                   attr,
+                                   attr_val,
+                                   owner);
+#endif  /* CAP */
+
+/****** JAIL *******/
+#ifdef CONFIG_RSBAC_JAIL
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+if (rsbac_switch_jail)
+#endif
+  if(request_vector & RSBAC_JAIL_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_jail(request,
+                                   caller_pid,
+                                   target,
+                                   tid,
+                                   new_target,
+                                   new_tid,
+                                   attr,
+                                   attr_val,
+                                   owner);
+#endif  /* JAIL */
+
+/****** RES *******/
+#ifdef CONFIG_RSBAC_RES
+#ifdef CONFIG_RSBAC_SWITCH_RES
+if (rsbac_switch_res)
+#endif
+  if(request_vector & RSBAC_RES_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_res (request,
+                                   caller_pid,
+                                   target,
+                                   tid,
+                                   new_target,
+                                   new_tid,
+                                   attr,
+                                   attr_val,
+                                   owner);
+#endif  /* RES */
+
+/******* UDF ********/
+#ifdef CONFIG_RSBAC_UDF
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+if (rsbac_switch_udf)
+#endif
+  if(request_vector & RSBAC_UDF_SET_ATTR_VECTOR)
+    error |= rsbac_adf_set_attr_udf (request,
+                                  caller_pid,
+                                  target,
+                                  tid,
+                                  new_target,
+                                  new_tid,
+                                  attr,
+                                  attr_val,
+                                  owner);
+#endif  /* UDF */
+
+/****** REG *******/
+#ifdef CONFIG_RSBAC_REG
+  error |= rsbac_adf_set_attr_reg (request,
+                                   caller_pid,
+                                   target,
+                                   tid,
+                                   new_target,
+                                   new_tid,
+                                   attr,
+                                   attr_val,
+                                   owner);
+#endif  /* REG */
+
+/* General work for all modules (after set_attr call) */
+#ifdef CONFIG_RSBAC_DEBUG
+general_work:
+#endif
+    switch(request)
+      {
+        /* remove deleted item from rsbac data */
+        case R_DELETE :
+            switch (target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_SYMLINK:
+                case T_UNIXSOCK:
+                  /* Only remove file/fifo target on deletion of last link */
+                  if (   (attr == A_nlink)
+                      && (attr_val.nlink > 1)
+                     )
+                     break;
+                  /* fall through */
+                case T_DIR:
+                  rsbac_remove_target(target,tid);
+                  break;
+                case T_IPC:
+                  /* shm removal delayed and removed directly, when destroyed */
+                  if(tid.ipc.type != I_shm)
+                    rsbac_remove_target(target,tid);
+                  break;
+                default:
+                  break;
+              }
+            break;
+
+        case R_CLONE:
+            switch (target)
+              {
+                case T_PROCESS:
+                  #if defined(CONFIG_RSBAC_IND_PROG_LOG)
+                  /* get program based log from old process */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_log_program_based,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_log_program_based);
+                    }
+                  else
+                    { /* only set, if not default value 0 */
+                      if(i_attr_val.log_program_based)
+                        {
+                          /* set program based log for new process */
+                          if (rsbac_set_attr(SW_GEN, new_target,
+                                             new_tid,
+                                             A_log_program_based,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_log_program_based);
+                            }
+                        }
+                    }
+                  #endif
+                  #if defined(CONFIG_RSBAC_FAKE_ROOT_UID)
+                  /* get fake_root_uid from old process */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_fake_root_uid,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_fake_root_uid);
+                    }
+                  else
+                    { /* only set, of not default value 0 */
+                      if(i_attr_val.fake_root_uid)
+                        {
+                          /* set program based log for new process */
+                          if (rsbac_set_attr(SW_GEN, new_target,
+                                             new_tid,
+                                             A_fake_root_uid,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_fake_root_uid);
+                            }
+                        }
+                    }
+                  #endif
+                  #if defined(CONFIG_RSBAC_NET)
+                  /* get remote_ip from old process */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_remote_ip,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_remote_ip);
+                    }
+                  else
+                    { /* only set, of not default value 0 */
+                      if(i_attr_val.remote_ip)
+                        {
+                          /* set program based log for new process */
+                          if (rsbac_set_attr(SW_GEN, new_target,
+                                             new_tid,
+                                             A_remote_ip,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_remote_ip);
+                            }
+                        }
+                    }
+                  #endif
+			/* get kernel_thread from old process */
+			if (rsbac_get_attr(SW_GEN,
+					target,
+					tid,
+					A_kernel_thread,
+					&i_attr_val, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_set_attr()",
+						A_kernel_thread);
+			} else {
+				if (i_attr_val.kernel_thread) {
+					if (rsbac_set_attr(SW_GEN, new_target,
+							new_tid,
+							A_kernel_thread,
+							i_attr_val)) {
+						rsbac_ds_set_error
+							("rsbac_adf_set_attr()",
+							 A_kernel_thread);
+					}
+				}
+			}
+
+                  /* get audit_uid from old process */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_audit_uid,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_audit_uid);
+                    }
+                  else
+                    { /* only set, of not default value NO_USER */
+                      if(i_attr_val.audit_uid != RSBAC_NO_USER)
+                        {
+                          /* set audit uid for new process */
+                          if (rsbac_set_attr(SW_GEN,
+                                             new_target,
+                                             new_tid,
+                                             A_audit_uid,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_audit_uid);
+                            }
+                        }
+                    }
+                  /* get auid_exempt from old process */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_auid_exempt,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_auid_exempt);
+                    }
+                  else
+                    { /* only set, of not default value NO_USER */
+                      if(i_attr_val.auid_exempt != RSBAC_NO_USER)
+                        {
+                          /* set program based log for new process */
+                          if (rsbac_set_attr(SW_GEN,
+                                             new_target,
+                                             new_tid,
+                                             A_auid_exempt,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_auid_exempt);
+                            }
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_UM_VIRTUAL
+                  /* set vset of new process */
+                  i_attr_val.vset = RSBAC_UID_SET(owner);
+                  if(i_attr_val.vset)
+                    {
+                      /* set vset for new process */
+                      if (rsbac_set_attr(SW_GEN, new_target,
+                                         new_tid,
+                                         A_vset,
+                                         i_attr_val))
+                        {
+                          rsbac_ds_set_error("rsbac_adf_set_attr()", A_vset);
+                        }
+                    }
+                  #endif
+#if defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+                  /* copy program_file */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_program_file,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_program_file);
+                    }
+                  else
+                    { /* set program file for new process */
+                      if (rsbac_set_attr(SW_GEN, new_target,
+                                         new_tid,
+                                         A_program_file,
+                                         i_attr_val))
+                        {
+                          rsbac_ds_set_error("rsbac_adf_set_attr()", A_program_file);
+                        }
+                    }
+#endif
+                  break;
+
+                default:
+                  break;
+              }
+            break;
+
+	case R_CLOSE:
+		switch (target) {
+#if 0
+		case T_IPC:
+			if(   (tid.ipc.type == I_anonunix)
+                           && (   (attr != A_nlink)
+                               || (attr_val.nlink <= 1)
+                              )
+                          )
+				rsbac_remove_target(target, tid);
+			break;
+#endif
+#ifdef CONFIG_RSBAC_NET_OBJ
+		case T_NETOBJ:
+			rsbac_remove_target(target, tid);
+			break;
+#endif
+		default:
+			break;
+		}
+		break;
+
+#if 0
+	case R_CREATE:
+		switch (target) {
+		case T_IPC:
+			if((tid.ipc.type != I_sem) && !tid.ipc.id.id_nr)
+				error |= -RSBAC_EINVALIDVALUE;
+			break;
+		default:
+			break;
+		}
+		break;
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+        case R_ACCEPT:
+            switch (target)
+              {
+                case T_NETOBJ:
+                  /* store remote IP */
+                  if(   tid.netobj.sock_p
+                     && tid.netobj.sock_p->ops
+                     && tid.netobj.sock_p->sk
+                     && (tid.netobj.sock_p->ops->family == AF_INET)
+                    )
+                    {
+                      i_tid.process = caller_pid;
+                      i_attr_val.remote_ip = inet_sk(tid.netobj.sock_p->sk)->inet_daddr;
+                      /* set program based log for new process */
+                      if (rsbac_set_attr(SW_GEN,
+                                         T_PROCESS,
+                                         i_tid,
+                                         A_remote_ip,
+                                         i_attr_val))
+                        {
+                          rsbac_ds_set_error("rsbac_adf_set_attr()", A_remote_ip);
+                        }
+                    }
+                  break;
+
+                default:
+                  break;
+              }
+            break;
+#endif /* CONFIG_RSBAC_NET_OBJ */
+
+        case R_EXECUTE :
+            switch (target)
+              {
+                case T_FILE:
+                  #if defined(CONFIG_RSBAC_IND_PROG_LOG)
+                  /* get program based log from file */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_log_program_based,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_log_program_based);
+                    }
+                  else
+                    {
+                      /* set program based log for process */
+                      i_tid.process = caller_pid;
+                      if (rsbac_set_attr(SW_GEN, T_PROCESS,
+                                         i_tid,
+                                         A_log_program_based,
+                                         i_attr_val))
+                        {
+                          rsbac_ds_set_error("rsbac_adf_set_attr()", A_log_program_based);
+                        }
+                    }
+                  #endif
+                  #if defined(CONFIG_RSBAC_FAKE_ROOT_UID)
+                  /* get fake_root_uid from file */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_fake_root_uid,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_fake_root_uid);
+                    }
+                  else
+                    {
+                      /* set fake_root_uid for process */
+                      if(i_attr_val.fake_root_uid)
+                        {
+                          i_tid.process = caller_pid;
+                          if (rsbac_set_attr(SW_GEN, T_PROCESS,
+                                             i_tid,
+                                             A_fake_root_uid,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_fake_root_uid);
+                            }
+                        }
+                    }
+                  #endif
+                  #ifdef CONFIG_RSBAC_UM_VIRTUAL
+                  /* get vset from file */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_vset,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_vset);
+                    }
+                  else
+                    {
+                      /* set vset for process */
+                      if(i_attr_val.vset != RSBAC_UM_VIRTUAL_KEEP)
+                        {
+                          i_tid.process = caller_pid;
+                          if (rsbac_set_attr(SW_GEN, T_PROCESS,
+                                             i_tid,
+                                             A_vset,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_fake_root_uid);
+                            }
+                        }
+                    }
+                  #endif
+#if defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+                  /* remember executed file */
+                  i_tid.process = caller_pid;
+                  i_attr_val.program_file = tid.file;
+                  if (rsbac_set_attr(SW_GEN,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_program_file,
+                                     i_attr_val))
+                    {
+                      rsbac_pr_set_error(A_program_file);
+                    }
+#endif
+                  /* get auid_exempt from file */
+                  if (rsbac_get_attr(SW_GEN,
+                                     target,
+                                     tid,
+                                     A_auid_exempt,
+                                     &i_attr_val,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr()", A_auid_exempt);
+                    }
+                  else
+                    {
+                      if(i_attr_val.auid_exempt != RSBAC_NO_USER)
+                        {
+                          /* set auid_exempt for process */
+                          i_tid.process = caller_pid;
+                          if (rsbac_set_attr(SW_GEN, T_PROCESS,
+                                             i_tid,
+                                             A_auid_exempt,
+                                             i_attr_val))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr()", A_auid_exempt);
+                            }
+                        }
+                    }
+                  break;
+
+                default:
+                  break;
+              }
+            break;
+
+        default:
+            break;
+      }
+
+#if defined(CONFIG_RSBAC_DEBUG) && defined(CONFIG_RSBAC_NET)
+    if(    rsbac_debug_adf_net
+       && (   (target == T_NETDEV)
+           || (target == T_NETTEMP)
+           || (target == T_NETOBJ)
+          )
+      )
+      do_log = TRUE;
+#endif
+
+/* log based on process owner */
+#ifdef CONFIG_RSBAC_IND_USER_LOG
+    i_tid.user = owner;
+    if (rsbac_get_attr(SW_GEN,
+                       T_USER,
+                       i_tid,
+                       A_log_user_based,
+                       &i_attr_val,
+                       FALSE))
+      {
+        rsbac_ds_get_error("rsbac_adf_set_attr()", A_log_user_based);
+      }
+    else
+      {
+        if(((rsbac_request_vector_t) 1 << request) & i_attr_val.log_user_based) 
+          do_log = TRUE;
+      }
+#endif /* CONFIG_RSBAC_IND_USER_LOG */
+
+/* log based on program */
+#ifdef CONFIG_RSBAC_IND_PROG_LOG
+    if(!do_log)
+      {
+        i_tid.process = caller_pid;
+        if (rsbac_get_attr(SW_GEN,
+                           T_PROCESS,
+                           i_tid,
+                           A_log_program_based,
+                           &i_attr_val,
+                           FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_set_attr()", A_log_program_based);
+          }
+        else
+          {
+            if(((rsbac_request_vector_t) 1 << request) & i_attr_val.log_program_based) 
+              do_log = TRUE;
+          }
+      }
+#endif /* CONFIG_RSBAC_IND_PROG_LOG */
+
+
+/* logging request on info level, if requested by file/dir/dev attributes */
+/* log_array_low/high, or, if that is requested, if enabled for this request */
+/* type (attributes state level, or that request based level is to be taken) */
+/* loglevel 2: log everything */
+/* loglevel 1: log, if denied */
+/* loglevel 0: log nothing */
+
+#ifdef CONFIG_RSBAC_IND_LOG /* only if individual logging is enabled */
+    /* if file/dir/dev, depend log on log_arrays */
+    /* (but not for file.device = 0) */
+    /* log_on_request is TRUE */
+    if(!do_log)
+      {
+        if(   (   (   (target == T_FILE)
+                   || (target == T_DIR)
+                   || (target == T_FIFO)
+                   || (target == T_SYMLINK)
+                  )
+               && RSBAC_MAJOR(tid.file.device)
+               && RSBAC_MINOR(tid.file.device)
+              )
+           || (target == T_DEV)
+          )
+          {
+            if (rsbac_get_attr(SW_GEN,
+                               target,
+                               tid,
+                               A_log_array_low,
+                               &i_attr_val,
+                               FALSE))
+              {
+                rsbac_ds_get_error("rsbac_adf_set_attr()", A_log_array_low);
+              }
+            else
+              {
+                if (rsbac_get_attr(SW_GEN,
+                                   target,
+                                   tid,
+                                   A_log_array_high,
+                                   &i_attr_val2,
+                                   FALSE))
+                  {
+                    rsbac_ds_get_error("rsbac_adf_set_attr()", A_log_array_high);
+                  }
+                else
+                  { /* ll = low-bit for request | (high-bit for request as bit 1) */
+                    log_level =   ((i_attr_val.log_array_low   >> request) & 1)
+                              | ( ((i_attr_val2.log_array_high >> request) & 1) << 1);
+                    if (   log_level == LL_full
+                        || (   log_level == LL_denied
+                            && error) )
+                      {
+                        do_log = TRUE;
+                      }
+                    if(log_level != LL_request)
+                      log_on_request = FALSE;
+                  }
+              }
+          }
+      }
+#endif /* CONFIG_RSBAC_IND_LOG */
+
+#ifdef CONFIG_RSBAC_NO_DECISION_ON_NETMOUNT
+log:
+#endif
+    /* if enabled, try request based log level */
+    if (log_on_request
+        && (   rsbac_log_levels[request][target] == LL_full
+            || (   rsbac_log_levels[request][target] == LL_denied
+                && error) ) )
+      do_log = TRUE;
+
+    if(do_log)
+      {
+        char * request_name;
+        char * target_type_name;
+        char * new_target_type_name;
+        char * target_id_name;
+        char * new_target_id_name;
+        char * attr_name;
+        rsbac_uid_t audit_uid;
+        char * audit_uid_name;
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+        rsbac_pseudo_t  pseudo = 0;
+#endif
+
+        /* Get process audit_uid */
+        i_tid.process = caller_pid;
+        if (rsbac_get_attr(SW_GEN,T_PROCESS,i_tid,A_audit_uid,&i_attr_val,FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_set_attr()", A_audit_uid);
+            return -RSBAC_EREADFAILED;  /* something weird happened */
+          }
+        audit_uid_name = rsbac_kmalloc(32);
+        audit_uid = i_attr_val.audit_uid;
+        if(audit_uid == RSBAC_NO_USER) {
+          audit_uid_name[0] = 0;
+          audit_uid = owner;
+        } else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_UID_SET(audit_uid))
+            sprintf(audit_uid_name, "audit uid %u/%u, ",
+                    RSBAC_UID_SET(audit_uid),
+                    RSBAC_UID_NUM(audit_uid));
+          else
+#endif
+          sprintf(audit_uid_name, "audit uid %u, ", RSBAC_UID_NUM(audit_uid));
+        }
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+        /* Get owner's logging pseudo */
+        i_tid.user = audit_uid;
+        if (rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val,FALSE))
+          {
+            rsbac_ds_get_error("rsbac_adf_set_attr()", A_pseudo);
+            return -RSBAC_EREADFAILED;  /* something weird happened */
+          }
+        /* if pseudo is not registered, return attribute value is 0 (see later) */
+        pseudo = i_attr_val.pseudo;
+#endif
+
+        /* rsbac_kmalloc all memory */
+        request_name = rsbac_kmalloc(32);
+        target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+        new_target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+        #ifdef CONFIG_RSBAC_LOG_FULL_PATH
+        target_id_name
+         = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+        new_target_id_name
+         = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+           /* max. path name len + some extra */
+        #else
+        target_id_name = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+        new_target_id_name = rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+           /* max. file name len + some extra */
+        #endif
+        attr_name = rsbac_kmalloc(32);
+
+        /* Getting basic information about this request */
+        request_name[0] = (char) 0;
+        target_type_name[0] = (char) 0;
+        target_id_name[0] = (char) 0;
+        new_target_type_name[0] = (char) 0;
+        new_target_id_name[0] = (char) 0;
+        attr_name[0] = (char) 0;
+        get_request_name(request_name, request);
+        get_target_name(target_type_name, target, target_id_name, tid);
+        get_target_name(new_target_type_name, new_target,
+                        new_target_id_name, new_tid);
+        get_attribute_name(attr_name, attr);
+
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+        if(pseudo)
+          rsbac_printk(KERN_INFO
+                       "rsbac_adf_set_attr(): request %s, pid %u, pseudo %u, target_type %s, tid %s, new_target_type %s, new_tid %s, attr %s, value %u, error %i\n",
+                       request_name, pid_nr(caller_pid), pseudo, target_type_name, target_id_name,
+                       new_target_type_name, new_target_id_name, attr_name, attr_val.dummy, error);
+        else
+#endif
+        {
+          char * owner_name = rsbac_kmalloc(32);
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_UID_SET(owner))
+            sprintf(owner_name, "%u/%u",
+                    RSBAC_UID_SET(owner),
+                    RSBAC_UID_NUM(owner));
+          else
+#endif
+            sprintf(owner_name, "%u", RSBAC_UID_NUM(owner));
+
+          rsbac_printk(KERN_INFO
+                       "rsbac_adf_set_attr(): request %s, pid %u, uid %s, %starget_type %s, tid %s, new_target_type %s, new_tid %s, attr %s, value %u, error %i\n",
+                       request_name, pid_nr(caller_pid), owner_name, audit_uid_name, target_type_name, target_id_name,
+                       new_target_type_name, new_target_id_name, attr_name, attr_val.dummy, error);
+          rsbac_kfree(owner_name);
+          rsbac_kfree(audit_uid_name);
+        }
+        /* rsbac_kfree all helper mem */
+        rsbac_kfree(request_name);
+        rsbac_kfree(target_type_name);
+        rsbac_kfree(new_target_type_name);
+        rsbac_kfree(target_id_name);
+        rsbac_kfree(new_target_id_name);
+        rsbac_kfree(attr_name);
+      }
+
+/* count */
+    rsbac_adf_set_attr_count[target]++;
+#ifdef CONFIG_RSBAC_XSTATS
+    rsbac_adf_set_attr_xcount[target][request]++;
+#endif
+
+    return(error);
+  } /* end of rsbac_adf_set_attr() */
+
+
+/****************
+ *
+ * Secure Delete
+ *
+ ****************/
+
+#ifdef CONFIG_RSBAC_SECDEL
+
+/* open_by_dentry */
+/* This is done by hand (copy from rsbac_read_open), because system calls */
+/* are currently blocked by rsbac */
+
+static int open_by_dentry(struct dentry * file_dentry_p, struct file * file_p)
+  {
+    int tmperr;
+
+    if ( !(S_ISREG(file_dentry_p->d_inode->i_mode)) )
+      { /* this is not a file! -> error! */
+        rsbac_printk(KERN_WARNING
+               "open_by_dentry(): expected file is not a file!\n");
+        return -RSBAC_EWRITEFAILED;
+      }
+    /* Now we fill the file structure, and */
+    /* if there is an open func, use it, otherwise ignore */
+    if ((tmperr = init_private_file(file_p, file_dentry_p, O_WRONLY | O_SYNC)))
+      {
+        rsbac_printk(KERN_WARNING
+               "open_by_dentry(): could not open file!\n");
+        return -RSBAC_EWRITEFAILED;
+      }
+    /* Without a write function we get into troubles -> error */
+    if ((!file_p->f_op) || (!file_p->f_op->write_iter))
+      {
+        rsbac_printk(KERN_WARNING
+               "open_by_dentry(): file write_iter function missing!\n");
+        return -RSBAC_EWRITEFAILED;
+      }
+    return 0;
+  }
+
+/*
+ **********************
+ * Secure File Truncation
+ */
+static int do_rsbac_sec_trunc(struct dentry * dentry_p,
+                              loff_t new_len,
+                              loff_t old_len,
+                              u_int may_sync)
+  {
+    int                           err = 0;
+    rsbac_boolean_t               need_overwrite = FALSE;
+
+    if (unlikely(!rsbac_is_initialized()))
+      return 0;
+    /* security checks */
+    if(   !dentry_p
+       || !dentry_p->d_inode)
+      return -RSBAC_EINVALIDPOINTER;
+    if(!S_ISREG(dentry_p->d_inode->i_mode))
+      return -RSBAC_EINVALIDTARGET;
+    if(dentry_p->d_sb->s_magic == PIPEFS_MAGIC)
+      return 0;
+    if(new_len >= old_len)
+      return 0;
+
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "do_rsbac_sec_trunc(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return -RSBAC_EFROMINTERRUPT;
+      }
+
+    if(dentry_p->d_inode && !rsbac_writable(dentry_p->d_inode->i_sb))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_write)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "do_rsbac_sec_trunc(): ignoring file %lu on network device %02u:%02u!\n",
+                   dentry_p->d_inode->i_ino,
+                   MAJOR(dentry_p->d_inode->i_sb->s_dev),
+                   MINOR(dentry_p->d_inode->i_sb->s_dev));
+          }
+#endif
+        return 0;
+      }
+
+    /******* FF ********/
+    #ifdef CONFIG_RSBAC_FF
+    #ifdef CONFIG_RSBAC_SWITCH_FF
+    if (rsbac_switch_ff)
+    #endif
+      /* no need to call module, if already need_overwrite */
+      if(!need_overwrite)
+        need_overwrite = rsbac_need_overwrite_ff(dentry_p);
+    #endif  /* FF */
+
+    /******* RC ********/
+    #ifdef CONFIG_RSBAC_RC
+    #ifdef CONFIG_RSBAC_SWITCH_RC
+    if (rsbac_switch_rc)
+    #endif
+      /* no need to call module, if already need_overwrite */
+      if(!need_overwrite)
+        need_overwrite = rsbac_need_overwrite_rc(dentry_p);
+    #endif  /* RC */
+
+    /****** RES *******/
+    #ifdef CONFIG_RSBAC_RES
+    #ifdef CONFIG_RSBAC_SWITCH_RES
+    if (rsbac_switch_res)
+    #endif
+      /* no need to call module, if already need_overwrite */
+      if(!need_overwrite)
+        need_overwrite = rsbac_need_overwrite_res(dentry_p);
+    #endif  /* RES */
+
+    /****** REG *******/
+    #ifdef CONFIG_RSBAC_REG
+    if(!need_overwrite)
+      need_overwrite = rsbac_need_overwrite_reg(dentry_p);
+    #endif  /* REG */
+
+    if(need_overwrite)
+      {
+        char            * buffer;
+        struct file       file;
+        int               tmperr = 0;
+        mm_segment_t      oldfs;
+
+        buffer = rsbac_kmalloc(RSBAC_SEC_DEL_CHUNK_SIZE);
+        if(!buffer)
+          return -RSBAC_ENOMEM;
+
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_write)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_sec_trunc(): zeroing of file %lu on device %02u:%02u from byte %lu to %lu!\n",
+                   dentry_p->d_inode->i_ino,
+                   MAJOR(dentry_p->d_inode->i_sb->s_dev),
+                   MINOR(dentry_p->d_inode->i_sb->s_dev),
+                   (u_long) new_len,
+                   (u_long) old_len-1);
+          }
+#endif
+        /* open */
+        err = open_by_dentry(dentry_p, &file);
+        if(err)
+          {
+            rsbac_kfree(buffer);
+            return err;
+          }
+
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_write)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_sec_trunc(): file %lu on device %02u:%02u is open, seeking to %lu!\n",
+                   dentry_p->d_inode->i_ino,
+                   MAJOR(dentry_p->d_inode->i_sb->s_dev),
+                   MINOR(dentry_p->d_inode->i_sb->s_dev),
+                   (u_long) new_len);
+          }
+#endif
+
+        /* OK, now we can start writing */
+
+        /* Set current user space to kernel space, because write() reads
+         * from user space
+         */
+        oldfs = get_fs();
+        set_fs(KERNEL_DS);
+
+          { /* taken from fs/read_write.c */
+            file.f_pos = new_len;
+            file.f_version = 0;
+          }
+        memset(buffer,0,RSBAC_SEC_DEL_CHUNK_SIZE);
+
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_write)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_sec_trunc(): file %lu on device %02u:%02u is positioned, starting to write!\n",
+                   dentry_p->d_inode->i_ino,
+                   MAJOR(dentry_p->d_inode->i_sb->s_dev),
+                   MINOR(dentry_p->d_inode->i_sb->s_dev));
+          }
+#endif
+	while (new_len < old_len)
+	{
+		struct iovec iov = { .iov_base = buffer,
+				.iov_len = rsbac_min(RSBAC_SEC_DEL_CHUNK_SIZE, old_len-new_len) };
+		struct kiocb kiocb;
+		struct iov_iter iter;
+
+		init_sync_kiocb(&kiocb, &file);
+		kiocb.ki_pos = file.f_pos;
+		iov_iter_init(&iter, WRITE, &iov, 1, iov.iov_len);
+
+		tmperr = file.f_op->write_iter(&kiocb, &iter);
+		BUG_ON(tmperr == -EIOCBQUEUED);
+		file.f_pos = kiocb.ki_pos;
+
+		if (tmperr < 0) {
+			err = tmperr;
+			break;
+		}
+		new_len += tmperr;
+	}
+        set_fs(oldfs);
+
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_write)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_sec_trunc(): syncing file %lu on device %02u:%02u!\n",
+                   dentry_p->d_inode->i_ino,
+                   MAJOR(dentry_p->d_inode->i_sb->s_dev),
+                   MINOR(dentry_p->d_inode->i_sb->s_dev));
+          }
+#endif
+
+	if(may_sync && (dentry_p->d_inode->i_size > 0))
+          err = generic_file_fsync(&file, 0, dentry_p->d_inode->i_size - 1, 1);
+          
+        rsbac_kfree(buffer);
+      }
+    /* Ready. */
+    return err;
+  }
+
+EXPORT_SYMBOL(rsbac_sec_trunc);
+int rsbac_sec_trunc(struct dentry * dentry_p,
+                    loff_t new_len, loff_t old_len)
+  {
+    return do_rsbac_sec_trunc(dentry_p, new_len, old_len, TRUE);
+  }
+
+EXPORT_SYMBOL(rsbac_sec_del);
+int rsbac_sec_del(struct dentry * dentry_p, u_int may_sync)
+  {
+    return do_rsbac_sec_trunc(dentry_p,
+                              0,
+                              dentry_p->d_inode->i_size,
+                              may_sync);
+  }
+
+#else /* no SECDEL */
+EXPORT_SYMBOL(rsbac_sec_trunc);
+int rsbac_sec_trunc(struct dentry * dentry_p,
+                    loff_t new_len, loff_t old_len)
+  {
+    return 0;
+  }
+EXPORT_SYMBOL(rsbac_sec_del);
+int rsbac_sec_del(struct dentry * dentry_p, u_int may_sync)
+  {
+    return 0;
+  }
+#endif /* SECDEL */
+
+#ifdef CONFIG_RSBAC_SYM_REDIR
+EXPORT_SYMBOL(rsbac_symlink_redirect);
+
+/* This function changes the symlink content by adding a suffix, if
+ * requested. It returns NULL, if unchanged, or a pointer to a
+ * kmalloc'd new char * otherwise, which has to be kfree'd after use.
+ */
+char * rsbac_symlink_redirect(
+  struct inode * inode_p,
+  const char * name,
+  u_int maxlen)
+  {
+#if defined(CONFIG_RSBAC_SYM_REDIR_REMOTE_IP) || defined(CONFIG_RSBAC_SYM_REDIR_MAC) || defined(CONFIG_RSBAC_SYM_REDIR_RC) || defined(CONFIG_RSBAC_SYM_REDIR_UID)
+    union rsbac_target_id_t i_tid;
+    int err;
+    union rsbac_attribute_value_t i_attr_val;
+#endif
+
+    if(unlikely(!name))
+      return NULL;
+    if(unlikely(!inode_p))
+      return NULL;
+    if(unlikely(!inode_p->i_sb))
+      return NULL;
+    if(unlikely(!rsbac_is_initialized()))
+      return NULL;
+
+    if(unlikely(!S_ISLNK(inode_p->i_mode)))
+      {
+        rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): called for non-symlink inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+        return NULL;
+      }
+
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "rsbac_symlink_redirect(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return NULL;
+      }
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): called for symlink inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_SYM_REDIR_REMOTE_IP) || defined(CONFIG_RSBAC_SYM_REDIR_MAC) || defined(CONFIG_RSBAC_SYM_REDIR_RC) || defined(CONFIG_RSBAC_SYM_REDIR_UID)
+    i_tid.symlink.device = inode_p->i_sb->s_dev;
+    i_tid.symlink.inode = inode_p->i_ino;
+    i_tid.symlink.dentry_p = NULL;
+#endif
+
+#ifdef CONFIG_RSBAC_SYM_REDIR_REMOTE_IP
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_SYMLINK,
+                              i_tid,
+                              A_symlink_add_remote_ip,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_symlink_add_remote_ip, err);
+        return NULL;  /* something weird happened */
+      }
+    if(i_attr_val.symlink_add_remote_ip)
+      {
+        u_int len;
+        rsbac_enum_t add_remote_ip;
+        __u32 addr;
+        char * new_name;
+
+        add_remote_ip = i_attr_val.symlink_add_remote_ip;
+        i_tid.process = task_pid(current);
+        err = rsbac_get_attr(SW_GEN,
+                             T_PROCESS,
+                             i_tid,
+                             A_remote_ip,
+                             &i_attr_val,
+                             FALSE);
+        if (err)
+          {
+            rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_remote_ip, err);
+            return NULL;  /* something weird happened */
+          }
+        addr = i_attr_val.remote_ip;
+        len = strlen(name);
+#if 0
+        while(   len
+              && (name[len-1] >= '0')
+              && (name[len-1] <= '9')
+             )
+          len--;
+
+#endif
+        if(len > (maxlen - 20))
+          {
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+            return NULL;
+          }
+        new_name = kmalloc(len + 20, GFP_ATOMIC);
+        if(!new_name)
+          {
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough memory for symlink redir remote ip inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+            return NULL;
+          }
+        strcpy(new_name, name);
+        switch(add_remote_ip)
+          {
+            case 1:
+              sprintf(new_name+len, "%u",
+                      ((unsigned char *)&addr)[0]);
+              break;
+            case 2:
+              sprintf(new_name+len, "%u.%u",
+                      ((unsigned char *)&addr)[0],
+                      ((unsigned char *)&addr)[1]);
+              break;
+            case 3:
+              sprintf(new_name+len, "%u.%u.%u",
+                      ((unsigned char *)&addr)[0],
+                      ((unsigned char *)&addr)[1],
+                      ((unsigned char *)&addr)[2]);
+              break;
+            default:
+              sprintf(new_name+len, "%u.%u.%u.%u",
+                      ((unsigned char *)&addr)[0],
+                      ((unsigned char *)&addr)[1],
+                      ((unsigned char *)&addr)[2],
+                      ((unsigned char *)&addr)[3]);
+          }
+        return new_name;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_SYM_REDIR_UID
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_SYMLINK,
+                              i_tid,
+                              A_symlink_add_uid,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_symlink_add_uid, err);
+        return NULL;  /* something weird happened */
+      }
+    if(i_attr_val.symlink_add_uid)
+      {
+        rsbac_uid_t user;
+
+        if(!rsbac_get_owner(&user))
+          {
+            u_int len;
+            u_int room = 20;
+            char * new_name;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(user))
+              room = 40;
+#endif
+            len = strlen(name);
+            while(   len
+                  && (   (   (name[len-1] >= '0')
+                          && (name[len-1] <= '9')
+                         )
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                      || (name[len-1] == '-')
+#endif
+                     )
+                 )
+              len--;
+            if(len > (maxlen - room))
+              {
+                rsbac_printk(KERN_DEBUG
+                   "rsbac_symlink_redirect(): not enough space for symlink inode %lu on dev %02u:%02u!\n",
+                   inode_p->i_ino,
+                   RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+                return NULL;
+              }
+            new_name = kmalloc(len + room, GFP_ATOMIC);
+            if(!new_name)
+              {
+                rsbac_printk(KERN_DEBUG
+                   "rsbac_symlink_redirect(): not enough memory for symlink redir uid inode %lu on dev %02u:%02u!\n",
+                   inode_p->i_ino,
+                   RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+                return NULL;
+              }
+            strcpy(new_name, name);
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(user))
+              sprintf(new_name+len, "%u-%u",
+                      RSBAC_UID_SET(user), RSBAC_UID_NUM(user));
+            else
+#endif
+            sprintf(new_name+len, "%u", RSBAC_UID_NUM(user));
+            return new_name;
+          }
+        else
+          return NULL;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_SYM_REDIR_MAC
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_SYMLINK,
+                              i_tid,
+                              A_symlink_add_mac_level,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_symlink_add_mac_level, err);
+        return NULL;  /* something weird happened */
+      }
+    if(i_attr_val.symlink_add_mac_level)
+      {
+        u_int len;
+        char * new_name;
+
+        i_tid.process = task_pid(current);
+        if ((err = rsbac_get_attr(SW_MAC,
+                                  T_PROCESS,
+                                  i_tid,
+                                  A_current_sec_level,
+                                  &i_attr_val,
+                                  FALSE) ))
+          {
+            rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_current_sec_level, err);
+            return NULL;  /* something weird happened */
+          }
+
+        len = strlen(name);
+        while(   len
+              && (   (   (name[len-1] >= '0')
+                      && (name[len-1] <= '9')
+                     )
+#ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
+                  || (name[len-1] == ':')
+#endif
+                 )
+             )
+          len--;
+#ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
+        if(len > (maxlen - 85))
+#else
+        if(len > (maxlen - 20))
+#endif
+          {
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+            return NULL;
+          }
+
+#ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
+        new_name = kmalloc(len + 85, GFP_ATOMIC);
+#else
+        new_name = kmalloc(len + 20, GFP_ATOMIC);
+#endif
+        if(!new_name)
+          {
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough memory for symlink redir MAC level inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+            return NULL;
+          }
+        strcpy(new_name, name);
+#ifdef CONFIG_RSBAC_SYM_REDIR_MAC_CAT
+        len+=sprintf(new_name+len, "%u:", i_attr_val.current_sec_level);
+        if ((err = rsbac_get_attr(SW_MAC,
+                                  T_PROCESS,
+                                  i_tid,
+                                  A_mac_curr_categories,
+                                  &i_attr_val,
+                                  FALSE) ))
+          {
+            rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_mac_curr_categories, err);
+            kfree(new_name);
+            return NULL;  /* something weird happened */
+          }
+        u64tostrmac(new_name+len, i_attr_val.mac_categories);
+#else
+        len+=sprintf(new_name+len, "%u", i_attr_val.current_sec_level);
+#endif
+        return new_name;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_SYM_REDIR_RC
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_SYMLINK,
+                              i_tid,
+                              A_symlink_add_rc_role,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_symlink_add_rc_role, err);
+        return NULL;  /* something weird happened */
+      }
+    if(i_attr_val.symlink_add_rc_role)
+      {
+        u_int len;
+        char * new_name;
+
+        i_tid.process = task_pid(current);
+        err = rsbac_get_attr(SW_RC,
+                             T_PROCESS,
+                             i_tid,
+                             A_rc_role,
+                             &i_attr_val,
+                             FALSE);
+        if (err)
+          {
+            rsbac_ds_get_error_num("rsbac_symlink_redirect()", A_rc_role, err);
+            return NULL;  /* something weird happened */
+          }
+
+        len = strlen(name);
+        while(   len
+              && (name[len-1] >= '0')
+              && (name[len-1] <= '9')
+             )
+          len--;
+        if(len > (maxlen - 20))
+          {
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough space for symlink inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+            return NULL;
+          }
+
+        new_name = kmalloc(len + 20, GFP_ATOMIC);
+        if(!new_name)
+          {
+            rsbac_printk(KERN_DEBUG
+               "rsbac_symlink_redirect(): not enough memory for symlink redir RC role inode %lu on dev %02u:%02u!\n",
+               inode_p->i_ino,
+               RSBAC_MAJOR(inode_p->i_sb->s_dev), RSBAC_MINOR(inode_p->i_sb->s_dev) );
+            return NULL;
+          }
+        strcpy(new_name, name);
+        sprintf(new_name+len, "%u", i_attr_val.rc_role);
+        return new_name;
+      }
+#endif
+
+    return NULL;
+  }
+#endif
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_PART
+int rsbac_dac_part_disabled(struct dentry * dentry_p)
+  {
+    int                            err;
+    enum  rsbac_target_t           i_target;
+    union rsbac_target_id_t        i_tid;
+    union rsbac_attribute_value_t  i_attr_val;
+
+    if(   !dentry_p
+       || !dentry_p->d_inode
+       || !dentry_p->d_inode->i_sb->s_dev
+       || !rsbac_is_initialized()
+       || !current->pid
+       || (current->pid == 1))
+      return FALSE;
+
+    if(S_ISREG(dentry_p->d_inode->i_mode))
+      i_target = T_FILE;
+    else
+    if(S_ISDIR(dentry_p->d_inode->i_mode))
+      i_target = T_DIR;
+    else
+    if(S_ISFIFO(dentry_p->d_inode->i_mode))
+      i_target = T_FIFO;
+    else
+    if(S_ISLNK(dentry_p->d_inode->i_mode))
+      i_target = T_SYMLINK;
+    else
+      return FALSE;
+
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "rsbac_dac_part_disabled(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return FALSE;
+      }
+
+    i_tid.file.device = dentry_p->d_sb->s_dev;
+    i_tid.file.inode = dentry_p->d_inode->i_ino;
+    i_tid.file.dentry_p = dentry_p;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG
+               "rsbac_dac_part_disable(): called for dentry_p->d_inode %lu on dev %02u:%02u, dentry_p %p!\n",
+               i_tid.file.inode,
+               RSBAC_MAJOR(i_tid.file.device), RSBAC_MINOR(i_tid.file.device),
+               i_tid.file.dentry_p );
+      }
+#endif
+
+    if ((err = rsbac_get_attr(SW_GEN,
+                              i_target,
+                              i_tid,
+                              A_linux_dac_disable,
+                              &i_attr_val,
+                              TRUE) ))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_dac_part_disable(): rsbac_get_attr() for linux_dac_disable returned error %i!\n",
+               err);
+        return FALSE;  /* something weird happened */
+      }
+    if(i_attr_val.linux_dac_disable == LDD_true)
+      return TRUE;
+    else
+      return FALSE;
+  }
+#endif
+
+#ifdef CONFIG_RSBAC_FAKE_ROOT_UID
+rsbac_uid_t rsbac_fake_uid(void)
+  {
+    int                            err;
+    union rsbac_target_id_t        i_tid;
+    union rsbac_attribute_value_t  i_attr_val;
+
+    if(!__kuid_val(current_uid()))
+      return 0;
+    if (unlikely(!rsbac_is_initialized()))
+      return __kuid_val(current_uid());
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "rsbac_fake_uid(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return __kuid_val(current_uid());
+      }
+
+    i_tid.process = task_pid(current);
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_PROCESS,
+                              i_tid,
+                              A_fake_root_uid,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error("rsbac_fake_uid()", A_fake_root_uid);
+        return __kuid_val(current_uid());
+      }
+    switch(i_attr_val.fake_root_uid)
+      {
+        case FR_both:
+        case FR_uid_only:
+          return 0;
+        default:
+          return __kuid_val(current_uid());
+      }
+  }
+
+rsbac_uid_t rsbac_fake_euid(void)
+  {
+    int                            err;
+    union rsbac_target_id_t        i_tid;
+    union rsbac_attribute_value_t  i_attr_val;
+
+    if(!__kuid_val(current_euid()))
+      return 0;
+    if (unlikely(!rsbac_is_initialized()))
+      return __kuid_val(current_euid());
+
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "rsbac_fake_euid(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return __kuid_val(current_euid());
+      }
+
+    i_tid.process = task_pid(current);
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_PROCESS,
+                              i_tid,
+                              A_fake_root_uid,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error("rsbac_fake_euid()", A_fake_root_uid);
+        return __kuid_val(current_euid());
+      }
+    switch(i_attr_val.fake_root_uid)
+      {
+        case FR_both:
+        case FR_euid_only:
+          return 0;
+        default:
+          return __kuid_val(current_euid());
+      }
+  }
+
+int rsbac_uid_faked(void)
+  {
+    int                            err;
+    union rsbac_target_id_t        i_tid;
+    union rsbac_attribute_value_t  i_attr_val;
+
+    if (unlikely(!rsbac_is_initialized()))
+      return 0;
+
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "rsbac_uid_faked(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return 0;
+      }
+
+    i_tid.process = task_pid(current);
+    if ((err = rsbac_get_attr(SW_GEN,
+                              T_PROCESS,
+                              i_tid,
+                              A_fake_root_uid,
+                              &i_attr_val,
+                              FALSE) ))
+      {
+        rsbac_ds_get_error("rsbac_uid_faked()", A_fake_root_uid);
+        return 0;  /* something weird happened */
+      }
+    switch(i_attr_val.fake_root_uid)
+      {
+        case FR_both:
+        case FR_uid_only:
+          return 1;
+        default:
+          return 0;
+      }
+  }
+
+#endif
+
+int rsbac_set_audit_uid(rsbac_uid_t uid)
+  {
+    union rsbac_target_id_t       tid;
+    union rsbac_attribute_value_t attr_val;
+
+    if(!uid || (uid == __kuid_val(current_uid())))
+      return 0;
+
+    if (unlikely(in_interrupt()))
+      {
+        printk(KERN_WARNING "rsbac_set_audit_uid(): called from interrupt: pid %u(%s)!\n",
+                     current->pid, current->comm);
+        dump_stack();
+        return -RSBAC_EFROMINTERRUPT;
+      }
+
+    tid.process = task_pid(current);
+    if (rsbac_get_attr(SW_GEN,
+                       T_PROCESS,
+                       tid,
+                       A_audit_uid,
+                       &attr_val,
+                       FALSE))
+      {
+        rsbac_ds_get_error("rsbac_set_audit_uid()", A_audit_uid);
+        return -RSBAC_EREADFAILED;
+      }
+    if(attr_val.audit_uid != RSBAC_NO_USER)
+      return 0;
+
+    if (rsbac_get_attr(SW_GEN,
+                       T_PROCESS,
+                       tid,
+                       A_auid_exempt,
+                       &attr_val,
+                       FALSE))
+      {
+        rsbac_ds_get_error("rsbac_set_audit_uid()", A_auid_exempt);
+        return -RSBAC_EREADFAILED;
+      }
+    if(attr_val.auid_exempt == uid)
+      return 0;
+
+    attr_val.audit_uid = uid;
+    if (rsbac_set_attr(SW_GEN,
+                       T_PROCESS,
+                       tid,
+                       A_audit_uid,
+                       attr_val))
+      {
+        rsbac_ds_set_error("rsbac_set_audit_uid()", A_audit_uid);
+        return -RSBAC_EWRITEFAILED;
+      }
+    return 0;
+  }
+
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_JAIL_LOG_MISSING)
+EXPORT_SYMBOL(rsbac_log_missing_cap);
+
+void rsbac_log_missing_cap(int cap)
+  {
+    #if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_CAP_LEARN)
+    #if defined(CONFIG_RSBAC_CAP_LOG_MISSING) && defined(CONFIG_RSBAC_CAP_LEARN)
+    if(rsbac_cap_log_missing || rsbac_cap_learn)
+    #elif defined(CONFIG_RSBAC_CAP_LEARN)
+    if(rsbac_cap_learn)
+    #else
+    if(rsbac_cap_log_missing)
+    #endif
+      rsbac_cap_log_missing_cap(cap);
+    #endif
+    #if defined(CONFIG_RSBAC_JAIL_LOG_MISSING)
+    if(rsbac_jail_log_missing)
+      rsbac_jail_log_missing_cap(cap);
+    #endif
+  }
+#endif
+
+/* end of rsbac/adf/main.c */
diff --git a/rsbac/adf/auth/Makefile b/rsbac/adf/auth/Makefile
new file mode 100644
index 0000000..2d2f2b2
--- /dev/null
+++ b/rsbac/adf/auth/Makefile
@@ -0,0 +1,10 @@
+#
+# File: rsbac/adf/auth/Makefile
+#
+# Makefile for the Linux rsbac auth decision module.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+obj-y   := auth_syscalls.o auth_main.o
+
diff --git a/rsbac/adf/auth/auth_main.c b/rsbac/adf/auth/auth_main.c
new file mode 100644
index 0000000..1fe3200
--- /dev/null
+++ b/rsbac/adf/auth/auth_main.c
@@ -0,0 +1,1189 @@
+/**************************************************** */
+/* Rule Set Based Access Control                      */
+/* Implementation of the Access Control Decision      */
+/* Facility (ADF) - Authorization module              */
+/* File: rsbac/adf/auth/main.c                        */
+/*                                                    */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org>  */
+/*                                                    */
+/* Last modified: 04/Apr/2016                         */
+/**************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/auth.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+static int  rsbac_replace_auth_cap(rsbac_pid_t caller_pid,
+                                   enum rsbac_auth_cap_type_t cap_type,
+                                   rsbac_uid_t from,
+                                   rsbac_uid_t to)
+  {
+    if(rsbac_auth_p_capset_member(caller_pid, cap_type, from))
+      {
+        struct rsbac_auth_cap_range_t cap_range;
+
+        /* remove it and set cap for 'to' */
+        cap_range.first = to;
+        cap_range.last  = to;
+        if (rsbac_auth_add_to_p_capset(0, caller_pid, cap_type, cap_range, 0))
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_adf_set_attr_auth(): rsbac_auth_add_to_p_capset() returned error!\n");
+            return -RSBAC_EWRITEFAILED;
+          }
+        cap_range.first = from;
+        cap_range.last  = from;
+        if (rsbac_auth_remove_from_p_capset(0, caller_pid, cap_type, cap_range))
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_adf_set_attr_auth(): rsbac_auth_remove_from_p_capset() returned error!\n");
+            return -RSBAC_EWRITEFAILED;
+          }
+      }
+    return 0; /* success */
+  }
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request_auth (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)
+  {
+    enum  rsbac_adf_req_ret_t result = DO_NOT_CARE;
+    union rsbac_attribute_value_t i_attr_val1;
+    union rsbac_target_id_t       i_tid;
+
+    switch (request)
+      {
+#if defined(CONFIG_RSBAC_AUTH_UM_PROT) || defined(CONFIG_RSBAC_AUTH_GROUP)
+        case R_CHANGE_GROUP:
+            switch(target)
+              {
+#if defined(CONFIG_RSBAC_AUTH_UM_PROT)
+                case T_USER:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+#endif /* AUTH_UM_PROT */
+
+#if defined(CONFIG_RSBAC_AUTH_GROUP)
+                case T_PROCESS:
+                  if(attr != A_group)
+                    return NOT_GRANTED;
+#if defined(CONFIG_RSBAC_AUTH_ALLOW_SAME)
+                  if(attr_val.group == RSBAC_GEN_GID(RSBAC_UID_SET(owner),__kgid_val(current_gid())))
+                    return DO_NOT_CARE;
+#endif
+                  /* check auth_may_setuid of process */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return NOT_GRANTED;
+                    }
+                  /* if auth_may_setuid is full or and_gid, then grant */
+                  if(   (i_attr_val1.auth_may_setuid == AMS_full)
+                     || (i_attr_val1.auth_may_setuid == AMS_last_auth_and_gid)
+                    )
+                    return GRANTED;
+
+                  /* check, if the target uid is in capset, grant, if yes, deny, if not. */
+                  if(rsbac_auth_p_capset_member(caller_pid, ACT_group_real, attr_val.group))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+#endif /* AUTH_GROUP */
+
+                /* We do not care about */
+                /* all other cases */
+                default:
+                  return DO_NOT_CARE;
+              }
+#endif /* AUTH_UM_PROT || AUTH_GROUP */
+
+#if defined(CONFIG_RSBAC_AUTH_UM_PROT)
+        case R_CREATE:
+        case R_DELETE:
+        case R_GET_PERMISSIONS_DATA:
+        case R_RENAME:
+        case R_WRITE:
+            switch(target)
+              {
+                case T_USER:
+                case T_GROUP:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                /* We do not care about */
+                /* all other cases */
+                default: return DO_NOT_CARE;
+              }
+#endif
+
+        case R_CHANGE_OWNER:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_owner)
+                    return NOT_GRANTED;
+#if defined(CONFIG_RSBAC_AUTH_ALLOW_SAME)
+                  if(attr_val.owner == owner)
+                    return DO_NOT_CARE;
+#endif
+                  /* check auth_may_setuid of process */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return NOT_GRANTED;
+                    }
+                  switch(i_attr_val1.auth_may_setuid)
+                    {
+                      case AMS_off:
+                        break;
+                      case AMS_full:
+                        return GRANTED;
+                      case AMS_last_auth_only:
+                      case AMS_last_auth_and_gid:
+                        if(attr_val.owner == RSBAC_NO_USER)
+                          return NOT_GRANTED;
+                        if (rsbac_get_attr(SW_AUTH,
+                                           T_PROCESS,
+                                           tid,
+                                           A_auth_last_auth,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_pr_get_error(A_auth_last_auth);
+                            return NOT_GRANTED;
+                          }
+                        if(i_attr_val1.auth_last_auth == attr_val.owner)
+                          return GRANTED;
+                        break;
+
+                      default:
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_adf_request_auth(): auth_may_setuid of process %u an invalid value %u!\n",
+                                     tid.process, i_attr_val1.auth_may_setuid);
+                        return NOT_GRANTED;
+                    }
+                  /* check, if the target uid is in capset, grant, if yes, deny, if not. */
+                  if(rsbac_auth_p_capset_member(caller_pid, ACT_real, attr_val.owner))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default:
+                  return DO_NOT_CARE;
+              }
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+        case R_CHANGE_DAC_EFF_OWNER:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_owner)
+                    return NOT_GRANTED;
+                  if(attr_val.owner == owner)
+                    return DO_NOT_CARE;
+#if defined(CONFIG_RSBAC_AUTH_ALLOW_SAME)
+                  if(attr_val.owner == __kuid_val(current_euid()))
+                    return DO_NOT_CARE;
+#endif
+                  /* check auth_may_setuid of process */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return NOT_GRANTED;
+                    }
+                  switch(i_attr_val1.auth_may_setuid)
+                    {
+                      case AMS_off:
+                        break;
+                      case AMS_full:
+                        return GRANTED;
+                      case AMS_last_auth_only:
+                      case AMS_last_auth_and_gid:
+                        if(attr_val.owner == RSBAC_NO_USER)
+                          return NOT_GRANTED;
+                        if (rsbac_get_attr(SW_AUTH,
+                                           T_PROCESS,
+                                           tid,
+                                           A_auth_last_auth,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_pr_get_error(A_auth_last_auth);
+                            return NOT_GRANTED;
+                          }
+                        if(i_attr_val1.auth_last_auth == attr_val.owner)
+                          return GRANTED;
+                        break;
+
+                      default:
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_adf_request_auth(): auth_may_setuid of process %u has invalid value %u!\n",
+                                     tid.process, i_attr_val1.auth_may_setuid);
+                        return NOT_GRANTED;
+                    }
+                  /* check, if the target uid is in capset, grant, if yes, deny, if not. */
+                  if(rsbac_auth_p_capset_member(caller_pid, ACT_eff, attr_val.owner))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default:
+                  return DO_NOT_CARE;
+              }
+        case R_CHANGE_DAC_FS_OWNER:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_owner)
+                    return NOT_GRANTED;
+                  if(attr_val.owner == owner)
+                    return DO_NOT_CARE;
+#if defined(CONFIG_RSBAC_AUTH_ALLOW_SAME)
+                  if(attr_val.owner == __kuid_val(current_fsuid()))
+                    return DO_NOT_CARE;
+#endif
+                  /* check auth_may_setuid of process */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return NOT_GRANTED;
+                    }
+                  switch(i_attr_val1.auth_may_setuid)
+                    {
+                      case AMS_off:
+                        break;
+                      case AMS_full:
+                        return GRANTED;
+                      case AMS_last_auth_only:
+                      case AMS_last_auth_and_gid:
+                        if(attr_val.owner == RSBAC_NO_USER)
+                          return NOT_GRANTED;
+                        if (rsbac_get_attr(SW_AUTH,
+                                           T_PROCESS,
+                                           tid,
+                                           A_auth_last_auth,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_pr_get_error(A_auth_last_auth);
+                            return NOT_GRANTED;
+                          }
+                        if(i_attr_val1.auth_last_auth == attr_val.owner)
+                          return GRANTED;
+                        break;
+
+                      default:
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_adf_request_auth(): auth_may_setuid of process %u has an invalid value!\n",
+                                     tid.process);
+                        return NOT_GRANTED;
+                    }
+                  /* check, if the target uid is in capset, grant, if yes, deny, if not. */
+                  if(rsbac_auth_p_capset_member(caller_pid, ACT_fs, attr_val.owner))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default:
+                  return DO_NOT_CARE;
+              }
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+        case R_CHANGE_DAC_EFF_GROUP:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_group)
+                    return NOT_GRANTED;
+                  if(attr_val.group == RSBAC_GEN_GID(RSBAC_UID_SET(owner),__kgid_val(current_gid())))
+                    return DO_NOT_CARE;
+#if defined(CONFIG_RSBAC_AUTH_ALLOW_SAME)
+                  if(attr_val.group == RSBAC_GEN_GID(RSBAC_UID_SET(owner),__kgid_val(current_egid())))
+                    return DO_NOT_CARE;
+#endif
+                  /* check auth_may_setuid of process */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return NOT_GRANTED;
+                    }
+                  /* if auth_may_setuid is set, then grant */
+                  if(   (i_attr_val1.auth_may_setuid == AMS_full)
+                     || (i_attr_val1.auth_may_setuid == AMS_last_auth_and_gid)
+                    )
+                    return GRANTED;
+
+                  /* check, if the target uid is in capset, grant, if yes, deny, if not. */
+                  if(rsbac_auth_p_capset_member(caller_pid, ACT_group_eff, attr_val.group))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default:
+                  return DO_NOT_CARE;
+              }
+        case R_CHANGE_DAC_FS_GROUP:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_group)
+                    return NOT_GRANTED;
+                  if(attr_val.group == RSBAC_GEN_GID(RSBAC_UID_SET(owner),__kgid_val(current_gid())))
+                    return DO_NOT_CARE;
+#if defined(CONFIG_RSBAC_AUTH_ALLOW_SAME)
+                  if(attr_val.group == RSBAC_GEN_GID(RSBAC_UID_SET(owner),__kgid_val(current_fsgid())))
+                    return DO_NOT_CARE;
+#endif
+                  /* check auth_may_setuid of process */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return NOT_GRANTED;
+                    }
+                  /* if auth_may_setuid is set, then grant */
+                  if(   (i_attr_val1.auth_may_setuid == AMS_full)
+                     || (i_attr_val1.auth_may_setuid == AMS_last_auth_and_gid)
+                    )
+                    return GRANTED;
+
+                  /* check, if the target uid is in capset, grant, if yes, deny, if not. */
+                  if(rsbac_auth_p_capset_member(caller_pid, ACT_group_fs, attr_val.group))
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default:
+                  return DO_NOT_CARE;
+              }
+#endif
+#endif /* AUTH_GROUP */
+
+        case R_MODIFY_ATTRIBUTE:
+            switch(attr)
+              {
+                /* Only protect itself, if asked to by configuration */
+                #ifdef CONFIG_RSBAC_AUTH_AUTH_PROT
+                case A_system_role:
+                case A_auth_role:
+                case A_auth_may_setuid:
+                case A_auth_may_set_cap:
+                case A_auth_start_uid:
+                case A_auth_start_euid:
+                case A_auth_start_gid:
+                case A_auth_start_egid:
+                case A_auth_learn:
+                case A_program_file:
+                case A_auth_add_f_cap:
+                case A_auth_remove_f_cap:
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                #endif
+
+                case A_auth_last_auth:
+                  if(target != T_PROCESS)
+                    return DO_NOT_CARE;
+                  /* check auth_may_set_cap of calling process */
+                  i_tid.process = task_pid(current);
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_may_set_cap,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_set_cap);
+                      return -RSBAC_EREADFAILED;
+                    }
+                  /* if auth_may_set_cap is not set, then reject */
+                  if (!i_attr_val1.auth_may_set_cap)
+                    {
+                      rsbac_printk(KERN_INFO
+                                   "rsbac_adf_request_auth(): changing auth_last_auth of process %u to %u denied for process %u!\n",
+                                   tid.process,
+                                   attr_val.auth_last_auth,
+                                   task_pid(current));
+                      return NOT_GRANTED;
+                    }
+
+                default:
+                  return DO_NOT_CARE;
+              }
+
+/* Only protect itself, if asked to by configuration */
+#ifdef CONFIG_RSBAC_AUTH_AUTH_PROT
+        case R_GET_STATUS_DATA:
+            switch(target)
+              {
+                case T_SCD:
+                  /* target rsbac_log? only for secoff */
+                  if (tid.scd != ST_rsbac_log)
+                    return GRANTED;
+                  /* Secoff or Auditor? */
+                  i_tid.user = owner;
+                  if ((rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE)))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* grant only for secoff */
+                  if (   (i_attr_val1.system_role == SR_security_officer)
+                      || (i_attr_val1.system_role == SR_auditor)
+                     )
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                default:
+                  return DO_NOT_CARE;
+               };
+
+        case R_MODIFY_PERMISSIONS_DATA:
+            switch(target)
+              {
+                case T_SCD:
+                  #ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+                  if(tid.scd == ST_ioports)
+                    return GRANTED;
+                  #endif
+                  /* fall through */
+                #if defined(CONFIG_RSBAC_AUTH_UM_PROT)
+                case T_USER:
+                case T_GROUP:
+                #endif
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  /* For booting: if administrator and ioports, then grant */
+                  if (
+                      #if defined(CONFIG_RSBAC_AUTH_UM_PROT)
+                         (target == T_SCD) &&
+                      #endif
+                         (i_attr_val1.system_role == SR_administrator)
+                      && (tid.scd == ST_ioports) )
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                  
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+                /* switching Linux DAC */
+                case T_NONE:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+#endif
+
+                /* all other cases are not checked */
+                default: return DO_NOT_CARE;
+              }
+
+        case R_MODIFY_SYSTEM_DATA:
+            switch(target)
+              {
+                case T_SCD:
+                  /* target not rsbac_log? no problem -> grant */
+                  switch(tid.scd)
+                    {
+                      case ST_rsbac_log:
+                      case ST_rsbac_remote_log:
+                        break;
+                      case ST_kmem:
+                        return NOT_GRANTED;
+                      default:
+                        return GRANTED;
+                    }
+                  /* Get role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* grant only for secoff and auditor */
+                  if (   (i_attr_val1.system_role == SR_security_officer)
+                      || (i_attr_val1.system_role == SR_auditor)
+                     )
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+                  
+                /* all other cases are not checked */
+                default: return DO_NOT_CARE;
+              }
+
+        case R_SWITCH_LOG:
+            switch(target)
+              {
+                case T_NONE:
+                  /* test owner's auth_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default: return DO_NOT_CARE;
+              }
+
+        case R_SWITCH_MODULE:
+            switch(target)
+              {
+                case T_NONE:
+                  /* we need the switch_target */
+                  if(attr != A_switch_target)
+                    return NOT_GRANTED;
+#ifndef CONFIG_RSBAC_AUTH_OTHER_PROT
+                  /* do not care for other modules */
+                  if(   (attr_val.switch_target != SW_AUTH)
+                     #ifdef CONFIG_RSBAC_SOFTMODE
+                     && (attr_val.switch_target != SW_SOFTMODE)
+                     #endif
+                     #ifdef CONFIG_RSBAC_FREEZE
+                     && (attr_val.switch_target != SW_FREEZE)
+                     #endif
+                    )
+                    return DO_NOT_CARE;
+#endif
+                  /* test owner's auth_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_USER,
+                                     i_tid,
+                                     A_auth_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_role);
+                      return NOT_GRANTED;
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return GRANTED;
+                  else
+                    return NOT_GRANTED;
+
+                /* all other cases are not checked */
+                default: return DO_NOT_CARE;
+              }
+#endif
+
+/*********************/
+        default: return DO_NOT_CARE;
+      }
+
+    return result;
+  } /* end of rsbac_adf_request_auth() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up.                                                              */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+inline int  rsbac_adf_set_attr_auth(
+                      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)
+  {
+    int error;
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    union rsbac_attribute_value_t i_attr_val2;
+    #if defined(CONFIG_RSBAC_AUTH_LEARN)
+    union rsbac_attribute_value_t i_attr_val3;
+    union rsbac_attribute_value_t i_attr_val4;
+    #endif
+
+    switch (request)
+      {
+        case R_CLONE:
+            if (target == T_PROCESS)
+              {
+                /* Get auth_may_setuid from first process */
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_may_setuid,
+                                   &i_attr_val1,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_may_setuid);
+                    return -RSBAC_EREADFAILED;
+                  }
+                /* Get auth_may_set_cap from first process */
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_may_set_cap,
+                                   &i_attr_val2,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_may_set_cap);
+                    return -RSBAC_EREADFAILED;
+                  }
+                #if defined(CONFIG_RSBAC_AUTH_LEARN)
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_start_uid,
+                                   &i_attr_val3,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_start_uid);
+                    return -RSBAC_EREADFAILED;
+                  }
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_learn,
+                                   &i_attr_val4,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_learn);
+                    return -RSBAC_EREADFAILED;
+                  }
+                #endif
+                /* Set auth_may_setuid for new process */
+                if (i_attr_val1.auth_may_setuid && rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_may_setuid,
+                                   i_attr_val1))
+                  {
+                    rsbac_pr_set_error(A_auth_may_setuid);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                /* Set auth_may_set_cap for new process */
+                if (i_attr_val2.auth_may_set_cap && rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_may_set_cap,
+                                   i_attr_val2))
+                  {
+                    rsbac_pr_set_error(A_auth_may_set_cap);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                #if defined(CONFIG_RSBAC_AUTH_LEARN)
+                if (rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_start_uid,
+                                   i_attr_val3))
+                  {
+                    rsbac_pr_set_error(A_auth_start_uid);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                if (i_attr_val4.auth_learn && rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_learn,
+                                   i_attr_val4))
+                  {
+                    rsbac_pr_set_error(A_auth_learn);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                #ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_start_euid,
+                                   &i_attr_val4,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_start_uid);
+                    return -RSBAC_EREADFAILED;
+                  }
+                if (rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_start_euid,
+                                   i_attr_val4))
+                  {
+                    rsbac_pr_set_error(A_auth_start_uid);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                #endif
+                #ifdef CONFIG_RSBAC_AUTH_GROUP
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_start_gid,
+                                   &i_attr_val4,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_start_uid);
+                    return -RSBAC_EREADFAILED;
+                  }
+                if (rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_start_gid,
+                                   i_attr_val4))
+                  {
+                    rsbac_pr_set_error(A_auth_start_uid);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                #ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_start_egid,
+                                   &i_attr_val4,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_start_uid);
+                    return -RSBAC_EREADFAILED;
+                  }
+                if (rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_start_egid,
+                                   i_attr_val4))
+                  {
+                    rsbac_pr_set_error(A_auth_start_uid);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                #endif
+                #endif
+                #endif
+                /* copy auth_last_auth */
+                if (rsbac_get_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   tid,
+                                   A_auth_last_auth,
+                                   &i_attr_val1,
+                                   FALSE))
+                  {
+                    rsbac_pr_get_error(A_auth_last_auth);
+                    return -RSBAC_EREADFAILED;
+                  }
+                if ((i_attr_val1.auth_last_auth != RSBAC_NO_USER) && rsbac_set_attr(SW_AUTH,
+                                   T_PROCESS,
+                                   new_tid,
+                                   A_auth_last_auth,
+                                   i_attr_val1))
+                  {
+                    rsbac_pr_set_error(A_auth_last_auth);
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                /* copy capability list */
+                if(rsbac_auth_copy_pp_capset(tid.process,new_tid.process))
+                  {
+                    rsbac_printk(KERN_WARNING
+                           "rsbac_adf_set_attr_auth(): rsbac_auth_copy_pp_capset() returned error!\n");
+                    return -RSBAC_EWRITEFAILED;
+                  }
+                return 0;
+              }
+            else
+              return 0;
+
+        case R_EXECUTE:
+            switch(target)
+              {
+                case T_FILE:
+                  /* reset auth_may_setuid and auth_may_set_cap for process */
+                  i_tid.process = caller_pid;
+                  /* First, set auth_may_setuid to program file's auth_may_setuid */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_FILE,
+                                     tid,
+                                     A_auth_may_setuid,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_setuid);
+                      return -RSBAC_EREADFAILED;
+                    }
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_may_setuid,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_may_setuid);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  /* Next, set auth_may_set_cap to program file's auth_may_set_cap */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_FILE,
+                                     tid,
+                                     A_auth_may_set_cap,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_may_set_cap);
+                      return -RSBAC_EREADFAILED;
+                    }
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_may_set_cap,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_may_set_cap);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  /* reset auth_last_auth for process */
+                  i_attr_val1.auth_last_auth = RSBAC_NO_USER;
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_last_auth,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_last_auth);
+                    }
+
+                  /* copy file capability list from file to process */
+                  if (rsbac_auth_copy_fp_capset(tid.file, caller_pid))
+                    {
+                      rsbac_printk(KERN_WARNING
+                             "rsbac_adf_set_attr_auth(): rsbac_auth_copy_fp_capset() returned error!\n");
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  /* replace RSBAC_AUTH_OWNER_F_CAP by current owner */
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_real,
+                                                 RSBAC_AUTH_OWNER_F_CAP,
+                                                 owner);
+                  if(error)
+                    return error;
+                  #ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_eff,
+                                                 RSBAC_AUTH_OWNER_F_CAP,
+                                                 owner);
+                  if(error)
+                    return error;
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_eff,
+                                                 RSBAC_AUTH_DAC_OWNER_F_CAP,
+                                                 __kuid_val(current_euid()));
+                  if(error)
+                    return error;
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_fs,
+                                                 RSBAC_AUTH_OWNER_F_CAP,
+                                                 owner);
+                  if(error)
+                    return error;
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_fs,
+                                                 RSBAC_AUTH_DAC_OWNER_F_CAP,
+                                                 __kuid_val(current_fsuid()));
+                  if(error)
+                    return error;
+                  #endif
+                  #ifdef CONFIG_RSBAC_AUTH_GROUP
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_group_real,
+                                                 RSBAC_AUTH_GROUP_F_CAP,
+                                                 __kgid_val(current_gid()));
+                  if(error)
+                    return error;
+                  #ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_group_eff,
+                                                 RSBAC_AUTH_GROUP_F_CAP,
+                                                 __kgid_val(current_gid()));
+                  if(error)
+                    return error;
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_group_eff,
+                                                 RSBAC_AUTH_DAC_GROUP_F_CAP,
+                                                 __kgid_val(current_egid()));
+                  if(error)
+                    return error;
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_group_fs,
+                                                 RSBAC_AUTH_GROUP_F_CAP,
+                                                 __kgid_val(current_gid()));
+                  if(error)
+                    return error;
+                  error = rsbac_replace_auth_cap(caller_pid,
+                                                 ACT_group_fs,
+                                                 RSBAC_AUTH_DAC_GROUP_F_CAP,
+                                                 __kgid_val(current_fsgid()));
+                  if(error)
+                    return error;
+                  #endif
+                  #endif
+
+                  #if defined(CONFIG_RSBAC_AUTH_LEARN)
+                  /* Set auth_learn to program file's auth_learn */
+                  if (rsbac_get_attr(SW_AUTH,
+                                     T_FILE,
+                                     tid,
+                                     A_auth_learn,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_pr_get_error(A_auth_learn);
+                      return -RSBAC_EREADFAILED;
+                    }
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_learn,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_learn);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  /* remember caller */
+                  i_attr_val1.auth_start_uid = owner;
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_start_uid,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_start_uid);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  #ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+                  i_attr_val1.auth_start_euid = __kuid_val(current_euid());
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_start_euid,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_start_euid);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  #endif
+                  #ifdef CONFIG_RSBAC_AUTH_GROUP
+                  i_attr_val1.auth_start_gid = __kgid_val(current_gid());
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_start_gid,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_start_gid);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  #ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+                  i_attr_val1.auth_start_egid = __kgid_val(current_egid());
+                  if (rsbac_set_attr(SW_AUTH,
+                                     T_PROCESS,
+                                     i_tid,
+                                     A_auth_start_egid,
+                                     i_attr_val1))
+                    {
+                      rsbac_pr_set_error(A_auth_start_egid);
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  #endif
+                  #endif
+                  #endif
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return 0;
+              }
+
+/* Only protect itself, if asked to by configuration */
+#ifdef CONFIG_RSBAC_AUTH_AUTH_PROT
+        /* remove all file capabilities on all changing requests to files */
+        case R_APPEND_OPEN:
+        case R_CHANGE_GROUP:
+        case R_DELETE:
+        case R_LINK_HARD:
+        case R_MODIFY_ACCESS_DATA:
+        case R_READ_WRITE_OPEN:
+        case R_RENAME:
+        case R_TRUNCATE:
+        case R_WRITE_OPEN:
+            switch(target)
+              {
+                case T_FILE:
+                  /* remove cap set */
+                  if(rsbac_auth_remove_f_capsets(tid.file))
+                    {
+                      rsbac_printk(KERN_WARNING
+                             "rsbac_adf_set_attr_auth(): rsbac_auth_remove_f_capsets() returned error!\n");
+                      return -RSBAC_EWRITEFAILED;
+                    }
+                  return 0;
+
+                /* all other cases are not handled */
+                default: return 0;
+              }
+#endif
+
+/*********************/
+        default: return 0;
+      }
+
+    return 0;
+  } /* end of rsbac_adf_set_attr_auth() */
+
+/* end of rsbac/adf/auth/main.c */
diff --git a/rsbac/adf/auth/auth_syscalls.c b/rsbac/adf/auth/auth_syscalls.c
new file mode 100644
index 0000000..fc85d30
--- /dev/null
+++ b/rsbac/adf/auth/auth_syscalls.c
@@ -0,0 +1,156 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Authentification module          */
+/* File: rsbac/adf/auth/syscalls.c                   */
+/*                                                   */
+/* Author and (c) 1999-2013: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 09/Aug/2013                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/error.h>
+#include <rsbac/auth.h>
+#include <rsbac/debug.h>
+#include <rsbac/helpers.h>
+#include <rsbac/adf_main.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+int rsbac_auth_add_p_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl)
+  {
+/* check only in non-maint mode */
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+    if(rsbac_switch_auth)
+#endif
+      {
+        union rsbac_target_id_t       i_tid;
+        union rsbac_attribute_value_t i_attr_val1;
+
+        /* check auth_may_set_cap of calling process */
+        i_tid.process = task_pid(current);
+        if (rsbac_get_attr(SW_AUTH,
+                           T_PROCESS,
+                           i_tid,
+                           A_auth_may_set_cap,
+                           &i_attr_val1,
+                           FALSE))
+          {
+            rsbac_pr_get_error(A_auth_may_set_cap);
+            return -RSBAC_EREADFAILED;
+          }
+        /* if auth_may_set_cap is not set, then reject */
+        if (!i_attr_val1.auth_may_set_cap)
+          {
+            rsbac_printk(KERN_INFO
+                   "rsbac_auth_add_p_cap(): adding AUTH cap %u:%u to process %u denied for process %u!\n",
+                   cap_range.first,
+                   cap_range.last,
+                   pid,
+                   task_pid(current));
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_AUTH]
+            #endif
+              )
+            #endif
+              return(-EPERM);
+          }
+      }
+
+    /* OK, check passed. Add the capability. */
+    return rsbac_auth_add_to_p_capset(ta_number, pid, cap_type, cap_range, ttl);
+  }
+
+int rsbac_auth_remove_p_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_pid_t pid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+    if(rsbac_switch_auth)
+#endif
+      {
+        union rsbac_target_id_t       i_tid;
+        union rsbac_attribute_value_t i_attr_val1;
+
+        /* check auth_may_set_cap of calling process */
+        i_tid.process = task_pid(current);
+        if (rsbac_get_attr(SW_AUTH,
+                           T_PROCESS,
+                           i_tid,
+                           A_auth_may_set_cap,
+                           &i_attr_val1,
+                           FALSE))
+          {
+            rsbac_pr_get_error(A_auth_may_set_cap);
+            return -RSBAC_EREADFAILED;
+          }
+        /* if auth_may_set_cap is not set, then reject */
+        if (!i_attr_val1.auth_may_set_cap)
+          {
+            rsbac_printk(KERN_INFO
+                   "rsbac_auth_remove_p_cap(): removing AUTH cap %u:%u from process %u denied for process %u!\n",
+                   cap_range.first,
+                   cap_range.last,
+                   pid,
+                   task_pid(current));
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_AUTH]
+            #endif
+              )
+            #endif
+              return(-EPERM);
+          }
+      }
+
+    /* OK, check passed. Try to remove the capability. */
+    return rsbac_auth_remove_from_p_capset(ta_number, pid, cap_type, cap_range);
+  }
+
+int rsbac_auth_add_f_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_auth_file_t file,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl)
+  {
+    /* check has been done in help/syscalls.c: sys_rsbac_auth_add_f_cap */
+    return rsbac_auth_add_to_f_capset(ta_number, file, cap_type, cap_range, ttl);
+  }
+
+int rsbac_auth_remove_f_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_auth_file_t file,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range)
+  {
+    /* check has been done in help/syscalls.c: sys_rsbac_auth_remove_f_cap */
+    return rsbac_auth_remove_from_f_capset(ta_number, file, cap_type, cap_range);
+  }
+
+/* end of rsbac/adf/auth/syscalls.c */
diff --git a/rsbac/adf/cap/Makefile b/rsbac/adf/cap/Makefile
new file mode 100644
index 0000000..3411764
--- /dev/null
+++ b/rsbac/adf/cap/Makefile
@@ -0,0 +1,10 @@
+#
+# File: rsbac/adf/cap/Makefile
+#
+# Makefile for the Linux rsbac cap decision module.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := cap_main.o
+
diff --git a/rsbac/adf/cap/cap_main.c b/rsbac/adf/cap/cap_main.c
new file mode 100644
index 0000000..04fd53e
--- /dev/null
+++ b/rsbac/adf/cap/cap_main.c
@@ -0,0 +1,941 @@
+/**************************************************** */
+/* Rule Set Based Access Control                      */
+/* Implementation of the Access Control Decision      */
+/* Facility (ADF) - Linux Capabilities (CAP)          */
+/* File: rsbac/adf/cap/main.c                         */
+/*                                                    */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org>  */
+/*                                                    */
+/* Last modified: 04/Apr/2016                         */
+/**************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request_cap (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)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    switch (request)
+      {
+        case R_MODIFY_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_system_role:
+                case A_cap_role:
+                case A_min_caps:
+                case A_max_caps:
+                case A_max_caps_user:
+                case A_max_caps_program:
+                case A_cap_process_hiding:
+                case A_cap_learn:
+                #ifdef CONFIG_RSBAC_CAP_AUTH_PROT
+                case A_auth_may_setuid:
+                case A_auth_may_set_cap:
+                case A_auth_start_uid:
+                case A_auth_start_euid:
+                case A_auth_start_gid:
+                case A_auth_start_egid:
+                case A_auth_learn:
+                case A_auth_add_f_cap:
+                case A_auth_remove_f_cap:
+                #endif
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_cap_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_READ_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_system_role:
+                case A_cap_role:
+                case A_min_caps:
+                case A_max_caps:
+                case A_max_caps_user:
+                case A_max_caps_program:
+                case A_cap_process_hiding:
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer or Admin? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_cap_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if(   (i_attr_val1.system_role == SR_security_officer)
+                     || (i_attr_val1.system_role == SR_administrator)
+                    )
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_LOG:
+            switch(target)
+              {
+                case T_NONE:
+                  /* test owner's cap_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_cap_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are unknown */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_MODULE:
+            switch(target)
+              {
+                case T_NONE:
+                  /* we need the switch_target */
+                  if(attr != A_switch_target)
+                    return NOT_GRANTED;
+                  /* do not care for other modules */
+                  if(   (attr_val.switch_target != SW_CAP)
+                     #ifdef CONFIG_RSBAC_CAP_AUTH_PROT
+                     && (attr_val.switch_target != SW_AUTH)
+                     #endif
+                     #ifdef CONFIG_RSBAC_SOFTMODE
+                     && (attr_val.switch_target != SW_SOFTMODE)
+                     #endif
+                     #ifdef CONFIG_RSBAC_FREEZE
+                     && (attr_val.switch_target != SW_FREEZE)
+                     #endif
+                    )
+                    return(DO_NOT_CARE);
+                  /* test owner's cap_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_cap_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are unknown */
+                default:
+                  return DO_NOT_CARE;
+              }
+
+#ifdef CONFIG_RSBAC_CAP_PROC_HIDE
+        case R_CHANGE_GROUP:
+        case R_GET_STATUS_DATA:
+        case R_MODIFY_SYSTEM_DATA:
+        case R_SEND_SIGNAL:
+        case R_TRACE:
+          switch(target)
+            {
+              case T_PROCESS:
+                if(caller_pid == tid.process)
+                  return GRANTED;
+                if (rsbac_get_attr(SW_CAP,
+                                   target,
+                                   tid,
+                                   A_cap_process_hiding,
+                                   &i_attr_val1,
+                                   FALSE))
+                  {
+                    rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_process_hiding);
+                    return(NOT_GRANTED);  /* something weird happened */
+                  }
+                switch(i_attr_val1.cap_process_hiding)
+                  {
+                    case PH_full:
+                        /* Security Officer or Admin? */
+                        i_tid.user = owner;
+                        if (rsbac_get_attr(SW_CAP,
+                                           T_USER,
+                                           i_tid,
+                                           A_cap_role,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_role);
+                            return(NOT_GRANTED);
+                          }
+                        /* if sec_officer, then grant */
+                        if(i_attr_val1.system_role == SR_security_officer)
+                          return(GRANTED);
+                        else
+                          return(NOT_GRANTED);
+                    case PH_from_other_users:
+                      {
+                        struct task_struct * task_p;
+                        enum rsbac_adf_req_ret_t result;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                        if (rsbac_get_attr(SW_GEN,
+                                           T_PROCESS,
+                                           tid,
+                                           A_vset,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_ds_get_error("rsbac_adf_request_cap()", A_vset);
+                            return(NOT_GRANTED);
+                          }
+                        if (i_attr_val1.vset == RSBAC_UID_SET(owner))
+#endif
+                        {
+                          task_p = get_pid_task(tid.process, PIDTYPE_PID);
+                          if(task_p) {
+                            if(   pid_alive(task_p)
+                               && (__kuid_val(task_uid(task_p)) != RSBAC_UID_NUM(owner))
+                              ) {
+                              result = NOT_GRANTED;
+                            } else {
+                              result = GRANTED;
+                            }
+                            put_task_struct(task_p);
+                          } else {
+                            result = GRANTED;
+                          }
+                          if(result == GRANTED)
+                            return GRANTED;
+                        }
+                        /* Security Officer or Admin? */
+                        i_tid.user = owner;
+                        if (rsbac_get_attr(SW_CAP,
+                                           T_USER,
+                                           i_tid,
+                                           A_cap_role,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_ds_get_error("rsbac_adf_request_cap()", A_cap_role);
+                            return(NOT_GRANTED);
+                          }
+                        /* if sec_officer or admin, then grant */
+                        if(   (i_attr_val1.system_role == SR_security_officer)
+                           || (i_attr_val1.system_role == SR_administrator)
+                          )
+                          return(GRANTED);
+                        else
+                          return(NOT_GRANTED);
+                      }
+                    default:
+                      return DO_NOT_CARE;
+                  }
+
+              default:
+                return DO_NOT_CARE;
+            }
+#endif
+
+/*********************/
+        default: return DO_NOT_CARE;
+      }
+
+    return DO_NOT_CARE;
+  } /* end of rsbac_adf_request_cap() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up.                                                              */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+inline int rsbac_adf_set_attr_cap(
+                      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)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    switch (request)
+      {
+        case R_CHANGE_OWNER:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_owner)
+                    return(-RSBAC_EINVALIDATTR);
+			i_tid.user = attr_val.owner;
+			if (rsbac_get_attr(SW_CAP,
+					T_USER,
+					i_tid,
+					A_cap_ld_env,
+					&i_attr_val1, TRUE)) {
+				rsbac_ds_get_error
+					("rsbac_adf_set_attr_cap()",
+					 A_max_caps);
+			} else {
+				if (i_attr_val1.cap_ld_env == LD_keep) {
+					i_tid.process = caller_pid;
+					if (rsbac_get_attr(SW_CAP,
+							T_PROCESS,
+							i_tid,
+							A_cap_ld_env,
+							&i_attr_val1, FALSE)) {
+						rsbac_ds_set_error
+							("rsbac_adf_set_attr_cap()",
+							 A_cap_ld_env);
+					} else {
+						if (rsbac_set_attr(SW_CAP,
+								T_PROCESS,
+								tid,
+								A_cap_ld_env,
+								i_attr_val1)) {
+							rsbac_ds_set_error
+								("rsbac_adf_set_attr_cap()",
+								 A_cap_ld_env);
+						}
+					}
+				}
+			}
+                  /* Adjust Linux caps */
+                  i_tid.user = attr_val.owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_max_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_max_caps);
+                    }
+                  else
+                    {
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         || rsbac_ind_softmode[SW_CAP]
+                      #endif
+                        )
+                        { /* Warn */
+                          if((i_attr_val1.max_caps.cap[0] != RSBAC_CAP_DEFAULT_MAX) || (i_attr_val1.max_caps.cap[1] != RSBAC_CAP_DEFAULT_MAX))
+                            {
+                              rsbac_printk(KERN_NOTICE
+                                           "rsbac_adf_set_attr_cap(): running in softmode, max_caps of user %u not applied to process %u(%s)!\n",
+                                           owner,
+                                           pid_nr(caller_pid),
+                                           current->comm);
+                            }
+                        }
+                      else
+                      #endif
+                        {
+                          /* set caps for process */
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+				  return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] &= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+                          /* set max_caps_user for process */
+                          if (rsbac_set_attr(SW_CAP,
+                                             target,
+                                             tid,
+                                             A_max_caps_user,
+                                             i_attr_val1))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr_cap()", A_max_caps_user);
+                            }
+#endif
+                        }
+                    }
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_min_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_min_caps);
+                    }
+                  else
+                    {
+                      /* set caps for process */
+		      {
+      				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] |= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+		      }
+                    }
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return 0;
+              }
+            break;
+
+#if defined (CONFIG_RSBAC_CAP_PROC_HIDE) || defined(CONFIG_RSBAC_CAP_LOG_MISSING)
+        case R_CLONE:
+            switch(target)
+              {
+                case T_PROCESS:
+			i_tid.process = caller_pid;
+			if (rsbac_get_attr(SW_CAP,
+					   target,
+					   i_tid,
+					   A_cap_ld_env,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+					("rsbac_adf_set_attr_cap()",
+					 A_cap_ld_env);
+			} else {
+				if ((i_attr_val1.cap_ld_env != LD_allow) && rsbac_set_attr(SW_CAP,
+				    		   new_target,
+						   new_tid,
+						   A_cap_ld_env,
+						   i_attr_val1)) {
+						rsbac_ds_get_error
+							("rsbac_adf_set_attr_cap()",
+							 A_cap_ld_env);
+						   }
+			}
+#ifdef CONFIG_RSBAC_CAP_PROC_HIDE
+                  /* get process hiding from old process */
+                  if (rsbac_get_attr(SW_CAP,
+                                     target,
+                                     tid,
+                                     A_cap_process_hiding,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_cap_process_hiding);
+                    }
+                  else
+                    { /* only set, of not default value 0 */
+                      if(i_attr_val1.cap_process_hiding)
+                        {
+                          /* set program based log for new process */
+                          if (rsbac_set_attr(SW_CAP,
+                                             new_target,
+                                             new_tid,
+                                             A_cap_process_hiding,
+                                             i_attr_val1))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr_cap()", A_cap_process_hiding);
+                            }
+                        }
+                    }
+#endif
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+                  /* get max_caps_user from old process */
+                  if (rsbac_get_attr(SW_CAP,
+                                     target,
+                                     tid,
+                                     A_max_caps_user,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap():CLONE", A_max_caps_user);
+                    }
+                  else
+                    { /* only set, of not default value */
+                      if((i_attr_val1.max_caps_user.cap[0] != RSBAC_CAP_DEFAULT_MAX) || (i_attr_val1.max_caps_user.cap[1] != RSBAC_CAP_DEFAULT_MAX))
+                        {
+                          if (rsbac_set_attr(SW_CAP,
+                                             new_target,
+                                             new_tid,
+                                             A_max_caps_user,
+                                             i_attr_val1))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr_cap():CLONE", A_max_caps_user);
+                            }
+                        }
+                    }
+                  /* get max_caps_program from old process */
+                  if (rsbac_get_attr(SW_CAP,
+                                     target,
+                                     tid,
+                                     A_max_caps_program,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap():CLONE", A_max_caps_program);
+                    }
+                  else
+                    { /* only set, of not default value */
+                      if((i_attr_val1.max_caps_program.cap[0] != RSBAC_CAP_DEFAULT_MAX) || (i_attr_val1.max_caps_program.cap[1] != RSBAC_CAP_DEFAULT_MAX))
+                        {
+                          if (rsbac_set_attr(SW_CAP,
+                                             new_target,
+                                             new_tid,
+                                             A_max_caps_program,
+                                             i_attr_val1))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr_cap():CLONE", A_max_caps_program);
+                            }
+                        }
+                    }
+#endif
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return 0;
+              }
+#endif /* PROC_HIDE || LOG_MISSING */
+
+        case R_EXECUTE:
+            switch(target)
+              {
+                case T_FILE:
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_CAP,
+					   T_USER,
+					   i_tid,
+					   A_cap_ld_env,
+					   &i_attr_val1, TRUE)) {
+				rsbac_ds_get_error("rsbac_adf_set_attr_cap()",A_cap_ld_env);
+			} else {
+				if (i_attr_val1.cap_ld_env == LD_keep) {
+					i_tid.process = caller_pid;
+					if (rsbac_get_attr(SW_CAP,
+							   T_PROCESS,
+							   i_tid,
+							   A_cap_ld_env,
+							   &i_attr_val1, FALSE)) {
+					rsbac_ds_get_error("rsbac_adf_set_attr_cap()",
+							A_cap_ld_env);
+					}
+				i_tid.process = caller_pid;
+				if (rsbac_set_attr(SW_CAP,
+						   T_PROCESS,
+						   i_tid,
+						   A_cap_ld_env,
+						   i_attr_val1)) {
+					rsbac_ds_get_error("rsbac_adf_set_attr_cap()",
+							A_cap_ld_env);
+				}
+			     }
+			}
+                  /* Adjust Linux caps - first user, then program based */
+                  /* User must be redone, because caps are cleared by Linux kernel */
+		  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_max_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_max_caps);
+                    }
+                  else
+                    {
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         || rsbac_ind_softmode[SW_CAP]
+                      #endif
+                        )
+                        { /* Warn */
+                          if((i_attr_val1.max_caps.cap[0] != RSBAC_CAP_DEFAULT_MAX) || (i_attr_val1.max_caps.cap[1] != RSBAC_CAP_DEFAULT_MAX))
+                            {
+                              rsbac_printk(KERN_NOTICE
+                                           "rsbac_adf_set_attr_cap(): running in softmode, max_caps of user %u not applied to process %u(%s)!\n",
+                                           owner,
+                                           pid_nr(caller_pid),
+                                           current->comm);
+                            }
+                        }
+                      else
+                      #endif
+                        {
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] &= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+                        }
+                    }
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_min_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_min_caps);
+                    }
+                  else
+                    {
+                      /* set caps for process */
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] |= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+                    }
+                  if (rsbac_get_attr(SW_CAP,
+                                     target,
+                                     tid,
+                                     A_max_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_max_caps);
+                    }
+                  else
+                    {
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         || rsbac_ind_softmode[SW_CAP]
+                      #endif
+                        )
+                        { /* Warn */
+                          if((i_attr_val1.max_caps.cap[0] != RSBAC_CAP_DEFAULT_MAX) || (i_attr_val1.max_caps.cap[1] != RSBAC_CAP_DEFAULT_MAX))
+                            {
+                              rsbac_printk(KERN_NOTICE
+                                           "rsbac_adf_set_attr_cap(): running in softmode, max_caps of program not applied to process %u(%s)!\n",
+                                           pid_nr(caller_pid),
+                                           current->comm);
+                            }
+                        }
+                      else
+                      #endif
+                        {
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] &= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+                          i_tid.process = caller_pid;
+                          /* set max_caps_program for process */
+                          if (rsbac_set_attr(SW_CAP,
+                                             T_PROCESS,
+                                             i_tid,
+                                             A_max_caps_program,
+                                             i_attr_val1))
+                            {
+                              rsbac_ds_set_error("rsbac_adf_set_attr_cap():EXECUTE", A_max_caps_program);
+                            }
+#endif
+                        }
+                    }
+                  if (rsbac_get_attr(SW_CAP,
+                                     target,
+                                     tid,
+                                     A_min_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_min_caps);
+                    }
+                  else
+                    {
+                      /* set caps for process */
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] |= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+                    }
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return 0;
+              }
+            break;
+
+        case R_MODIFY_SYSTEM_DATA:
+            switch(target)
+              {
+                case T_SCD:
+                  if (tid.scd != ST_capability)
+                    return 0;
+
+                  /* Adjust Linux caps - user only */
+                  /* User must be redone, because caps have been changed by sys_capset() */
+		  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_max_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_max_caps);
+                    }
+                  else
+                    {
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         || rsbac_ind_softmode[SW_CAP]
+                      #endif
+                        )
+                        { /* Warn */
+                          if((i_attr_val1.max_caps.cap[0] != RSBAC_CAP_DEFAULT_MAX) || (i_attr_val1.max_caps.cap[1] != RSBAC_CAP_DEFAULT_MAX))
+                            {
+                              rsbac_printk(KERN_NOTICE
+                                           "rsbac_adf_set_attr_cap(): running in softmode, max_caps of user %u not applied to process %u(%s)!\n",
+                                           owner,
+                                           pid_nr(caller_pid),
+                                           current->comm);
+                            }
+                        }
+                      else
+                      #endif
+                        {
+                          /* set caps for process */
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] & i_attr_val1.max_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] & i_attr_val1.max_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] &= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] &= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] &= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+                        }
+                    }
+                  if (rsbac_get_attr(SW_CAP,
+                                     T_USER,
+                                     i_tid,
+                                     A_min_caps,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_set_attr_cap()", A_min_caps);
+                    }
+                  else
+                    {
+                      /* set caps for process */
+				struct cred *override_cred;
+				override_cred = prepare_creds();
+				if (!override_cred)
+					return -ENOMEM;
+                                if (   ((override_cred->cap_permitted.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+                                    || ((override_cred->cap_effective.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_effective.cap[0])
+                                    || ((override_cred->cap_inheritable.cap[0] | i_attr_val1.min_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+                                    || ((override_cred->cap_permitted.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+                                    || ((override_cred->cap_effective.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_effective.cap[1])
+                                    || ((override_cred->cap_inheritable.cap[1] | i_attr_val1.min_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+				   ) {
+                                	override_cred->cap_permitted.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_effective.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_inheritable.cap[0] |= i_attr_val1.max_caps.cap[0];
+					override_cred->cap_permitted.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_effective.cap[1] |= i_attr_val1.max_caps.cap[1];
+					override_cred->cap_inheritable.cap[1] |= i_attr_val1.max_caps.cap[1];
+					commit_creds(override_cred);
+				} else {
+                                	abort_creds(override_cred);
+				}
+                    }
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return 0;
+              }
+            break;
+
+/*********************/
+        default: return 0;
+      }
+
+    return 0;
+  } /* end of rsbac_adf_set_attr_cap() */
+
+/* end of rsbac/adf/cap/main.c */
diff --git a/rsbac/adf/daz/Makefile b/rsbac/adf/daz/Makefile
new file mode 100644
index 0000000..823c83d
--- /dev/null
+++ b/rsbac/adf/daz/Makefile
@@ -0,0 +1,9 @@
+#
+# File: rsbac/adf/daz/Makefile
+#
+# Makefile for the Linux rsbac DAZ decision module.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := daz_main.o dazuko_xp.o
diff --git a/rsbac/adf/daz/daz_main.c b/rsbac/adf/daz/daz_main.c
new file mode 100644
index 0000000..a3392b1
--- /dev/null
+++ b/rsbac/adf/daz/daz_main.c
@@ -0,0 +1,1165 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Dazuko Malware Scan              */
+/* File: rsbac/adf/daz/daz_main.c                    */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Copyright (c) 2004 H+BEDV Datentechnik GmbH       */
+/* Written by John Ogness <jogness@antivir.de>       */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+/* Dazuko RSBAC. 
+   Allow RSBAC Linux file access control for 3rd-party applications.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+   */
+
+#include "dazuko_rsbac.h"
+#include "dazuko_xp.h"
+#include "dazukoio.h"
+
+#include <linux/init.h>
+#include <linux/unistd.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/syscalls.h>
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/debug.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/net_getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/proc_fs.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+#include <linux/device.h>
+
+#define DAZ_MAX_FILENAME PATH_MAX
+
+ssize_t linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos);
+ssize_t linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos);
+long linux_dazuko_device_ioctl(struct file *file, unsigned int cmd, unsigned long param);
+int linux_dazuko_device_open(struct inode *inode, struct file *file);
+int linux_dazuko_device_release(struct inode *inode, struct file *file);
+
+extern struct xp_atomic active;
+
+static int			dev_major = -1;
+
+static struct file_operations	fops = {
+	read: linux_dazuko_device_read,		/* read */
+	write: linux_dazuko_device_write,	/* write */
+	unlocked_ioctl: linux_dazuko_device_ioctl,	/* ioctl */
+	open: linux_dazuko_device_open,		/* open */
+	release: linux_dazuko_device_release,	/* release */
+};
+
+static struct class *dazuko_class = NULL;
+
+static struct kmem_cache * dazuko_file_slab = NULL;
+static struct kmem_cache * xp_file_slab = NULL;
+static struct kmem_cache * xp_daemon_slab = NULL;
+static struct kmem_cache * dazuko_filename_slab = NULL;
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+static int daz_reset_scanned(struct rsbac_fs_file_t file)
+{
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_target_id_t       i_tid;
+
+	/* reset scanned status for file */
+	rsbac_pr_debug(adf_daz, "pid %u(%s), resetting scanned status!\n",
+				       current->pid, current->comm);
+	i_tid.file=file;
+	i_attr_val1.daz_scanned = DAZ_unscanned;
+	if(rsbac_set_attr(SW_DAZ,
+				T_FILE,
+				i_tid,
+				A_daz_scanned,
+				i_attr_val1))
+	{
+		rsbac_printk(KERN_WARNING "daz_reset_scanned(): rsbac_set_attr() for daz_scanned on device %02u:%02u inode %lu returned error!\n",
+			MAJOR(file.device), MINOR(file.device), file.inode);
+		return -RSBAC_EWRITEFAILED;
+	}
+	if (rsbac_get_attr(SW_DAZ,
+		T_FILE,
+		i_tid,
+		A_daz_scanner,
+		&i_attr_val1,
+		FALSE)) {
+		rsbac_printk(KERN_WARNING
+			"daz_reset_scanned(): rsbac_get_attr() for daz_scanner returned error!\n");
+		return -RSBAC_EREADFAILED;
+	}
+	if (i_attr_val1.daz_scanner) {
+		/* reset scanner flag for file */
+		i_attr_val1.daz_scanner = FALSE;
+		if(rsbac_set_attr(SW_DAZ,
+					T_FILE,
+					i_tid,
+					A_daz_scanner,
+					i_attr_val1))
+		{
+			rsbac_printk(KERN_WARNING "daz_reset_scanned(): rsbac_set_attr() for daz_scanner on device %02u:%02u inode %lu returned error!\n",
+				MAJOR(file.device), MINOR(file.device), file.inode);
+			return -RSBAC_EWRITEFAILED;
+		}
+	}
+	return 0;
+}
+#else
+static inline int daz_reset_scanned(struct rsbac_fs_file_t file)
+{
+	return 0;
+}
+#endif
+
+
+/* mutex */
+
+inline int xp_init_mutex(struct xp_mutex *mutex)
+{
+#ifdef init_MUTEX
+	init_MUTEX(&(mutex->mutex));
+#else
+	sema_init(&(mutex->mutex), 1);
+#endif
+
+	return 0;
+}
+
+inline int xp_down(struct xp_mutex *mutex)
+{
+	down(&(mutex->mutex));
+	return 0;
+}
+
+inline int xp_up(struct xp_mutex *mutex)
+{
+	up(&(mutex->mutex));
+	return 0;
+}
+
+inline int xp_destroy_mutex(struct xp_mutex *mutex)
+{
+	return 0;
+}
+
+
+/* read-write lock */
+
+inline int xp_init_rwlock(struct xp_rwlock *rwlock)
+{
+	rwlock_init(&(rwlock->rwlock));
+	return 0;
+}
+
+inline int xp_write_lock(struct xp_rwlock *rwlock)
+{
+	write_lock(&(rwlock->rwlock));
+	return 0;
+}
+
+inline int xp_write_unlock(struct xp_rwlock *rwlock)
+{
+	write_unlock(&(rwlock->rwlock));
+	return 0;
+}
+
+inline int xp_read_lock(struct xp_rwlock *rlock)
+{
+	read_lock(&(rlock->rwlock));
+	return 0;
+}
+
+inline int xp_read_unlock(struct xp_rwlock *rlock)
+{
+	read_unlock(&(rlock->rwlock));
+	return 0;
+}
+
+inline int xp_destroy_rwlock(struct xp_rwlock *rwlock)
+{
+	return 0;
+}
+
+
+/* wait-notify queue */
+
+inline int xp_init_queue(struct xp_queue *queue)
+{
+	init_waitqueue_head(&(queue->queue));
+	return 0;
+}
+
+inline int xp_wait_until_condition(struct xp_queue *queue, int (*cfunction)(void *), void *cparam, int allow_interrupt)
+{
+	/* wait until cfunction(cparam) != 0 (condition is true) */
+
+	if (allow_interrupt)
+	{
+		return wait_event_interruptible(queue->queue, cfunction(cparam) != 0);
+	}
+	else
+	{
+		wait_event(queue->queue, cfunction(cparam) != 0);
+	}
+
+	return 0;
+}
+
+inline int xp_notify(struct xp_queue *queue)
+{
+	wake_up(&(queue->queue));
+	return 0;
+}
+
+inline int xp_destroy_queue(struct xp_queue *queue)
+{
+	return 0;
+}
+
+
+/* memory */
+
+inline int xp_copyin(const void *user_src, void *kernel_dest, size_t size)
+{
+	return copy_from_user(kernel_dest, user_src, size);
+}
+
+inline int xp_copyout(const void *kernel_src, void *user_dest, size_t size)
+{
+	return copy_to_user(user_dest, kernel_src, size);
+}
+
+inline int xp_verify_user_writable(const void *user_ptr, size_t size)
+{
+	return 0;
+}
+
+inline int xp_verify_user_readable(const void *user_ptr, size_t size)
+{
+	return 0;
+}
+
+
+/* path attribute */
+
+inline int xp_is_absolute_path(const char *path)
+{
+	return (path[0] == '/');
+}
+
+
+/* atomic */
+
+inline int xp_atomic_set(struct xp_atomic *atomic, int value)
+{
+	atomic_set(&(atomic->atomic), value);
+	return 0;
+}
+
+inline int xp_atomic_inc(struct xp_atomic *atomic)
+{
+	atomic_inc(&(atomic->atomic));
+	return 0;
+}
+
+inline int xp_atomic_dec(struct xp_atomic *atomic)
+{
+	atomic_dec(&(atomic->atomic));
+	return 0;
+}
+
+inline int xp_atomic_read(struct xp_atomic *atomic)
+{
+	return atomic_read(&(atomic->atomic));
+}
+
+
+/* file descriptor */
+
+inline int xp_copy_file(struct xp_file *dest, struct xp_file *src)
+{
+	return 0;
+}
+
+inline int xp_compare_file(struct xp_file *file1, struct xp_file *file2)
+{
+	return 0;
+}
+
+inline int xp_fill_file_struct(struct dazuko_file_struct *dfs)
+{
+	/* make sure we have access to everything */
+	if (dfs == NULL)
+		return -1;
+
+	if (dfs->extra_data == NULL)
+		return -1;
+
+	if (dfs->extra_data->dentry == NULL)
+		return -1;
+
+	if (dfs->extra_data->dentry->d_inode == NULL)
+		return -1;
+
+	/* ok, we have everything we need */
+
+	dfs->extra_data->full_filename = rsbac_smalloc_unlocked(dazuko_filename_slab);
+	if (dfs->extra_data->full_filename == NULL)
+		return -1;
+	rsbac_lookup_full_path(dfs->extra_data->dentry, dfs->extra_data->full_filename, DAZ_MAX_FILENAME, 0);
+
+	rsbac_pr_debug(adf_daz, "pid %u(%s), file is %s!\n",
+				       current->pid, current->comm,
+				       dfs->extra_data->full_filename);
+
+	/* find the actual value of the length */
+	dfs->extra_data->full_filename_length = strlen(dfs->extra_data->full_filename);
+
+	/* reference copy of full path */
+	dfs->filename = dfs->extra_data->full_filename;
+	dfs->filename_length = dfs->extra_data->full_filename_length;
+
+	dfs->file_p.size = dfs->extra_data->dentry->d_inode->i_size;
+	dfs->file_p.set_size = 1;
+	dfs->file_p.uid = __kuid_val(dfs->extra_data->dentry->d_inode->i_uid);
+	dfs->file_p.set_uid = 1;
+	dfs->file_p.gid = __kgid_val(dfs->extra_data->dentry->d_inode->i_gid);
+	dfs->file_p.set_gid = 1;
+	dfs->file_p.mode = dfs->extra_data->dentry->d_inode->i_mode;
+	dfs->file_p.set_mode = 1;
+	dfs->file_p.device_type = dfs->extra_data->dentry->d_inode->i_rdev;
+	dfs->file_p.set_device_type = 1;
+
+	return 0;
+}
+
+static int dazuko_file_struct_cleanup(struct dazuko_file_struct **dfs)
+{
+	if (dfs == NULL)
+		return 0;
+
+	if (*dfs == NULL)
+		return 0;
+
+	if ((*dfs)->extra_data != NULL)
+	{
+		if ((*dfs)->extra_data->full_filename)
+			rsbac_sfree(dazuko_filename_slab, (*dfs)->extra_data->full_filename);
+
+		rsbac_sfree(xp_file_slab, (*dfs)->extra_data);
+	}
+
+	rsbac_sfree(dazuko_file_slab, *dfs);
+
+	*dfs = NULL;
+
+	return 0;
+}
+
+
+/* daemon id */
+
+int xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2)
+{
+	if (id1 == NULL || id2 == NULL)
+		return -1;
+
+	/* if file's are available and they match,
+	 * then we say that the id's match */
+	if (id1->file != NULL && id1->file == id2->file)
+		return 0;
+
+	if (id1->pid == id2->pid)
+		return 0;
+
+	return 1;
+}
+
+int xp_id_free(struct xp_daemon_id *id)
+{
+	rsbac_sfree(xp_daemon_slab, id);
+	return 0;
+}
+
+struct xp_daemon_id* xp_id_copy(struct xp_daemon_id *id)
+{
+	struct xp_daemon_id	*ptr;
+
+	if (id == NULL)
+		return NULL;
+
+	ptr = rsbac_smalloc(xp_daemon_slab);
+
+	if (ptr != NULL)
+	{
+		ptr->pid = id->pid;
+		ptr->file = id->file;
+	}
+	return ptr;
+}
+
+
+/* system hook */
+
+inline int xp_sys_hook()
+{
+	int wanted_major = CONFIG_RSBAC_DAZ_DEV_MAJOR;
+
+	/* Called from insmod when inserting the module. */
+	/* register the dazuko device */
+	if((wanted_major > 0) && (wanted_major <= 254)) {
+		dev_major = register_chrdev(wanted_major, DEVICE_NAME, &fops);
+		if (dev_major < 0) {
+			rsbac_printk(KERN_WARNING "dazuko: unable to register major chrdev %u, err=%d\n",
+				wanted_major, dev_major);
+			return dev_major;
+		}
+		dev_major = wanted_major;
+		dazuko_class = class_create(THIS_MODULE, "dazuko");
+		device_create(dazuko_class, NULL,
+				MKDEV(wanted_major, 0),
+				NULL, "dazuko");
+	} else {
+		dev_major = register_chrdev(0, DEVICE_NAME, &fops);
+		if (dev_major < 0) {
+			rsbac_printk(KERN_WARNING "dazuko: unable to register any major chrdev, err=%d\n",
+				dev_major);
+			return dev_major;
+		}
+		dazuko_class = class_create(THIS_MODULE, "dazuko");
+		device_create(dazuko_class, NULL,
+				MKDEV(dev_major, 0),
+				NULL, "dazuko");
+	}
+	return 0;
+}
+
+inline int xp_sys_unhook()
+{
+	/* Called by rmmod when removing the module. */
+	unregister_chrdev(dev_major, DEVICE_NAME);
+	device_destroy(dazuko_class, MKDEV(dev_major, CONFIG_RSBAC_DAZ_DEV_MAJOR));
+	class_destroy(dazuko_class);
+
+	return 0;
+}
+
+
+/* ioctl's */
+
+int linux_dazuko_device_open(struct inode *inode, struct file *file)
+{
+	DPRINT(("dazuko: linux_dazuko_device_open() [%d]\n", current->pid));
+
+	return 0;
+}
+
+ssize_t linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos)
+{
+	/* Reading from the dazuko device simply
+	 * returns the device number. This is to
+	 * help out the daemon. */
+
+	char	tmp[20];
+	size_t	dev_major_len;
+
+	DPRINT(("dazuko: linux_dazuko_device_read() [%d]\n", current->pid));
+
+	/* only one read is allowed */
+	if (*pos != 0)
+		return 0;
+
+	if (dev_major < 0)
+		return -ENODEV;
+
+	/* print dev_major to a string
+	 * and get length (with terminator) */
+	dazuko_bzero(tmp, sizeof(tmp));
+
+	dev_major_len = dazuko_snprintf(tmp, sizeof(tmp), "%d", dev_major) + 1;
+
+	if (tmp[sizeof(tmp)-1] != 0)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: failing device_read, device number overflow for dameon %d (dev_major=%d)\n", current->pid, dev_major);
+		return -EFAULT;
+	}
+
+	if (length < dev_major_len)
+		return -EINVAL;
+
+	/* copy dev_major string to userspace */
+	if (xp_copyout(tmp, buffer, dev_major_len) != 0)
+		return -EFAULT;
+
+	*pos = dev_major_len;
+
+	return dev_major_len;
+}
+
+ssize_t linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos)
+{
+	struct dazuko_request	*u_request;
+	struct xp_daemon_id	xp_id;
+	char			tmpbuffer[32];
+	char			*value;
+	unsigned int		size;
+
+	size = length;
+	if (length >= sizeof(tmpbuffer))
+		size = sizeof(tmpbuffer) -1;
+
+	/* copy request pointer string to kernelspace */
+	if (xp_copyin(buffer, tmpbuffer, size) != 0)
+		return -EFAULT;
+
+	tmpbuffer[size] = 0;
+
+	if (dazuko_get_value("\nRA=", buffer, &value) != 0)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: error: linux_dazuko_device_write.RA missing\n");
+		return -EFAULT;
+	}
+
+	u_request = (struct dazuko_request *)simple_strtoul(value, NULL, 10);
+
+	rsbac_kfree(value);
+
+	xp_id.pid = current->pid;
+	xp_id.file = file;
+
+	if (dazuko_handle_user_request(u_request, &xp_id) == 0)
+		return length;
+	else
+		return -EINTR;
+}
+
+long linux_dazuko_device_ioctl(struct file *file, unsigned int cmd, unsigned long param)
+{
+	/* A daemon uses this function to interact with
+	 * the kernel. A daemon can set scanning parameters,
+	 * give scanning response, and get filenames to scan. */
+
+	struct xp_daemon_id	xp_id;
+	int			error = 0;
+
+	if (param == 0)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: error: linux_dazuko_device_ioctl(..., 0)\n");
+		return -EFAULT;
+	}
+
+	xp_id.pid = current->pid;
+	xp_id.file = file;
+
+	error = dazuko_handle_user_request_compat12((void *)param, _IOC_NR(cmd), &xp_id);
+
+	if (error != 0)
+	{
+		/* general error occurred */
+
+		return -EPERM;
+	}
+
+	return error;
+}
+
+int linux_dazuko_device_release(struct inode *inode, struct file *file)
+{
+	struct xp_daemon_id	xp_id;
+
+	DPRINT(("dazuko: dazuko_device_release() [%d]\n", current->pid));
+
+	xp_id.pid = current->pid;
+	xp_id.file = file;
+
+	return dazuko_unregister_daemon(&xp_id);
+}
+
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_daz(void)
+#else
+int __init rsbac_init_daz(void)
+#endif
+{
+	if (rsbac_is_initialized())
+	{
+		rsbac_printk(KERN_WARNING "rsbac_init_daz(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+
+	/* init data structures */
+	rsbac_printk(KERN_INFO "rsbac_init_daz(): Initializing RSBAC: DAZuko subsystem\n");
+
+	dazuko_file_slab = rsbac_slab_create("rsbac_daz_file",
+					sizeof(struct dazuko_file_struct));
+	xp_file_slab = rsbac_slab_create("rsbac_daz_xp_file",
+					sizeof(struct xp_file_struct));
+	xp_daemon_slab = rsbac_slab_create("rsbac_daz_xp_daemon",
+					sizeof(struct xp_daemon_id));
+	dazuko_filename_slab = rsbac_slab_create("rsbac_daz_filename",
+					DAZ_MAX_FILENAME);
+
+	return dazuko_init();
+}
+
+static int daz_ignored(union rsbac_target_id_t tid)
+{
+	union rsbac_attribute_value_t i_attr_val1;
+
+	if (rsbac_get_attr(SW_DAZ,
+		T_FILE,
+		tid,
+		A_daz_do_scan,
+		&i_attr_val1,
+		TRUE)) {
+		rsbac_printk(KERN_WARNING
+			"rsbac_adf_request_daz(): rsbac_get_attr() for daz_do_scan returned error!\n");
+		return FALSE;
+	}
+	if(i_attr_val1.daz_do_scan == DAZ_never)
+		return TRUE;
+	return FALSE;
+}
+
+static enum rsbac_adf_req_ret_t daz_check_secoff(rsbac_uid_t owner, enum rsbac_attribute_t attr)
+{
+	union rsbac_target_id_t       i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	switch(attr) {
+		case A_daz_scanned:
+		case A_daz_scanner:
+		case A_system_role:
+		case A_daz_role:
+		case A_daz_do_scan:
+			/* All attributes (remove target!) */
+		case A_none:
+			/* Security Officer? */
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_DAZ,
+				T_USER,
+				i_tid,
+				A_daz_role,
+				&i_attr_val1,
+				FALSE)) {
+				rsbac_printk(KERN_WARNING
+						"rsbac_adf_request_daz(): rsbac_get_attr() returned error!\n");
+				return NOT_GRANTED;
+			}
+			/* if sec_officer, then grant */
+			if (i_attr_val1.system_role == SR_security_officer)
+				return GRANTED;
+			else
+				return NOT_GRANTED;
+
+		default:
+			return DO_NOT_CARE;
+	}
+}
+
+inline enum rsbac_adf_req_ret_t
+rsbac_adf_request_daz (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)
+{
+	struct dazuko_file_struct *dfs = NULL;
+	struct xp_daemon_id xp_id;
+	int error = 0;
+	int check_error = 0;
+	struct event_properties event_p;
+	int event;
+	int daemon_allowed;
+
+	union rsbac_target_id_t       i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	/* get daz_do_scan for target */
+	switch(target) {
+		case T_FILE:
+			switch(request) {
+				case R_DELETE:
+					if(daz_ignored(tid))
+						return DO_NOT_CARE;
+					event = DAZUKO_ON_UNLINK;
+					daemon_allowed = 1;
+					break;
+				case R_CLOSE:
+					if(daz_ignored(tid))
+						return DO_NOT_CARE;
+					event = DAZUKO_ON_CLOSE;
+					daemon_allowed = 1;
+					break;
+				case R_EXECUTE:
+					if(daz_ignored(tid))
+						return DO_NOT_CARE;
+					event = DAZUKO_ON_EXEC;
+					daemon_allowed = 0;
+					break;
+				case R_READ_WRITE_OPEN:
+				case R_READ_OPEN:
+					if(daz_ignored(tid))
+						return DO_NOT_CARE;
+					event = DAZUKO_ON_OPEN;
+					daemon_allowed = 1;
+					break;
+				case R_READ_ATTRIBUTE:
+				case R_MODIFY_ATTRIBUTE:
+					return daz_check_secoff(owner, attr);
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		case T_DIR:
+			switch(request) {
+				case R_DELETE:
+					if(daz_ignored(tid))
+						return DO_NOT_CARE;
+					event = DAZUKO_ON_RMDIR;
+					daemon_allowed = 1;
+					break;
+				case R_READ_ATTRIBUTE:
+				case R_MODIFY_ATTRIBUTE:
+					return daz_check_secoff(owner, attr);
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		case T_DEV:
+			switch(request) {
+				case R_READ_WRITE_OPEN:
+				case R_READ_OPEN:
+				case R_APPEND_OPEN:
+				case R_WRITE_OPEN:
+					if(   (tid.dev.type == D_char)
+						&& (tid.dev.major == CONFIG_RSBAC_DAZ_DEV_MAJOR)
+					  ) {
+						i_tid.process = caller_pid;
+						if (rsbac_get_attr(SW_DAZ,
+									T_PROCESS,
+									i_tid,
+									A_daz_scanner,
+									&i_attr_val1,
+									FALSE)) {
+							rsbac_printk(KERN_WARNING
+									"rsbac_adf_request_daz(): rsbac_get_attr() returned error!\n");
+							return NOT_GRANTED;
+						}
+						/* if scanner, then grant */
+						if (i_attr_val1.daz_scanner)
+							return GRANTED;
+						else
+							return NOT_GRANTED;
+					}
+					else
+						return DO_NOT_CARE;
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		case T_PROCESS:
+			switch(request) {
+				case R_READ_ATTRIBUTE:
+				case R_MODIFY_ATTRIBUTE:
+					return daz_check_secoff(owner, attr);
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		case T_USER:
+			switch(request) {
+				case R_READ_ATTRIBUTE:
+				case R_MODIFY_ATTRIBUTE:
+					return daz_check_secoff(owner, attr);
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		case T_NONE:
+			switch(request) {
+				case R_SWITCH_MODULE:
+					/* we need the switch_target */
+					if(attr != A_switch_target)
+						return NOT_GRANTED;
+					/* do not care for other modules */
+					if(   (attr_val.switch_target != SW_DAZ)
+#ifdef CONFIG_RSBAC_SOFTMODE
+						&& (attr_val.switch_target != SW_SOFTMODE)
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+						&& (attr_val.switch_target != SW_FREEZE)
+#endif
+					  )
+						return DO_NOT_CARE;
+					return daz_check_secoff(owner, attr);
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		default:
+			return DO_NOT_CARE;
+	}
+
+/* From here we can only have FILE or DIR targets */
+
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	if (rsbac_get_attr(SW_DAZ,
+				target,
+				tid,
+				A_daz_scanned,
+				&i_attr_val1,
+				FALSE))
+	{
+		rsbac_printk(KERN_WARNING
+				"rsbac_adf_request_daz(): rsbac_get_attr() returned error!\n");
+		return NOT_GRANTED;
+	}
+	if(i_attr_val1.daz_scanned == DAZ_clean)
+		return GRANTED;
+#endif
+
+	rsbac_pr_debug(adf_daz, "pid %u(%s), scanning required!\n",
+				       current->pid, current->comm);
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+
+	check_error = dazuko_sys_check(event, daemon_allowed, &xp_id);
+
+	if (!check_error)
+	{
+		dazuko_bzero(&event_p, sizeof(event_p));
+		/*
+		   event_p.flags = flags;
+		   event_p.set_flags = 1;
+		   event_p.mode = mode;
+		   event_p.set_mode = 1;
+		   */
+		event_p.pid = current->pid;
+		event_p.set_pid = 1;
+		event_p.uid = __kuid_val(current_uid());
+		event_p.set_uid = 1;
+
+		dfs = rsbac_smalloc_clear_unlocked(dazuko_file_slab);
+		if (dfs != NULL)
+		{
+			dfs->extra_data = rsbac_smalloc_clear_unlocked(xp_file_slab);
+			if (dfs->extra_data != NULL)
+			{
+				dfs->extra_data->dentry = tid.file.dentry_p;
+
+				error = dazuko_sys_pre(event, dfs, NULL, &event_p);
+
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+				if(error != 2) {
+					if(error == 0)
+						i_attr_val1.daz_scanned = DAZ_clean;
+					else
+						i_attr_val1.daz_scanned = DAZ_infected;
+
+					if (rsbac_set_attr(SW_DAZ,
+								target,
+								tid,
+								A_daz_scanned,
+								i_attr_val1))
+					{
+						rsbac_printk(KERN_WARNING "rsbac_adf_request_daz(): rsbac_set_attr() returned error!\n");
+						dazuko_file_struct_cleanup(&dfs);
+						return NOT_GRANTED;
+					}
+				}
+#endif
+				rsbac_pr_debug(adf_daz, "pid %u(%s), dazuko_sys_pre() result is %i\n",
+				       current->pid, current->comm, error);
+			}
+			else
+			{
+				rsbac_sfree(dazuko_file_slab, dfs);
+				dfs = NULL;
+			}
+
+			dazuko_file_struct_cleanup(&dfs);
+		}
+		if(error == 2)
+			return DO_NOT_CARE;
+		if(error == 0) {
+			rsbac_pr_debug(adf_daz, "pid %u(%s), file clean!\n",
+				       current->pid, current->comm);
+			return GRANTED;
+		} else {
+			rsbac_pr_debug(adf_daz, "pid %u(%s), file infected!\n",
+				       current->pid, current->comm);
+			return NOT_GRANTED;
+		}
+	}
+	rsbac_pr_debug(adf_daz, "pid %u(%s), dazuko_sys_check() result is %i\n",
+	       current->pid, current->comm, check_error);
+	return DO_NOT_CARE;
+} /* end of rsbac_adf_request_daz() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up. Because of this, the write boundary is not adjusted - there  */
+/* is no user-level writing anyway...                                        */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+inline int rsbac_adf_set_attr_daz(
+		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)
+{
+	struct dazuko_file_struct *dfs = NULL;
+	struct xp_daemon_id xp_id;
+	int check_error = 0;
+	struct event_properties event_p;
+	int event;
+	int daemon_allowed;
+	union rsbac_target_id_t       i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_attribute_value_t i_attr_val2;
+
+	switch(target) {
+		case T_FILE:
+			switch(request) {
+				case R_EXECUTE:
+					/* get daz_scanner for file */
+					if (rsbac_get_attr(SW_DAZ,
+								T_FILE,
+								tid,
+								A_daz_scanner,
+								&i_attr_val1,
+								FALSE))
+					{
+						rsbac_printk(KERN_WARNING
+								"rsbac_adf_set_attr_daz(): rsbac_get_attr() returned error!\n");
+						return -RSBAC_EREADFAILED;
+					}
+					/* get for process */
+					i_tid.process = caller_pid;
+					if (rsbac_get_attr(SW_DAZ,
+								T_PROCESS,
+								i_tid,
+								A_daz_scanner,
+								&i_attr_val2,
+								FALSE))
+					{
+						rsbac_printk(KERN_WARNING
+							"rsbac_adf_set_attr_daz(): rsbac_get_attr() returned error!\n");
+						return -RSBAC_EREADFAILED;
+					}
+					/* and set for process, if different */
+					if(i_attr_val1.daz_scanner != i_attr_val2.daz_scanner)
+						if (rsbac_set_attr(SW_DAZ,
+								T_PROCESS,
+								i_tid,
+								A_daz_scanner,
+								i_attr_val1))
+						{
+							rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_daz(): rsbac_set_attr() returned error!\n");
+							return -RSBAC_EWRITEFAILED;
+						}
+					if(daz_ignored(tid))
+						return 0;
+					event = DAZUKO_ON_EXEC;
+					daemon_allowed = 0;
+					break;
+				case R_WRITE:
+					if(daz_ignored(tid))
+						return 0;
+					daz_reset_scanned(tid.file);
+					return 0;
+				case R_CLOSE:
+					if(daz_ignored(tid))
+						return 0;
+					event = DAZUKO_ON_CLOSE;
+					daemon_allowed = 1;
+					if(   (attr == A_f_mode)
+							&& (attr_val.f_mode & FMODE_WRITE)
+					)
+						daz_reset_scanned(tid.file);
+					break;
+				case R_READ_OPEN:
+					if(daz_ignored(tid))
+						return 0;
+					event = DAZUKO_ON_OPEN;
+					daemon_allowed = 1;
+					break;
+				case R_APPEND_OPEN:
+				case R_READ_WRITE_OPEN:
+				case R_WRITE_OPEN:
+					if(daz_ignored(tid))
+						return 0;
+					daz_reset_scanned(tid.file);
+					event = DAZUKO_ON_OPEN;
+					daemon_allowed = 1;
+					break;
+				case R_DELETE:
+					if(daz_ignored(tid))
+						return 0;
+					daz_reset_scanned(tid.file);
+					event = DAZUKO_ON_UNLINK;
+					daemon_allowed = 1;
+					break;
+				default:
+					return 0;
+			}
+			break;
+		case T_DIR:
+			switch(request) {
+				case R_DELETE:
+					if(daz_ignored(tid))
+						return 0;
+					event = DAZUKO_ON_RMDIR;
+					daemon_allowed = 1;
+					break;
+				default:
+					return 0;
+			}
+		case T_PROCESS:
+			switch(request) {
+				case R_CLONE:
+					/* Get daz_scanner from first process */
+					if (rsbac_get_attr(SW_DAZ,
+							T_PROCESS,
+							tid,
+							A_daz_scanner,
+							&i_attr_val1,
+							FALSE))
+					{
+						rsbac_printk(KERN_WARNING
+							"rsbac_adf_set_attr_daz(): rsbac_get_attr() returned error!\n");
+						return -RSBAC_EREADFAILED;
+					}
+					/* Set daz_scanner for new process, if set for first */
+					if (   i_attr_val1.daz_scanner
+						&& (rsbac_set_attr(SW_DAZ,
+								T_PROCESS,
+								new_tid,
+								A_daz_scanner,
+								i_attr_val1)) )
+					{
+						rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_daz(): rsbac_set_attr() returned error!\n");
+						return -RSBAC_EWRITEFAILED;
+					}
+					return 0;
+				default:
+					return 0;
+			}
+		default:
+			return 0;
+	}
+
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	/* get daz_scanned for file */
+	if (rsbac_get_attr(SW_DAZ,
+				target,
+				tid,
+				A_daz_scanned,
+				&i_attr_val1,
+				FALSE))
+	{
+		rsbac_printk(KERN_WARNING
+				"rsbac_adf_set_attr_daz(): rsbac_get_attr() returned error!\n");
+		return -RSBAC_EREADFAILED;
+	}
+	if(i_attr_val1.daz_scanned == DAZ_clean)
+		return 0;
+#endif
+
+	xp_id.pid = current->pid;
+	xp_id.file = NULL;
+
+	check_error = dazuko_sys_check(event, daemon_allowed, &xp_id);
+
+	if (!check_error)
+	{
+		dazuko_bzero(&event_p, sizeof(event_p));
+		/*
+		   event_p.flags = flags;
+		   event_p.set_flags = 1;
+		   event_p.mode = mode;
+		   event_p.set_mode = 1;
+		   */
+		event_p.pid = current->pid;
+		event_p.set_pid = 1;
+		event_p.uid = __kuid_val(current_uid());
+		event_p.set_uid = 1;
+
+		dfs = rsbac_smalloc_clear_unlocked(dazuko_file_slab);
+		if (dfs != NULL)
+		{
+			dfs->extra_data = rsbac_smalloc_clear_unlocked(xp_file_slab);
+			if (dfs->extra_data != NULL)
+			{
+				dfs->extra_data->dentry = tid.file.dentry_p;
+
+				dazuko_sys_post(event, dfs, NULL, &event_p);
+				dazuko_file_struct_cleanup(&dfs);
+			}
+			else
+			{
+				rsbac_sfree(dazuko_file_slab, dfs);
+				dfs = NULL;
+			}
+		}
+	}
+
+	return 0;
+} /* end of rsbac_adf_set_attr_daz() */
diff --git a/rsbac/adf/daz/dazuko_call.h b/rsbac/adf/daz/dazuko_call.h
new file mode 100644
index 0000000..2ba8e1a
--- /dev/null
+++ b/rsbac/adf/daz/dazuko_call.h
@@ -0,0 +1,470 @@
+/* Dazuko. Check parameters of XP calls before making real calls.
+   Written by John Ogness <jogness@antivir.de>
+
+   Copyright (c) 2003, 2004 H+BEDV Datentechnik GmbH
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+   3. Neither the name of Dazuko nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DAZUKO_CALL_H
+#define DAZUKO_CALL_H
+
+#include "dazuko_platform.h"
+
+#include "dazuko_xp.h"
+
+#include <rsbac/helpers.h>
+#include <rsbac/debug.h>
+
+struct xp_mutex;
+struct xp_rwlock;
+struct xp_queue;
+struct xp_atomic;
+struct xp_file;
+struct dazuko_file_struct;
+struct xp_daemon_id;
+
+#define call_xp_sys_hook xp_sys_hook
+#define call_xp_sys_unhook xp_sys_unhook
+#define call_xp_print xp_print
+
+
+/* mutex */
+
+static inline int call_xp_init_mutex(struct xp_mutex *mutex)
+{
+	if (mutex == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: xp_init_mutex(NULL)\n");
+		return -1;
+	}
+
+	return xp_init_mutex(mutex);
+}
+
+static inline int call_xp_down(struct xp_mutex *mutex)
+{
+	if (mutex == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_down(NULL)\n");
+		return -1;
+	}
+
+	return xp_down(mutex);
+}
+
+static inline int call_xp_up(struct xp_mutex *mutex)
+{
+	if (mutex == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_up(NULL)\n");
+		return -1;
+	}
+
+	return xp_up(mutex);
+}
+
+static inline int call_xp_destroy_mutex(struct xp_mutex *mutex)
+{
+	if (mutex == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_destroy_mutex(NULL)\n");
+		return -1;
+	}
+
+	return xp_destroy_mutex(mutex);
+}
+
+
+/* read-write lock */
+
+static inline int call_xp_init_rwlock(struct xp_rwlock *rwlock)
+{
+	if (rwlock == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_init_rwlock(NULL)\n");
+		return -1;
+	}
+
+	return xp_init_rwlock(rwlock);
+}
+
+static inline int call_xp_write_lock(struct xp_rwlock *rwlock)
+{
+	if (rwlock == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_write_lock(NULL)\n");
+		return -1;
+	}
+
+	return xp_write_lock(rwlock);
+}
+
+static inline int call_xp_write_unlock(struct xp_rwlock *rwlock)
+{
+	if (rwlock == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_write_unlock(NULL)\n");
+		return -1;
+	}
+
+	return xp_write_unlock(rwlock);
+}
+
+static inline int call_xp_read_lock(struct xp_rwlock *rlock)
+{
+	if (rlock == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_read_lock(NULL)\n");
+		return -1;
+	}
+
+	return xp_read_lock(rlock);
+}
+
+static inline int call_xp_read_unlock(struct xp_rwlock *rlock)
+{
+	if (rlock == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_read_unlock(NULL)\n");
+		return -1;
+	}
+
+	return xp_read_unlock(rlock);
+}
+
+static inline int call_xp_destroy_rwlock(struct xp_rwlock *rwlock)
+{
+	if (rwlock == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_destroy_rwlock(NULL)\n");
+		return -1;
+	}
+
+	return xp_destroy_rwlock(rwlock);
+}
+
+
+/* wait-notify queue */
+
+static inline int call_xp_init_queue(struct xp_queue *queue)
+{
+	if (queue == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_init_queue(NULL)\n");
+		return -1;
+	}
+
+	return xp_init_queue(queue);
+}
+
+static inline int call_xp_wait_until_condition(struct xp_queue *queue, int (*cfunction)(void *), void *cparam, int allow_interrupt)
+{
+	if (queue == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_wait_until_condition(queue=NULL)\n");
+		return -1;
+	}
+
+	if (cfunction == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: warning: xp_wait_until_condition(cfunction=NULL)\n");
+		return -1;
+	}
+
+	return xp_wait_until_condition(queue, cfunction, cparam, allow_interrupt);
+}
+
+static inline int call_xp_notify(struct xp_queue *queue)
+{
+	if (queue == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_notify(NULL)\n");
+		return -1;
+	}
+
+	return xp_notify(queue);
+}
+
+static inline int call_xp_destroy_queue(struct xp_queue *queue)
+{
+	if (queue == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_destroy_queue(NULL)\n");
+		return -1;
+	}
+
+	return xp_destroy_queue(queue);
+}
+
+
+/* memory */
+
+static inline int call_xp_copyin(const void *user_src, void *kernel_dest, size_t size)
+{
+	if (user_src == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copyin(user_src=NULL)\n");
+		return -1;
+	}
+
+	if (kernel_dest == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copyin(kernel_dest=NULL)\n");
+		return -1;
+	}
+
+	if (size < 1)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copyin(size=%d)\n", size);
+		return 0;
+	}
+
+	return xp_copyin(user_src, kernel_dest, size);
+}
+
+static inline int call_xp_copyout(const void *kernel_src, void *user_dest, size_t size)
+{
+	if (kernel_src == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copyout(kernel_src=NULL)\n");
+		return -1;
+	}
+
+	if (user_dest == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copyout(user_dest=NULL)\n");
+		return -1;
+	}
+
+	if (size < 1)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copyout(size=%d)\n", size);
+		return 0;
+	}
+
+	return xp_copyout(kernel_src, user_dest, size);
+}
+
+static inline int call_xp_verify_user_writable(const void *user_ptr, size_t size)
+{
+	if (user_ptr == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_verify_user_writable(user_ptr=NULL)\n");
+		return -1;
+	}
+
+	if (size < 1)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_verify_user_writable(size=%d)\n", size);
+		return -1;
+	}
+
+	return xp_verify_user_writable(user_ptr, size);
+}
+
+static inline int call_xp_verify_user_readable(const void *user_ptr, size_t size)
+{
+	if (user_ptr == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_verify_user_readable(user_ptr=NULL)\n");
+		return -1;
+	}
+
+	if (size < 1)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_verify_user_readable(size=%d)\n", size);
+		return -1;
+	}
+
+	return xp_verify_user_readable(user_ptr, size);
+}
+
+
+/* path attribute */
+
+static inline int call_xp_is_absolute_path(const char *path)
+{
+	if (path == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_is_absolute_path(NULL)\n");
+		return 0;
+	}
+
+	return xp_is_absolute_path(path);
+}
+
+
+/* atomic */
+
+static inline int call_xp_atomic_set(struct xp_atomic *atomic, int value)
+{
+	if (atomic == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_atomic_set(atomic=NULL)\n");
+		return -1;
+	}
+
+	return xp_atomic_set(atomic, value);
+}
+
+static inline int call_xp_atomic_inc(struct xp_atomic *atomic)
+{
+	if (atomic == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_atomic_inc(NULL)\n");
+		return -1;
+	}
+
+	return xp_atomic_inc(atomic);
+}
+
+static inline int call_xp_atomic_dec(struct xp_atomic *atomic)
+{
+	if (atomic == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_atomic_dec(NULL)\n");
+		return -1;
+	}
+
+	return xp_atomic_dec(atomic);
+}
+
+static inline int call_xp_atomic_read(struct xp_atomic *atomic)
+{
+	if (atomic == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_atomic_read(NULL)\n");
+		return -1;
+	}
+
+	return xp_atomic_read(atomic);
+}
+
+
+/* file descriptor */
+
+static inline int call_xp_copy_file(struct xp_file *dest, struct xp_file *src)
+{
+	if (dest == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copy_file(dest=NULL)\n");
+		return -1;
+	}
+
+	if (src == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_copy_file(src=NULL)\n");
+		return -1;
+	}
+
+	return xp_copy_file(dest, src);
+}
+
+static inline int call_xp_compare_file(struct xp_file *file1, struct xp_file *file2)
+{
+	if (file1 == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_compare_file(file1=NULL)\n");
+		return -1;
+	}
+
+	if (file2 == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_compare_file(file2=NULL)\n");
+		return -1;
+	}
+
+	return xp_compare_file(file1, file2);
+}
+
+
+/* file structure */
+
+static inline int call_xp_fill_file_struct(struct dazuko_file_struct *dfs)
+{
+	if (dfs == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_fill_file_struct(NULL)\n");
+		return -1;
+	}
+
+	return xp_fill_file_struct(dfs);
+}
+
+
+/* daemon id */
+
+static inline int call_xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2)
+{
+	if (id1 == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_id_compare(id1=NULL)\n");
+		return -1;
+	}
+
+	if (id2 == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_id_compare(id2=NULL)\n");
+		return -1;
+	}
+
+	return xp_id_compare(id1, id2);
+}
+
+static inline int call_xp_id_free(struct xp_daemon_id *id)
+{
+	if (id == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_id_free(NULL)\n");
+		return 0;
+	}
+
+	return xp_id_free(id);
+}
+
+static inline struct xp_daemon_id* call_xp_id_copy(struct xp_daemon_id *id)
+{
+	struct xp_daemon_id *ptr;
+
+	if (id == NULL)
+	{
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_id_copy(NULL)\n");
+		return NULL;
+	}
+
+	ptr = xp_id_copy(id);
+
+	if (ptr == NULL)
+		rsbac_printk(KERN_WARNING, "dazuko: warning: xp_id_copy() -> NULL\n");
+
+	return ptr;
+}
+
+#endif
diff --git a/rsbac/adf/daz/dazuko_linux26.h b/rsbac/adf/daz/dazuko_linux26.h
new file mode 100644
index 0000000..fecce8d
--- /dev/null
+++ b/rsbac/adf/daz/dazuko_linux26.h
@@ -0,0 +1,82 @@
+/* Dazuko Linux. Allow Linux 2.6 file access control for 3rd-party applications.
+   Copyright (c) 2003, 2004 H+BEDV Datentechnik GmbH
+   Written by John Ogness <jogness@antivir.de>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef DAZUKO_LINUX26_H
+#define DAZUKO_LINUX26_H
+
+#include <linux/module.h>
+#include <linux/semaphore.h>
+
+#define	DEVICE_NAME		"dazuko"
+
+#define XP_ERROR_PERMISSION	-EPERM;
+#define XP_ERROR_INTERRUPT	-EINTR;
+#define XP_ERROR_BUSY		-EBUSY;
+#define XP_ERROR_FAULT		-EFAULT;
+#define XP_ERROR_INVALID	-EINVAL;
+#define XP_ERROR_NODEVICE	-ENODEV;
+
+
+struct xp_daemon_id
+{
+	int		pid;
+	struct file	*file;
+};
+
+struct xp_file
+{
+	char file;
+};
+
+struct xp_mutex
+{
+	struct semaphore mutex;
+};
+
+struct xp_atomic
+{
+	atomic_t atomic;
+};
+
+struct xp_file_struct
+{
+	int full_filename_length;
+	char *full_filename;
+	int free_full_filename;
+	struct dentry *dentry;
+	int dput_dentry;
+	char *buffer;
+	int free_page_buffer;
+	struct nameidata *nd;
+	struct vfsmount *vfsmount;
+	int mntput_vfsmount;
+	struct inode *inode;
+};
+
+struct xp_queue
+{
+	wait_queue_head_t queue;
+};
+
+struct xp_rwlock
+{
+	rwlock_t rwlock;
+};
+
+#endif
diff --git a/rsbac/adf/daz/dazuko_platform.h b/rsbac/adf/daz/dazuko_platform.h
new file mode 100644
index 0000000..b8ac821
--- /dev/null
+++ b/rsbac/adf/daz/dazuko_platform.h
@@ -0,0 +1,2 @@
+#include <linux/version.h>
+#include "dazuko_linux26.h"
diff --git a/rsbac/adf/daz/dazuko_rsbac.h b/rsbac/adf/daz/dazuko_rsbac.h
new file mode 100644
index 0000000..3519be9
--- /dev/null
+++ b/rsbac/adf/daz/dazuko_rsbac.h
@@ -0,0 +1,100 @@
+/* Dazuko RSBAC. Allow RSBAC Linux file access control for 3rd-party applications.
+   Copyright (c) 2004 H+BEDV Datentechnik GmbH
+   Written by John Ogness <jogness@antivir.de>
+
+   Copyright (c) 2004-2010 Amon Ott <ao@rsbac.org>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef DAZUKO_RSBAC_H
+#define DAZUKO_RSBAC_H
+
+#ifdef CONFIG_MODVERSIONS
+#define MODVERSIONS
+#include <config/modversions.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))
+#endif
+
+#include <linux/slab.h>
+#include <asm/atomic.h>
+
+#ifdef CONFIG_SMP
+#ifndef __SMP__
+#define __SMP__
+#endif
+#endif
+
+#include <linux/semaphore.h>
+
+
+#define	DEVICE_NAME		"dazuko"
+
+#define XP_ERROR_PERMISSION	-EPERM;
+#define XP_ERROR_INTERRUPT	-EINTR;
+#define XP_ERROR_BUSY		-EBUSY;
+#define XP_ERROR_FAULT		-EFAULT;
+#define XP_ERROR_INVALID	-EINVAL;
+
+
+struct xp_daemon_id
+{
+	int		pid;
+	struct file	*file;
+};
+
+struct xp_file
+{
+	char	c;
+};
+
+struct xp_mutex
+{
+	struct semaphore	mutex;
+};
+
+struct xp_atomic
+{
+	atomic_t	atomic;
+};
+
+struct xp_file_struct
+{
+	int			full_filename_length;	/* length of filename */
+	char			*full_filename;		/* kernelspace filename with full path */
+	struct dentry		*dentry;		/* used to get inode */
+};
+
+struct xp_queue
+{
+	wait_queue_head_t queue;
+};
+
+struct xp_rwlock
+{
+	rwlock_t	rwlock;
+};
+
+#endif
diff --git a/rsbac/adf/daz/dazuko_xp.c b/rsbac/adf/daz/dazuko_xp.c
new file mode 100644
index 0000000..cc9265b
--- /dev/null
+++ b/rsbac/adf/daz/dazuko_xp.c
@@ -0,0 +1,2903 @@
+/* DazukoXP. Allow cross platform file access control for 3rd-party applications.
+   Written by John Ogness <jogness@antivir.de>
+
+   Copyright (c) 2002, 2003, 2004 H+BEDV Datentechnik GmbH
+   Copyright (c) 2004-2011 Amon Ott <ao@rsbac.org>
+   
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+   3. Neither the name of Dazuko nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <rsbac/types.h>
+#include <rsbac/debug.h>
+
+#include "dazuko_platform.h"
+
+#include "dazuko_xp.h"
+#include "dazukoio.h"
+
+#include "dazuko_call.h"
+
+#define NUM_SLOT_LISTS	5
+#define NUM_SLOTS	25
+
+#define	SCAN_ON_OPEN		(access_mask & DAZUKO_ON_OPEN)
+#define	SCAN_ON_CLOSE		(access_mask & DAZUKO_ON_CLOSE)
+#define	SCAN_ON_EXEC		(access_mask & DAZUKO_ON_EXEC)
+#define	SCAN_ON_CLOSE_MODIFIED	(access_mask & DAZUKO_ON_CLOSE_MODIFIED)
+
+struct dazuko_path
+{
+	/* A node in a linked list of paths. Used
+	 * for the include and exclude lists. */
+
+	struct dazuko_path	*next;
+	int		len;
+	char		path[1];	/* this MUST be at the end of the struct */
+};
+
+struct hash
+{
+	/* A node in a linked list of filenames.
+	 * Used for the list of files to be
+	 * scanned on close. */
+
+	struct hash	*next;
+	struct xp_file	file;
+	int		dirty;
+	int		namelen;
+	char		name[1];	/* this MUST be at the end of the struct */
+};
+
+struct daemon_id
+{
+	int			unique;
+	struct xp_daemon_id	*xp_id;
+};
+
+struct slot
+{
+	/* A representation of a daemon. It holds
+	 * all information about the daemon, the
+	 * file that is scanned, and the state of
+	 * the scanning process. */
+
+	int			id;		
+	struct daemon_id	did;		/* identifier for our daemon */
+	int			write_mode;
+	int			state;
+	int			response;
+	int			event;
+	int			filenamelength;	/* not including terminator */
+	char			*filename;
+	struct event_properties	event_p;
+	struct file_properties	file_p;
+	struct xp_mutex		mutex;
+};
+
+struct slot_list
+{
+	struct xp_atomic	use_count;
+	struct slot		slots[NUM_SLOTS];
+	char			reg_name[1];	/* this MUST be at the end of the struct */
+};
+
+struct slot_list_container
+{
+	struct slot_list	*slot_list;
+	struct xp_mutex		mutex;
+};
+
+struct one_slot_state_not_condition_param
+{
+	struct slot	*slot;
+	int		state;
+};
+
+struct two_slot_state_not_condition_param
+{
+	struct slot	*slot1;
+	int		state1;
+	struct slot	*slot2;
+	int		state2;
+};
+
+struct get_ready_slot_condition_param
+{
+	struct slot		*slot;
+	struct slot_list	*slotlist;
+};
+
+static int				unique_count = 1;
+static char				access_mask = 7;
+static struct slot_list_container	slot_lists[NUM_SLOT_LISTS];
+static struct dazuko_path			*incl_paths = NULL;
+static struct dazuko_path			*excl_paths = NULL;
+static struct hash			*hash = NULL;
+static struct xp_rwlock			lock_hash;
+static struct xp_rwlock			lock_lists;
+static struct xp_atomic			active;
+static struct xp_mutex			mutex_unique_count;
+
+static struct xp_queue			wait_kernel_waiting_for_free_slot;
+static struct xp_queue			wait_daemon_waiting_for_work;
+static struct xp_queue			wait_kernel_waiting_while_daemon_works;
+static struct xp_queue			wait_daemon_waiting_for_free;
+
+#ifdef CONFIG_RSBAC_DAZ_SELECT
+static struct kmem_cache * dazuko_file_listnode_slab = NULL;
+#endif
+static struct kmem_cache * dazuko_request_slab = NULL;
+static struct kmem_cache * access_compat12_slab = NULL;
+
+int dazuko_vsnprintf(char *str, size_t size, const char *format, va_list ap)
+{
+	char		*target;
+	const char	*end;
+	int		overflow = 0;
+	char		number_buffer[32]; /* 32 should be enough to hold any number, right? */
+	const char	*s;
+
+	if (str == NULL || size < 1 || format == NULL)
+		return -1;
+
+	target = str;
+	end = (target + size) - 1;
+
+#define DAZUKO_VSNPRINTF_PRINTSTRING \
+	for ( ; *s ; s++) \
+	{ \
+		if (target == end) \
+		{ \
+			overflow = 1; \
+			goto dazuko_vsnprintf_out; \
+		} \
+		*target = *s; \
+		target++; \
+	}
+
+	for ( ; *format ; format++)
+	{
+		if (target == end)
+		{
+			overflow = 1;
+			goto dazuko_vsnprintf_out;
+		}
+
+		if (*format == '%')
+		{
+			format++;
+
+			switch (*format)
+			{
+				case 's': /* %s */
+					s = va_arg(ap, char *);
+					if (s == NULL)
+						s = "(null)";
+					DAZUKO_VSNPRINTF_PRINTSTRING
+					break;
+
+				case 'd': /* %d */
+					sprintf(number_buffer, "%d", va_arg(ap, int));
+					s = number_buffer;
+					DAZUKO_VSNPRINTF_PRINTSTRING
+					break;
+
+				case 'c': /* %c */
+					*target = va_arg(ap, int);
+					target++;
+					break;
+
+				case 'l': /* %lu */
+					format++;
+					if (*format != 'u')
+					{
+						/* print error message */
+						goto dazuko_vsnprintf_out;
+					}
+					sprintf(number_buffer, "%lu", va_arg(ap, unsigned long));
+					s = number_buffer;
+					DAZUKO_VSNPRINTF_PRINTSTRING
+					break;
+
+				case '0': /* %02x */
+					format++;
+					if (*format != '2')
+					{
+						/* print error message */
+						goto dazuko_vsnprintf_out;
+					}
+					format++;
+					if (*format != 'x')
+					{
+						/* print error message */
+						goto dazuko_vsnprintf_out;
+					}
+					sprintf(number_buffer, "%02x", va_arg(ap, int));
+					s = number_buffer;
+					DAZUKO_VSNPRINTF_PRINTSTRING
+					break;
+
+				default:
+					/* print error message */
+					goto dazuko_vsnprintf_out;
+			}
+		}
+		else
+		{
+			*target = *format;
+			target++;
+		}
+	}
+
+dazuko_vsnprintf_out:
+
+	*target = 0;
+
+	/* We are returning what we've written. If there was an
+	 * overflow, the returned value will match "size" rather
+	 * than being less than "size"
+	 */
+
+	return ((target - str) + overflow);
+}
+
+int dazuko_snprintf(char *str, size_t size, const char *format, ...)
+{
+	va_list	ap;
+	int	ret;
+
+	va_start(ap, format);
+	ret = dazuko_vsnprintf(str, size, format, ap);
+	va_end(ap);
+
+	return ret;
+}
+
+inline void dazuko_bzero(void *p, int len)
+{
+	/* "zero out" len bytes starting with p */
+
+	char	*ptr = (char *)p;
+
+	while (len--)
+		*ptr++ = 0;
+}
+
+static inline int dazuko_get_new_unique(void)
+{
+	int	unique;
+
+/* DOWN */
+	call_xp_down(&mutex_unique_count);
+
+	unique = unique_count;
+	unique_count++;
+
+	call_xp_up(&mutex_unique_count);
+/* UP */
+
+	return unique;
+}
+
+static inline int dazuko_slot_state(struct slot *s)
+{
+	int state;
+
+/* DOWN */
+	if (call_xp_down(&(s->mutex)) != 0)
+		return XP_ERROR_INTERRUPT;
+
+	state = s->state;
+
+	call_xp_up(&(s->mutex));
+/* UP */
+
+	return state;
+}
+
+static int one_slot_state_not_condition(void *param)
+{
+	return (dazuko_slot_state(((struct one_slot_state_not_condition_param *)param)->slot)
+		!= ((struct one_slot_state_not_condition_param *)param)->state);
+}
+
+static int two_slot_state_not_condition(void *param)
+{
+	return (dazuko_slot_state(((struct two_slot_state_not_condition_param *)param)->slot1)
+		!= ((struct two_slot_state_not_condition_param *)param)->state1
+		&& dazuko_slot_state(((struct two_slot_state_not_condition_param *)param)->slot2)
+		!= ((struct two_slot_state_not_condition_param *)param)->state2);
+}
+
+static inline int __dazuko_change_slot_state(struct slot *s, int from_state, int to_state)
+{
+	/* Make a predicted state transition. We fail if it
+	 * is an unpredicted change. We can ALWAYS go to the
+	 * to_state if it is the same as from_state. Not SMP safe! */
+
+	if (to_state != from_state)
+	{
+		/* make sure this is a predicted transition and there
+		 * is a daemon on this slot (unique != 0)*/
+		if (s->state != from_state || s->did.unique == 0)
+			return 0;
+	}
+
+	s->state = to_state;
+
+	/* handle appropriate wake_up's for basic
+	 * state changes */
+
+	if (to_state == DAZUKO_READY)
+	{
+		call_xp_notify(&wait_kernel_waiting_for_free_slot);
+	}
+	else if (to_state == DAZUKO_FREE)
+	{
+		call_xp_notify(&wait_kernel_waiting_while_daemon_works);
+		call_xp_notify(&wait_daemon_waiting_for_free);
+	}
+
+	return 1;
+}
+
+static int dazuko_change_slot_state(struct slot *s, int from_state, int to_state, int release)
+{
+	/* SMP safe version of __dazuko_change_slot_state().
+	 * This should only be used if we haven't
+	 * already aquired slot.mutex. Use this function
+	 * with CAUTION, since the mutex may or may not
+	 * be released depending on the return value AND
+	 * on the value of the "release" argument. */
+
+	int	success;
+
+	/* if we are interrupted, report the state as unpredicted */
+/* DOWN */
+	if (call_xp_down(&(s->mutex)) != 0)
+		return 0;
+
+	success = __dazuko_change_slot_state(s, from_state, to_state);
+
+	/* the mutex is released if the state change was
+	 * unpredicted or if the called wants it released */
+	if (!success || release)
+		call_xp_up(&(s->mutex));
+/* UP */
+	return success;
+}
+
+static struct slot * _dazuko_find_slot(struct daemon_id *did, int release, struct slot_list *sl)
+{
+	/* Find the first slot with the same given
+	 * pid number. SMP safe. Use this function
+	 * with CAUTION, since the mutex may or may not
+	 * be released depending on the return value AND
+	 * on the value of the "release" argument. */
+
+	int	i;
+	struct slot	*s = NULL;
+
+	if (sl == NULL)
+	{
+		rsbac_printk(KERN_WARNING "dazuko: invalid slot_list given (bug!)\n");
+		return NULL;
+	}
+
+	for (i=0 ; i<NUM_SLOTS ; i++)
+	{
+		s = &(sl->slots[i]);
+/* DOWN */
+		/* if we are interrupted, we say that no
+ 		 * slot was found */
+		if (call_xp_down(&(s->mutex)) != 0)
+			return NULL;
+
+		if (did == NULL)
+		{
+			/* we are looking for an empty slot */
+			if (s->did.unique == 0 && s->did.xp_id == NULL)
+			{
+				/* we release the mutex only if the
+	 			* called wanted us to */
+				if (release)
+					call_xp_up(&(s->mutex));
+/* UP */
+				return s;
+			}
+		}
+		else if (s->did.unique == 0 && s->did.xp_id == NULL)
+		{
+			/* this slot is emtpy, so it can't match */
+
+			/* do nothing */
+		}
+		/* xp_id's must match! */
+		else if (call_xp_id_compare(s->did.xp_id, did->xp_id) == 0)
+		{
+			/* unique's must also match (unless unique is negative,
+			 * in which case we will trust xp_id) */
+			if (did->unique < 0 || (s->did.unique == did->unique))
+			{
+				/* we release the mutex only if the
+				 * called wanted us to */
+				if (release)
+					call_xp_up(&(s->mutex));
+/* UP */
+				return s;
+			}
+		}
+
+		call_xp_up(&(s->mutex));
+/* UP */
+	}
+
+	return NULL;
+}
+
+static struct slot * dazuko_find_slot_and_slotlist(struct daemon_id *did, int release, struct slot_list *slist, struct slot_list **sl_result)
+{
+	struct slot		*s;
+	int		i;
+	struct slot_list	*sl;
+
+	if (slist == NULL)
+	{
+		for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+		{
+/* DOWN */
+			/* if we are interrupted, we say that no
+ 			* slot was found */
+			if (call_xp_down(&(slot_lists[i].mutex)) != 0)
+				return NULL;
+
+			sl = slot_lists[i].slot_list;
+
+			call_xp_up(&(slot_lists[i].mutex));
+/* UP */
+
+			if (sl != NULL)
+			{
+				s = _dazuko_find_slot(did, release, sl);
+				if (s != NULL)
+				{
+					/* set the current slot_list */
+					if (sl_result != NULL)
+						*sl_result = sl;
+
+					return s;
+				}
+			}
+		}
+	}
+	else
+	{
+		return _dazuko_find_slot(did, release, slist);
+	}
+
+	return NULL;
+}
+
+static inline struct slot * dazuko_find_slot(struct daemon_id *did, int release, struct slot_list *slist)
+{
+	return dazuko_find_slot_and_slotlist(did, release, slist, NULL);
+}
+
+static int dazuko_insert_path_fs(struct dazuko_path **list, char *fs_path, int fs_len)
+{
+	/* Create a new struct dazuko_path structure and insert it
+	 * into the linked list given (list argument).
+	 * The fs_len argument is to help speed things
+	 * up so we don't have to calculate the length
+	 * of fs_path. */
+
+	struct dazuko_path	*newitem;
+	struct dazuko_path	*tmp;
+
+	if (fs_path == NULL || fs_len < 1)
+		return XP_ERROR_INVALID;
+
+	/* we want only absolute paths */
+	if (!call_xp_is_absolute_path(fs_path))
+		return XP_ERROR_INVALID;
+
+	/* create a new struct dazuko_path structure making room for path also */
+	newitem = rsbac_kmalloc(sizeof(struct dazuko_path) + fs_len + 1);
+	if (newitem == NULL)
+		return XP_ERROR_FAULT;
+
+	/* fs_path is already in kernelspace */
+	memcpy(newitem->path, fs_path, fs_len);
+
+	newitem->path[fs_len] = 0;
+
+	while (newitem->path[fs_len-1] == 0)
+	{
+		fs_len--;
+		if (fs_len == 0)
+			break;
+	}
+
+	if (fs_len < 1)
+	{
+		rsbac_kfree(newitem);
+		return XP_ERROR_INVALID;
+	}
+
+	newitem->len = fs_len;
+
+	/* check if this path already exists in the list */
+	for (tmp=*list ; tmp ; tmp=tmp->next)
+	{
+		if (newitem->len == tmp->len)
+		{
+			if (memcmp(newitem->path, tmp->path, tmp->len) == 0)
+			{
+				/* we already have this path */
+
+				rsbac_kfree(newitem);
+
+				return 0;
+			}
+		}
+	}
+
+	DPRINT(("dazuko: adding %s %s\n", (list == &incl_paths) ? "incl" : "excl", newitem->path));
+
+	/* add struct dazuko_path to head of linked list */
+/* LOCK */
+	call_xp_write_lock(&lock_lists);
+	newitem->next = *list;
+	*list = newitem;
+	call_xp_write_unlock(&lock_lists);
+/* UNLOCK */
+
+	return 0;
+}
+
+static void dazuko_remove_all_hash(void)
+{
+	/* Empty the hash linked list. */
+
+	struct hash	*tmp;
+
+/* LOCK */
+	call_xp_write_lock(&lock_hash);
+	while (hash)
+	{
+		tmp = hash;
+		hash = hash->next;
+
+		DPRINT(("dazuko: removing hash %s\n", tmp->name));
+
+		rsbac_kfree(tmp);
+	}
+	call_xp_write_unlock(&lock_hash);
+/* UNLOCK */
+}
+
+static void dazuko_remove_all_paths(void)
+{
+	/* Empty both include and exclude struct dazuko_path
+	 * linked lists. */
+
+	struct dazuko_path	*tmp;
+
+/* LOCK */
+	call_xp_write_lock(&lock_lists);
+
+	/* empty include paths list */
+	while (incl_paths)
+	{
+		tmp = incl_paths;
+		incl_paths = incl_paths->next;
+
+		DPRINT(("dazuko: removing incl %s\n", tmp->path));
+
+		rsbac_kfree(tmp);
+	}
+
+	/* empty exclude paths list */
+	while (excl_paths)
+	{
+		tmp = excl_paths;
+		excl_paths = excl_paths->next;
+
+		DPRINT(("dazuko: removing excl %s\n", tmp->path));
+
+		rsbac_kfree(tmp);
+	}
+
+	call_xp_write_unlock(&lock_lists);
+/* UNLOCK */
+}
+
+static int _dazuko_unregister_daemon(struct daemon_id *did)
+{
+	/* We unregister the daemon by finding the
+	 * slot with the same slot->pid as the the
+	 * current process id, the daemon. */
+
+	struct slot		*s;
+	struct slot_list	*sl;
+
+	DPRINT(("dazuko: dazuko_unregister_daemon() [%d]\n", did->unique));
+
+	/* find our slot and hold the mutex
+	 * if we find it */
+/* DOWN? */
+	s = dazuko_find_slot_and_slotlist(did, 0, NULL, &sl);
+
+	if (s == NULL)
+	{
+		/* this daemon was not registered */
+		return 0;
+	}
+
+/* DOWN */
+
+	/* clearing the unique and pid makes the slot available */
+	s->did.unique = 0;
+	call_xp_id_free(s->did.xp_id);
+	s->did.xp_id = NULL;
+
+	/* reset slot state */
+	__dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE);
+
+	call_xp_atomic_dec(&(sl->use_count));
+
+	call_xp_up(&(s->mutex));
+/* UP */
+
+	/* active should always be positive here, but
+	 * let's check just to be sure. ;) */
+	if (call_xp_atomic_read(&active) > 0)
+	{
+		/* active and the kernel usage counter
+		 * should always reflect how many daemons
+		 * are active */
+
+		call_xp_atomic_dec(&active);
+	}
+	else
+	{
+		rsbac_printk(KERN_WARNING "dazuko: active count error (possible bug)\n");
+	}
+
+	/* Wake up any kernel processes that are
+	 * waiting for an available slot. Remove
+	 * all the include and exclude paths
+	 * if there are no more daemons */
+
+	if (call_xp_atomic_read(&active) == 0)
+	{
+		/* clear out include and exclude paths */
+		/* are we sure we want to do this? */
+		dazuko_remove_all_paths();
+
+		/* clear out hash nodes */
+		dazuko_remove_all_hash();
+	}
+
+	call_xp_notify(&wait_kernel_waiting_for_free_slot);
+	call_xp_notify(&wait_kernel_waiting_while_daemon_works);
+
+	return 0;
+}
+
+int dazuko_unregister_daemon(struct xp_daemon_id *xp_id)
+{
+	struct daemon_id	did;
+	int			ret;
+
+	if (xp_id == NULL)
+		return 0;
+
+	did.unique = -1;
+	did.xp_id = call_xp_id_copy(xp_id);
+
+	ret = _dazuko_unregister_daemon(&did);
+
+	call_xp_id_free(did.xp_id);
+
+	return ret;
+}
+
+static inline int dazuko_state_error(struct slot *s, int current_state)
+{
+	if (dazuko_change_slot_state(s, current_state, DAZUKO_BROKEN, 1))
+	{
+		call_xp_notify(&wait_kernel_waiting_for_free_slot);
+		call_xp_notify(&wait_kernel_waiting_while_daemon_works);
+	}
+
+	return 0;
+}
+
+static int dazuko_register_daemon(struct daemon_id *did, const char *reg_name, int string_length, int write_mode)
+{
+	const char	*p1;
+	char		*p2;
+	struct slot		*s;
+	struct slot_list	*sl;
+	int		i;
+
+	rsbac_pr_debug(adf_daz, "Registering daemon %s [%d]\n", reg_name, did->unique);
+
+	if (did == NULL || reg_name == NULL)
+		return XP_ERROR_PERMISSION;
+
+	s = dazuko_find_slot(did, 1, NULL);
+
+	if (s != NULL)
+	{
+		/* We are already registered! */
+
+		rsbac_printk(KERN_INFO "dazuko: daemon %d already assigned to slot[%d]\n", did->unique, s->id);
+
+		return XP_ERROR_PERMISSION;
+	}
+
+	/* Find the slot_list with the matching name. */
+
+	for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+	{
+/* DOWN */
+		/* if we are interrupted, we say that it
+ 		* was interrupted */
+		if (call_xp_down(&(slot_lists[i].mutex)) != 0)
+			return XP_ERROR_INTERRUPT;
+
+		sl = slot_lists[i].slot_list;
+
+		call_xp_up(&(slot_lists[i].mutex));
+/* UP */
+
+		if (sl != NULL)
+		{
+			p1 = reg_name;
+			p2 = sl->reg_name;
+
+			while (*p1 == *p2)
+			{
+				if (*p1 == 0)
+					break;
+
+				p1++;
+				p2++;
+			}
+
+			if (*p1 == *p2)
+				break;
+		}
+	}
+
+	if (i == NUM_SLOT_LISTS)
+	{
+		/* There is no slot_list with this name. We
+		 * need to make one. */
+
+		sl = rsbac_kmalloc_clear_unlocked(sizeof(struct slot_list) + string_length + 1);
+		if (sl == NULL)
+			return XP_ERROR_FAULT;
+
+		call_xp_atomic_set(&(sl->use_count), 0);
+
+		p1 = reg_name;
+		p2 = sl->reg_name;
+
+		while (*p1)
+		{
+			*p2 = *p1;
+
+			p1++;
+			p2++;
+		}
+		*p2 = 0;
+
+		/* give each slot a unique id */
+		for (i=0 ; i<NUM_SLOTS ; i++)
+		{
+			sl->slots[i].id = i;
+			call_xp_init_mutex(&(sl->slots[i].mutex));
+		}
+
+		/* we need to find an empty slot */
+		for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+		{
+/* DOWN */
+			/* if we are interrupted, we need to cleanup
+ 			* and return error */
+			if (call_xp_down(&(slot_lists[i].mutex)) != 0)
+			{
+				rsbac_kfree(sl);
+				return XP_ERROR_INTERRUPT;
+			}
+
+			if (slot_lists[i].slot_list == NULL)
+			{
+				slot_lists[i].slot_list = sl;
+
+				call_xp_up(&(slot_lists[i].mutex));
+/* UP */
+				break;
+			}
+
+			call_xp_up(&(slot_lists[i].mutex));
+/* UP */
+		}
+
+		if (i == NUM_SLOT_LISTS)
+		{
+			/* no empty slot :( */
+			rsbac_kfree(sl);
+			return XP_ERROR_BUSY;
+		}
+	}
+
+	/* find an available slot and hold the mutex
+	 * if we find one */
+/* DOWN? */
+	s = dazuko_find_slot(NULL, 0, sl);
+
+	if (s == NULL)
+		return XP_ERROR_BUSY;
+
+/* DOWN */
+
+	/* We have found a slot, so increment the active
+	 * variable and the kernel module use counter.
+	 * The module counter will always reflect the
+	 * number of daemons. */
+
+	call_xp_atomic_inc(&active);
+
+	/* get new unique id for this process */
+	did->unique = dazuko_get_new_unique();
+
+	s->did.unique = did->unique;
+	s->did.xp_id = call_xp_id_copy(did->xp_id);
+	s->write_mode = write_mode;
+
+	call_xp_atomic_inc(&(sl->use_count));
+
+	/* the daemon is registered, but not yet
+	 * ready to receive files */
+	__dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE);
+	rsbac_pr_debug(adf_daz, "slot[%d] assigned to daemon %s [%d]", s->id, reg_name, did->unique);
+	call_xp_up(&(s->mutex));
+/* UP */
+
+	return 0;
+}
+
+static struct slot* dazuko_get_an_access(struct daemon_id *did)
+{
+	/* The daemon is requesting a filename of a file
+	 * to scan. This code will wait until a filename
+	 * is available, or until we should be killed.
+	 * (killing is done if any errors occur as well
+	 * as when the user kills us) */
+
+	/* If a slot is returned, it will be already locked! */
+
+	int					i;
+	struct slot					*s;
+	struct one_slot_state_not_condition_param	cond_p;
+
+tryagain:
+	/* find our slot */
+	s = dazuko_find_slot(did, 1, NULL);
+
+	if (s == NULL)
+	{
+		i = dazuko_register_daemon(did, "_COMPAT", 7, 1);
+		if (i != 0)
+		{
+			rsbac_printk(KERN_INFO "dazuko: unregistered daemon %d attempted to get access\n", did->unique);
+			return NULL;
+		}
+
+		s = dazuko_find_slot(did, 1, NULL);
+		if (s == NULL)
+		{
+			rsbac_printk(KERN_INFO "dazuko: unregistered daemon %d attempted to get access\n", did->unique);
+			return NULL;
+		}
+
+		rsbac_printk(KERN_INFO "dazuko: warning: daemon %d is using a deprecated protocol\n", did->unique);
+	}
+
+	/* the daemon is now ready to receive a file */
+	dazuko_change_slot_state(s, DAZUKO_READY, DAZUKO_READY, 1);
+
+	cond_p.slot = s;
+	cond_p.state = DAZUKO_READY;
+	if (call_xp_wait_until_condition(&wait_daemon_waiting_for_work, one_slot_state_not_condition, &cond_p, 1) != 0)
+	{
+		/* The user has issued an interrupt.
+		 * Return an error. The daemon should
+		 * unregister itself. */
+
+		DPRINT(("dazuko: daemon %d killed while waiting for work\n", did->unique));
+
+		if (dazuko_change_slot_state(s, DAZUKO_READY, DAZUKO_BROKEN, 1) || dazuko_change_slot_state(s, DAZUKO_WAITING, DAZUKO_BROKEN, 1))
+		{
+			call_xp_notify(&wait_kernel_waiting_for_free_slot);
+			call_xp_notify(&wait_kernel_waiting_while_daemon_works);
+		}
+
+		return NULL;
+	}
+
+	/* slot SHOULD now be in DAZUKO_WAITING state */
+
+	/* we will be working with the slot, so
+	 * we need to lock it */
+
+/* DOWN? */
+	if (!dazuko_change_slot_state(s, DAZUKO_WAITING, DAZUKO_WORKING, 0))
+	{
+		/* State transition error. Try again., */
+
+		goto tryagain;
+	}
+
+/* DOWN */
+
+	/* Slot IS in DAZUKO_WORKING state. Copy all the
+	 * necessary information to userspace structure. */
+
+	/* IMPORTANT: slot is still locked! */
+
+	return s;  /* access is available */
+}
+
+static int dazuko_return_access(struct daemon_id *did, int response, struct slot *s)
+{
+	/* The daemon has finished scanning a file
+	 * and has the response to give. The daemon's
+	 * slot should be in the DAZUKO_WORKING state. */
+
+	struct one_slot_state_not_condition_param	cond_p;
+
+	/* do we already have a slot? */
+	if (s == NULL)
+	{
+		/* find our slot */
+		s = dazuko_find_slot(did, 1, NULL);
+
+		if (s == NULL)
+		{
+			/* It appears the kernel isn't interested
+			 * in us or our response. It gave our slot away! */
+
+			DPRINT(("dazuko: daemon %d unexpectedly lost slot\n", did->unique));
+
+			return XP_ERROR_PERMISSION;
+		}
+	}
+
+	/* we will be writing into the slot, so we
+	 * need to lock it */
+
+/* DOWN? */
+	if (!dazuko_change_slot_state(s, DAZUKO_WORKING, DAZUKO_DONE, 0))
+	{
+		/* The slot is in the wrong state. We will
+		 * assume the kernel has cancelled the file
+		 * access. */
+
+		DPRINT(("dazuko: response from daemon %d on slot[%d] not needed\n", did->unique, s->id));
+
+		return 0;
+	}
+
+/* DOWN */
+
+	s->response = response;
+
+	call_xp_up(&(s->mutex));
+/* UP */
+
+	/* wake up any kernel processes that are
+	 * waiting for responses */
+	call_xp_notify(&wait_kernel_waiting_while_daemon_works);
+
+	cond_p.slot = s;
+	cond_p.state = DAZUKO_DONE;
+	if (call_xp_wait_until_condition(&wait_daemon_waiting_for_free, one_slot_state_not_condition, &cond_p, 1) != 0)
+	{
+		/* The user has issued an interrupt.
+		 * Return an error. The daemon should
+		 * unregister itself. */
+
+		DPRINT(("dazuko: daemon %d killed while waiting for response acknowledgement\n", did->unique));
+
+		return XP_ERROR_INTERRUPT;
+	}
+
+	return 0;
+}
+
+static inline int dazuko_isdigit(const char c)
+{
+	return (c >= '0' && c <= '9');
+}
+
+static inline long dazuko_strtol(const char *string)
+{
+	long		num = 1;
+	const char	*p = string;
+
+	if (string == NULL)
+		return 0;
+
+	switch (*p)
+	{
+		case '-':
+			num = -1;
+			p++;
+			break;
+
+		case '+':
+			p++;
+			break;
+	}
+
+	if (dazuko_isdigit(*p))
+	{
+		num *= *p - '0';
+		p++;
+	}
+	else
+	{
+		return 0;
+	}
+
+	while (dazuko_isdigit(*p))
+	{
+		num *= 10;
+		num += *p - '0';
+		p++;
+	}
+
+	return num;
+}
+
+static inline int dazuko_strlen(const char *string)
+{
+	const char	*p;
+
+	if (string == NULL)
+		return -1;
+
+	for (p=string ; *p ; p++)
+		continue;
+
+	return (p - string);
+}
+
+static inline const char* dazuko_strchr(const char *haystack, char needle)
+{
+	const char	*p;
+
+	if (haystack == NULL)
+		return NULL;
+
+	for (p=haystack ; *p ; p++)
+	{
+		if (*p == needle)
+			return p;
+	}
+
+	return NULL;
+}
+
+static inline const char* dazuko_strstr(const char *haystack, const char *needle)
+{
+	const char	*p1;
+	const char	*p2;
+	const char	*p3;
+
+	if (haystack == NULL || needle == NULL)
+		return NULL;
+
+	for (p1=haystack ; *p1 ; p1++)
+	{
+		for (p2=needle,p3=p1 ; *p2&&*p3 ; p2++,p3++)
+		{
+			if (*p2 != *p3)
+				break;
+		}
+
+		if (*p2 == 0)
+			return p1;
+	}
+
+	return NULL;
+}
+
+int dazuko_get_value(const char *key, const char *string, char **value)
+{
+	const char	*p1;
+	const char	*p2;
+	int		size;
+
+	if (value == NULL)
+		return -1;
+
+	*value = NULL;
+
+	if (key == NULL || string == NULL)
+		return -1;
+
+	p1 = dazuko_strstr(string, key);
+	if (p1 == NULL)
+		return -1;
+
+	p1 += dazuko_strlen(key);
+
+	for (p2=p1 ; *p2 && *p2!='\n' ; p2++)
+		continue;
+
+	size = (p2 - p1) + 1;
+	*value = rsbac_kmalloc_unlocked(size);
+	if (*value == NULL)
+		return -1;
+
+	memcpy(*value, p1, size - 1);
+	(*value)[size - 1] = 0;
+
+	return 0;
+}
+
+static inline void dazuko_clear_replybuffer(struct dazuko_request *request)
+{
+	dazuko_bzero(request->reply_buffer, request->reply_buffer_size);
+	request->reply_buffer_size_used = 0;
+}
+
+static inline void dazuko_close_replybuffer(struct dazuko_request *request)
+{
+	request->reply_buffer[request->reply_buffer_size_used] = 0;
+	request->reply_buffer_size_used++;
+}
+
+static inline void dazuko_add_keyvalue_to_replybuffer(struct dazuko_request *request, const char *key, void *value, char vtype)
+{
+
+#define DAZUKO_VSNPRINT(type, name) dazuko_snprintf(request->reply_buffer + request->reply_buffer_size_used, (request->reply_buffer_size - request->reply_buffer_size_used) - 1, "%s%" #type , key, *((name *)value))
+
+	switch (vtype)
+	{
+		case 'd':
+			DAZUKO_VSNPRINT(d, const int);
+			break;
+
+		case 's':
+			DAZUKO_VSNPRINT(s, const char *);
+			break;
+
+		case 'l':
+			DAZUKO_VSNPRINT(lu, const unsigned long);
+			break;
+
+		default:
+			/* all other types treated as chars */
+			DAZUKO_VSNPRINT(c, const char);
+			break;
+	}
+
+	/* update how much buffer we have used */
+	request->reply_buffer_size_used += strlen(request->reply_buffer + request->reply_buffer_size_used);
+}
+
+static inline int dazuko_printable(char c)
+{
+	/* hopefully this counts for all operating systems! */
+
+	return ((c >= ' ') && (c <= '~') && (c != '\\'));
+}
+
+static inline void dazuko_add_esc_to_replybuffer(struct dazuko_request *request, const char *key, char **filename)
+{
+	int		found = 0;
+	char		*p_rq;
+	const char	*limit;
+	const char	*p_fn;
+	unsigned char	c;
+
+	/* check for escape characters in filename */
+	for (p_fn=*filename ; *p_fn ; p_fn++)
+	{
+		if (!dazuko_printable(*p_fn))
+		{
+			found = 1;
+			break;
+		}
+	}
+
+	if (found)
+	{
+		/* this is expensive, but it will also almost never occur */
+
+		p_rq = request->reply_buffer + request->reply_buffer_size_used;
+		limit = request->reply_buffer + request->reply_buffer_size - 1;
+
+		dazuko_snprintf(p_rq, limit - p_rq, "%s", key);
+		p_rq += strlen(p_rq);
+
+		for (p_fn=*filename ; *p_fn && (p_rq<limit) ; p_fn++)
+		{
+			if (dazuko_printable(*p_fn))
+			{
+				*p_rq = *p_fn;
+				p_rq++;
+			}
+			else
+			{
+				c = *p_fn & 0xFF;
+				dazuko_snprintf(p_rq, limit - p_rq, "\\x%02x", c);
+				p_rq += strlen(p_rq);
+			}
+		}
+
+		request->reply_buffer_size_used += strlen(request->reply_buffer + request->reply_buffer_size_used);
+	}
+	else
+	{
+		/* no escape characters found */
+
+		dazuko_add_keyvalue_to_replybuffer(request, key, filename, 's');
+	}
+}
+
+static int dazuko_set_option(struct daemon_id *did, int opt, void *param, int len)
+{
+	/* The daemon wants to set a configuration
+	 * option in the kernel. */
+
+	struct slot	*s;
+	int		error;
+
+	/* sanity check */
+	if (len < 0 || len > 8192)
+		return XP_ERROR_PERMISSION;
+
+	/* make sure we are already registered
+	 * (or that we don't register twice) */
+
+	/* find our slot */
+	s = dazuko_find_slot(did, 1, NULL);
+
+	switch (opt)
+	{
+		case REGISTER:
+			rsbac_printk(KERN_INFO "dazuko: dazuko_set_option does not support REGISTER (bug!)\n");
+			return XP_ERROR_PERMISSION;
+
+		case UNREGISTER:
+			if (s == NULL)
+			{
+				/* We are not registered! */
+
+				return 0;
+			}
+			break;
+
+		default:
+			if (s == NULL)
+			{
+				error = dazuko_register_daemon(did, "_COMPAT", 7, 1);
+				if (error)
+				{
+					rsbac_printk(KERN_INFO "dazuko: unregistered daemon %d attempted access\n", did->unique);
+					return XP_ERROR_PERMISSION;
+				}
+
+				s = dazuko_find_slot(did, 1, NULL);
+				if (s == NULL)
+				{
+					rsbac_printk(KERN_INFO "dazuko: unregistered daemon %d attempted access\n", did->unique);
+					return XP_ERROR_PERMISSION;
+				}
+
+				rsbac_printk(KERN_INFO "dazuko: warning: daemon %d is using a deprecated protocol\n", did->unique);
+			}
+			break;
+	}
+
+	/* check option type and take the appropriate action */
+	switch (opt)
+	{
+		case UNREGISTER:
+			error = _dazuko_unregister_daemon(did);
+			if (error)
+				return error;
+			break;
+
+		case SET_ACCESS_MASK:
+			memcpy(&access_mask, (char *)param, sizeof(char));
+			break;
+
+		case ADD_INCLUDE_PATH:
+			error = dazuko_insert_path_fs(&incl_paths, (char *)param, len);
+			if (error)
+				return error;
+			break;
+
+		case ADD_EXCLUDE_PATH:
+			error = dazuko_insert_path_fs(&excl_paths, (char *)param, len);
+			if (error)
+				return error;
+			break;
+
+		case REMOVE_ALL_PATHS:
+			dazuko_remove_all_paths();
+			break;
+
+		default:
+			rsbac_printk(KERN_INFO "dazuko: daemon %d requested unknown set %d (possible bug)\n", did->unique, opt);
+			break;
+	}
+
+	return 0;
+}
+
+static int dazuko_handle_request(struct dazuko_request *request, struct xp_daemon_id *xp_id)
+{
+	char			*value1;
+	char			*value2;
+	int			error = 0;
+	int			type;
+	struct slot		*s;
+	struct daemon_id	did;
+
+	if (request == NULL || xp_id == NULL)
+		return -1;
+
+	type = request->type[0] + (256 * request->type[1]);
+
+	switch (type)
+	{
+		case REGISTER:
+			/* read "\nRM=regmode\nGN=group" */
+			/* send "\nID=id" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (request->reply_buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nGN=", request->buffer, &value1) != 0)
+				return -1;
+
+			if (dazuko_get_value("\nRM=", request->buffer, &value2) != 0)
+			{
+				rsbac_kfree(value1);
+				return -1;
+			}
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = 0; /* a unique is not yet assigned */
+
+			error = dazuko_register_daemon(&did, value1, dazuko_strlen(value1), dazuko_strchr(value2, 'W') != NULL);
+
+			dazuko_clear_replybuffer(request);
+			dazuko_add_keyvalue_to_replybuffer(request, "\nID=", &(did.unique), 'd');
+			dazuko_close_replybuffer(request);
+
+			rsbac_kfree(value1);
+			rsbac_kfree(value2);
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		case UNREGISTER:
+			/* read "\nID=id" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = dazuko_strtol(value1);
+
+			error = dazuko_set_option(&did, UNREGISTER, NULL, 0);
+
+			rsbac_kfree(value1);
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		case SET_ACCESS_MASK:
+			/* read "\nID=id\nAM=mask" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			if (dazuko_get_value("\nAM=", request->buffer, &value2) != 0)
+			{
+				rsbac_kfree(value1);
+				return -1;
+			}
+
+			access_mask = (char)dazuko_strtol(value2);
+
+			rsbac_kfree(value1);
+			rsbac_kfree(value2);
+
+			break;
+
+		case ADD_INCLUDE_PATH:
+			/* read "\nID=id\nPT=path" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			if (dazuko_get_value("\nPT=", request->buffer, &value2) != 0)
+			{
+				rsbac_kfree(value1);
+				return -1;
+			}
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = dazuko_strtol(value1);
+
+			error = dazuko_set_option(&did, ADD_INCLUDE_PATH, value2, dazuko_strlen(value2));
+
+			rsbac_kfree(value1);
+			rsbac_kfree(value2);
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		case ADD_EXCLUDE_PATH:
+			/* read "\nID=id\nPT=path" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			if (dazuko_get_value("\nPT=", request->buffer, &value2) != 0)
+			{
+				rsbac_kfree(value1);
+				return -1;
+			}
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = dazuko_strtol(value1);
+
+			error = dazuko_set_option(&did, ADD_EXCLUDE_PATH, value2, dazuko_strlen(value2));
+
+			rsbac_kfree(value1);
+			rsbac_kfree(value2);
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		case REMOVE_ALL_PATHS:
+			/* read "\nID=id" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = dazuko_strtol(value1);
+
+			error = dazuko_set_option(&did, REMOVE_ALL_PATHS, NULL, 0);
+
+			rsbac_kfree(value1);
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		case GET_AN_ACCESS:
+			/* read "\nID=id" */
+			/* send "\nFN=file\nFL=flags\nMD=mode\nUI=uid\nPI=pid" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (request->reply_buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = dazuko_strtol(value1);
+
+			rsbac_kfree(value1);
+
+/* DOWN? */
+			s = dazuko_get_an_access(&did);
+
+			if (s == NULL)
+			{
+				call_xp_id_free(did.xp_id);
+				return XP_ERROR_INTERRUPT;
+			}
+/* DOWN */
+
+			/* Slot IS in DAZUKO_WORKING state. Copy all the
+			 * necessary information to userspace structure. */
+
+			dazuko_clear_replybuffer(request);
+			dazuko_add_keyvalue_to_replybuffer(request, "\nEV=", &(s->event), 'd');
+			dazuko_add_esc_to_replybuffer(request, "\nFN=", &(s->filename));
+
+			if (s->event_p.set_uid)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nUI=", &(s->event_p.uid), 'd');
+
+			if (s->event_p.set_pid)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nPI=", &(s->event_p.pid), 'd');
+
+			if (s->event_p.set_flags)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nFL=", &(s->event_p.flags), 'd');
+
+			if (s->event_p.set_mode)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nMD=", &(s->event_p.mode), 'd');
+
+			if (s->file_p.set_size)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nFS=", &(s->file_p.size), 'l');
+
+			if (s->file_p.set_uid)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nFU=", &(s->file_p.uid), 'd');
+
+			if (s->file_p.set_gid)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nFG=", &(s->file_p.gid), 'd');
+
+			if (s->file_p.set_mode)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nFM=", &(s->file_p.mode), 'd');
+
+			if (s->file_p.set_device_type)
+				dazuko_add_keyvalue_to_replybuffer(request, "\nDT=", &(s->file_p.device_type), 'd');
+
+			dazuko_close_replybuffer(request);
+
+/* XXX: What do we do if there is a problem copying back to userspace?! */
+/* dazuko_state_error(s, DAZUKO_WORKING); */
+
+			/* are we in read_only mode? */
+			if (!(s->write_mode))
+			{
+				/* the access is immediately (and at the kernel level)
+				 * returned */
+
+				call_xp_up(&(s->mutex));
+/* UP */
+
+				dazuko_return_access(&did, 0, s);
+			}
+			else
+			{
+				call_xp_up(&(s->mutex));
+/* UP */
+			}
+
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		case RETURN_AN_ACCESS:
+			/* read "\nID=id\nDN=deny" */
+
+			if (request->buffer_size <= 0)
+				return -1;
+
+			if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
+				return -1;
+
+			if (dazuko_get_value("\nDN=", request->buffer, &value2) != 0)
+			{
+				rsbac_kfree(value1);
+				return -1;
+			}
+
+			did.xp_id = call_xp_id_copy(xp_id);
+			did.unique = dazuko_strtol(value1);
+
+			error = dazuko_return_access(&did, dazuko_strtol(value2), NULL);
+
+			rsbac_kfree(value1);
+			rsbac_kfree(value2);
+			call_xp_id_free(did.xp_id);
+
+			break;
+
+		default:
+			rsbac_printk(KERN_INFO "dazuko: daemon made unknown request %d (possible bug)\n", type);
+
+			break;
+	}
+
+	return error;
+}
+
+int dazuko_handle_user_request(struct dazuko_request *user_request, struct xp_daemon_id *xp_id)
+{
+	int			error = 0;
+	struct dazuko_request	*request;
+	struct dazuko_request	*temp_request;
+
+	if (user_request == NULL || xp_id == NULL)
+		return XP_ERROR_FAULT;
+
+	/* allocate kernel request */
+	request = rsbac_smalloc_unlocked(dazuko_request_slab);
+	if (request == NULL)
+		return XP_ERROR_FAULT;
+
+/* use out0 now */
+
+	/* allocate temp kernel request */
+	temp_request = rsbac_smalloc_unlocked(dazuko_request_slab);
+	if (temp_request == NULL)
+	{
+		error = XP_ERROR_FAULT;
+		goto dazuko_handle_user_request_out0;
+	}
+
+/* use out1 now */
+
+	/* copy in the request */
+	if (call_xp_copyin(user_request, temp_request, sizeof(struct dazuko_request)) != 0)
+	{
+		error = XP_ERROR_FAULT;
+		goto dazuko_handle_user_request_out1;
+	}
+
+	memcpy(request->type, temp_request->type, sizeof(char[2]));
+	request->buffer_size = temp_request->buffer_size;
+
+	/* sanity check */
+	if (request->buffer_size < 0 || request->buffer_size > 8192)
+	{
+		error = XP_ERROR_FAULT;
+		goto dazuko_handle_user_request_out1;
+	}
+
+	request->reply_buffer_size = temp_request->reply_buffer_size;
+
+	/* sanity check */
+	if (request->reply_buffer_size < 0 || request->reply_buffer_size > 8192)
+	{
+		error = XP_ERROR_PERMISSION;
+		goto dazuko_handle_user_request_out1;
+	}
+
+	/* allocate buffer */
+	request->buffer = rsbac_kmalloc_unlocked(request->buffer_size + 1);
+	if (request->buffer == NULL)
+	{
+		error = XP_ERROR_FAULT;
+		goto dazuko_handle_user_request_out1;
+	}
+
+/* use out2 now */
+
+	if (request->reply_buffer_size > 0)
+	{
+		/* allocate reply buffer */
+		request->reply_buffer = rsbac_kmalloc_unlocked(request->reply_buffer_size + 1);
+		if (request->reply_buffer == NULL)
+		{
+			error = XP_ERROR_FAULT;
+			goto dazuko_handle_user_request_out2;
+		}
+
+/* use out3 now */
+
+		request->reply_buffer_size_used = 0;
+	}
+
+	/* copy the buffer from userspace to kernelspace */
+	if (call_xp_copyin(temp_request->buffer, request->buffer, request->buffer_size) != 0)
+	{
+		error = XP_ERROR_FAULT;
+		goto dazuko_handle_user_request_out3;
+	}
+
+	request->buffer[request->buffer_size] = 0;
+
+	error = dazuko_handle_request(request, xp_id);
+
+	if (error == 0 && request->reply_buffer_size > 0)
+	{
+		request->reply_buffer[request->reply_buffer_size] = 0;
+
+		temp_request->reply_buffer_size_used = request->reply_buffer_size_used;
+
+		if (call_xp_copyout(temp_request, user_request, sizeof(struct dazuko_request)) != 0)
+		{
+			error = XP_ERROR_FAULT;
+			goto dazuko_handle_user_request_out3;
+		}
+
+		if (request->reply_buffer_size_used > 0)
+		{
+			if (call_xp_copyout(request->reply_buffer, temp_request->reply_buffer, request->reply_buffer_size_used) != 0)
+			{
+				error = XP_ERROR_FAULT;
+				goto dazuko_handle_user_request_out3;
+			}
+		}
+	}
+
+dazuko_handle_user_request_out3:
+	if (request->reply_buffer_size > 0)
+		rsbac_kfree(request->reply_buffer);
+dazuko_handle_user_request_out2:
+	rsbac_kfree(request->buffer);
+dazuko_handle_user_request_out1:
+	rsbac_sfree(dazuko_request_slab, temp_request);
+dazuko_handle_user_request_out0:
+	rsbac_sfree(dazuko_request_slab, request);
+
+	return error;
+}
+
+int dazuko_handle_user_request_compat12(void *ptr, int cmd, struct xp_daemon_id *xp_id)
+{
+	struct access_compat12	*user_request12;
+	struct access_compat12	*temp_request12;
+	int			error = 0;
+	struct slot		*s;
+	char			*k_param;
+	struct daemon_id	did;
+	int			temp_length;
+	int			temp_int;
+
+	if (ptr == NULL || xp_id == NULL)
+		return XP_ERROR_FAULT;
+
+	did.xp_id = call_xp_id_copy(xp_id);
+	did.unique = -1;
+
+	switch (cmd)
+	{
+		case IOCTL_GET_AN_ACCESS:
+			/* The daemon is requesting a filename of a file
+			 * to scan. This code will wait until a filename
+			 * is available, or until we should be killed.
+			 * (killing is done if any errors occur as well
+			 * as when the user kills us) */
+
+			user_request12 = (struct access_compat12 *)ptr;
+
+			error = call_xp_verify_user_writable(user_request12, sizeof(struct access_compat12));
+			if (error)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+/* DOWN? */
+			s = dazuko_get_an_access(&did);
+
+			if (s == NULL)
+			{
+				error = XP_ERROR_INTERRUPT;
+				break;
+			}
+
+/* DOWN */
+
+			/* Slot IS in WORKING state. Copy all the
+			 * necessary information to userspace structure. */
+
+			if (s->filenamelength >= DAZUKO_FILENAME_MAX_LENGTH_COMPAT12)
+			{
+				/* filename length overflow :( */
+
+				s->filename[DAZUKO_FILENAME_MAX_LENGTH_COMPAT12 - 1] = 0;
+				temp_length = DAZUKO_FILENAME_MAX_LENGTH_COMPAT12;
+			}
+			else
+			{
+				temp_length = s->filenamelength + 1;
+			}
+
+			temp_request12 = rsbac_smalloc_unlocked(access_compat12_slab);
+			if (temp_request12 == NULL)
+			{
+				error = XP_ERROR_FAULT;
+			}
+			else if (call_xp_copyin(user_request12, temp_request12, sizeof(struct access_compat12)) != 0)
+			{
+				error = XP_ERROR_FAULT;
+			}
+
+			if (error == 0)
+			{
+				temp_request12->event = s->event;
+				temp_request12->o_flags = s->event_p.flags;
+				temp_request12->o_mode = s->event_p.mode;
+				temp_request12->uid = s->event_p.uid;
+				temp_request12->pid = s->event_p.pid;
+				memcpy(temp_request12->filename, s->filename, temp_length);
+
+				if (call_xp_copyout(temp_request12, user_request12, sizeof(struct access_compat12)) != 0)
+				{
+					error = XP_ERROR_FAULT;
+				}
+			}
+
+			call_xp_up(&(s->mutex));
+/* UP */
+
+			if (error)
+			{
+				dazuko_state_error(s, DAZUKO_WORKING);
+			}
+
+			if (temp_request12 != NULL)
+			{
+				rsbac_sfree(access_compat12_slab, temp_request12);
+			}
+
+			break;
+
+		case IOCTL_RETURN_ACCESS:
+			/* The daemon has finished scanning a file
+			 * and has the response to give. The daemon's
+			 * slot should be in the WORKING state. */
+
+			user_request12 = (struct access_compat12 *)ptr;
+
+			error = call_xp_verify_user_readable(user_request12, sizeof(struct access_compat12));
+			if (error)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			temp_request12 = rsbac_smalloc_unlocked(access_compat12_slab);
+			if (temp_request12 == NULL)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			if (call_xp_copyin(user_request12, temp_request12, sizeof(struct access_compat12)) != 0)
+			{
+				error = XP_ERROR_FAULT;
+			}
+
+			temp_int = temp_request12->deny;
+
+			rsbac_sfree(access_compat12_slab, temp_request12);
+
+			error = dazuko_return_access(&did, temp_int, NULL);
+			break;
+
+		case IOCTL_SET_OPTION:
+			/* The daemon wants to set a configuration
+			 * option in the kernel. */
+
+			error = call_xp_verify_user_readable(ptr, 2*sizeof(int));
+			if (error)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			/* copy option type from userspace */
+			if (call_xp_copyin(ptr, &temp_int, sizeof(int)) != 0)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			ptr = ((char *)ptr + sizeof(int));
+
+			/* copy path length from userspace */
+			if (call_xp_copyin(ptr, &temp_length, sizeof(int)) != 0)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			/* sanity check */
+			if (temp_length < 0 || temp_length > 4096)
+			{
+				error = XP_ERROR_INVALID;
+				break;
+			}
+
+			ptr = ((char *)ptr + sizeof(int));
+
+			error = call_xp_verify_user_readable(ptr, temp_length);
+			if (error)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			k_param = rsbac_kmalloc_unlocked(temp_length + 1);
+			if (k_param == NULL)
+			{
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			/* We must copy the param from userspace to kernelspace. */
+
+			if (call_xp_copyin(ptr, k_param, temp_length) != 0)
+			{
+				rsbac_kfree(k_param);
+				error = XP_ERROR_FAULT;
+				break;
+			}
+
+			k_param[temp_length] = 0;
+
+			if (temp_int == REGISTER)
+				error = dazuko_register_daemon(&did, k_param, temp_length, 1);
+			else
+				error = dazuko_set_option(&did, temp_int, k_param, temp_length);
+
+			rsbac_kfree(k_param);
+
+			break;
+
+		default:
+			rsbac_printk(KERN_INFO "dazuko: daemon requested unknown device_ioctl %d (possible bug)\n", cmd);
+
+			break;
+	}
+
+	call_xp_id_free(did.xp_id);
+
+	return error;
+}
+
+static struct slot * dazuko_get_and_hold_ready_slot(struct slot_list *sl)
+{
+	/* This is a simple search to find a
+	 * slot whose state is DAZUKO_READY. This means
+	 * it is able to accept work. If a slot
+	 * is found, the slot.mutex is held so
+	 * it can be filled with work by the caller.
+	 * It is the responsibility of the caller
+	 * to RELEASE THE MUTEX. */
+
+	int		i;
+	struct slot	*s;
+
+	for (i=0 ; i<NUM_SLOTS ; i++)
+	{
+		s = &(sl->slots[i]);
+/* DOWN? */
+		if (dazuko_change_slot_state(s, DAZUKO_READY, DAZUKO_WAITING, 0))
+		{
+/* DOWN */
+			return s;
+		}
+	}
+
+	/* we didn't find a slot that is ready for work */
+
+	return NULL;
+}
+
+static int get_ready_slot_condition(void *param)
+{
+	return ((((struct get_ready_slot_condition_param *)param)->slot = dazuko_get_and_hold_ready_slot(((struct get_ready_slot_condition_param *)param)->slotlist)) != NULL
+		|| call_xp_atomic_read(&active) == 0
+		|| call_xp_atomic_read(&(((struct get_ready_slot_condition_param *)param)->slotlist->use_count)) == 0);
+}
+
+static int dazuko_run_daemon_on_slotlist(int event, char *filename, int filenamelength, struct event_properties *event_p, struct file_properties *file_p, int prev_response, struct slot_list *sl)
+{
+	/* This is the main function called by the kernel
+	 * to work with a daemon. */
+
+	int						rc;
+	int						unique;
+	struct slot					*s;
+	struct get_ready_slot_condition_param		cond_p1;
+	struct two_slot_state_not_condition_param	cond_p2;
+
+begin:
+	/* we initialize the slot value because
+	 * we cannot guarentee that it will be
+	 * assigned a new value BEFORE !active
+	 * is checked */
+	s = NULL;
+
+	/* wait for a slot to become ready */
+	cond_p1.slotlist = sl;
+	cond_p1.slot = s;
+	if (call_xp_wait_until_condition(&wait_kernel_waiting_for_free_slot, get_ready_slot_condition, &cond_p1, 0) != 0)
+	{
+		/* The kernel process was killed while
+		 * waiting for a slot to become ready.
+		 * This is fine. */
+
+		DPRINT(("dazuko: kernel process %d killed while waiting for free slot\n", event_p->pid));
+
+		return -1;  /* user interrupted */
+	}
+
+	/* Make sure we have a slot. We may have
+	 * gotten past the last wait because we
+	 * are no longer active. */
+
+	s = cond_p1.slot;
+
+	if (s == NULL)
+	{
+		/* We were no longer active. We don't
+		 * need to initiate a daemon. This also
+		 * means we never acquired the lock. */
+
+		return 0;  /* allow access */
+	}
+
+/* DOWN */
+
+	/* the slot is already locked at this point */
+
+	/* grab the daemon's unique */
+	unique = s->did.unique;
+
+	/* At this point we have a locked slot. It IS
+	 * sitting in the DAZUKO_WAITING state, waiting for
+	 * us to give it some work. */
+	
+	/* set up the slot to do work */
+	s->filename = filename;
+	s->event = event;
+	s->response = prev_response;
+	s->filenamelength = filenamelength;
+
+	if (event_p == NULL)
+		dazuko_bzero(&(s->event_p), sizeof(struct event_properties));
+	else
+		memcpy(&(s->event_p), event_p, sizeof(struct event_properties));
+
+	if (file_p == NULL)
+		dazuko_bzero(&(s->file_p), sizeof(struct file_properties));
+	else
+		memcpy(&(s->file_p), file_p, sizeof(struct file_properties));
+
+	/* we are done modifying the slot */
+	call_xp_up(&(s->mutex));
+/* UP */
+
+	/* wake up any daemons waiting for work */
+	call_xp_notify(&wait_daemon_waiting_for_work);
+
+	/* wait until the daemon is finished with the slot */
+	cond_p2.slot1 = s;
+	cond_p2.state1 = DAZUKO_WAITING;
+	cond_p2.slot2 = s;
+	cond_p2.state2 = DAZUKO_WORKING;
+	if (call_xp_wait_until_condition(&wait_kernel_waiting_while_daemon_works, two_slot_state_not_condition, &cond_p2, 0) != 0)
+	{
+		/* The kernel process was killed while
+		 * waiting for a daemon to process the file.
+		 * This is fine. */
+
+		DPRINT(("dazuko: kernel process %d killed while waiting for daemon response\n", event_p->pid));
+
+		/* change the slot's state to let the
+		 * daemon know we are not interested
+		 * in a response */
+		dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE, 1);
+
+		return -1;  /* user interrupted */
+	}
+
+	/* we are working with the slot, so
+	 * we need to lock it */
+/* DOWN */
+	if (call_xp_down(&(s->mutex)) != 0)
+	{
+		return -1;  /* user interrupted */
+	}
+
+	/* make sure this is the right daemon */
+	if (s->did.unique != unique)
+	{
+		/* This is a different daemon than
+		 * the one we assigned work to.
+		 * We need to scan again. */
+		call_xp_up(&(s->mutex));
+/* UP */
+		goto begin;
+	}
+
+	/* The slot should now be in the DAZUKO_DONE state. */
+	if (!__dazuko_change_slot_state(s, DAZUKO_DONE, DAZUKO_FREE))
+	{
+		/* The daemon was killed while scanning.
+		 * We need to scan again. */
+
+		call_xp_up(&(s->mutex));
+/* UP */
+		goto begin;
+	}
+
+	/* grab the response */
+	rc = s->response;
+
+	call_xp_up(&(s->mutex));
+/* UP */
+
+	/* CONGRATULATIONS! You successfully completed a full state cycle! */
+
+	return rc;
+}
+
+static int dazuko_run_daemon(int event, char *filename, int filenamelength, struct event_properties *event_p, struct file_properties *file_p)
+{
+	struct slot_list	*sl;
+	int			i;
+	int			rc = 0;
+	int			error;
+
+	if (event_p != NULL)
+	{
+		/* we don't want to throw the same event twice */
+		if (event_p->thrown)
+			return 0;
+		event_p->thrown = 1;
+	}
+
+	for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+	{
+/* DOWN */
+		/* if we are interrupted, we report error */
+		if (call_xp_down(&(slot_lists[i].mutex)) != 0)
+			return XP_ERROR_INTERRUPT;
+
+		sl = slot_lists[i].slot_list;
+
+		call_xp_up(&(slot_lists[i].mutex));
+/* UP */
+
+		if (sl != NULL)
+		{
+			error = dazuko_run_daemon_on_slotlist(event, filename, filenamelength, event_p, file_p, rc, sl);
+
+			if (error < 0)
+			{
+				/* most likely user interrupt */
+				rc = error;
+				break;
+			}
+			else if (error > 0)
+			{
+				/* this daemon wants access blocked */
+				rc = 1;
+			}
+		}
+	}
+
+	return rc;
+}
+
+inline int dazuko_is_our_daemon(struct xp_daemon_id *xp_id)
+{
+	/* Check if the current process is one
+	 * of the daemons. */
+
+	struct daemon_id	did;
+	int			ret;
+
+	did.xp_id = call_xp_id_copy(xp_id);
+	did.unique = -1;
+
+	ret = (dazuko_find_slot(&did, 1, NULL) != NULL);
+
+	call_xp_id_free(did.xp_id);
+
+	return ret;
+}
+
+#ifdef CONFIG_RSBAC_DAZ_SELECT
+static int dazuko_is_selected(struct dazuko_file_struct *kfs)
+{
+	/* Check if the given filename (with path) is
+	 * under our include directories but not under
+	 * the exclude directories. */
+
+	struct dazuko_file_listnode	*cur;
+	struct dazuko_path			*path;
+	int				selected = 0;
+	int				use_aliases = 1;
+
+	if (kfs == NULL)
+		return 0;
+
+	/* If we are interrupted here, we will report that
+	 * this file is not selected. This will make the
+	 * kernel allow normal access. Is this dangerous? */
+/* LOCK */
+	call_xp_read_lock(&lock_lists);
+
+	if (kfs->aliases == NULL && kfs->filename != NULL)
+	{
+		/* extension is not using aliases */
+
+		use_aliases = 0;
+
+		kfs->aliases = rsbac_smalloc_clear(dazuko_file_listnode_slab);
+		if (kfs->aliases == NULL)
+		{
+			rsbac_printk(KERN_WARNING "dazuko: warning: access not controlled (%s)\n", kfs->filename);
+			return 0;
+		}
+
+		kfs->aliases->filename = kfs->filename;
+		kfs->aliases->filename_length = kfs->filename_length;
+	}
+
+	for (cur=kfs->aliases ; cur ; cur=cur->next)
+	{
+		if (cur->filename != NULL && cur->filename_length > 0)
+		{
+			/* check if filename is under our include paths */
+			for (path=incl_paths ; path ; path=path->next)
+			{
+				/* the include item must be at least as long as the given filename */
+				if (path->len <= cur->filename_length)
+				{
+					/* the include item should match the beginning of the given filename */
+					if (memcmp(path->path, cur->filename, path->len) == 0)
+					{
+						kfs->filename = cur->filename;
+						kfs->filename_length = cur->filename_length;
+
+						selected = 1;
+						break;
+					}
+				}
+			}
+
+			/* If we didn't find a path, it isn't in our
+			 * include directories. It can't be one of
+			 * the selected files to scan. */
+			if (!selected)
+			{
+				continue;
+			}
+
+			/* check if filename is under our exclude paths */
+			for (path=excl_paths ; path ; path=path->next)
+			{
+				/* the exclude item must be at least as long as the given filename */
+				if (path->len <= cur->filename_length)
+				{
+					/* the exclude item should match the beginning of the given filename */
+					if (memcmp(path->path, cur->filename, path->len) == 0)
+					{
+						kfs->filename = NULL;
+						kfs->filename_length = 0;
+
+						selected = 0;
+						break;
+					}
+				}
+			}
+
+			/* If we are still selected, then we can stop. */
+			if (selected)
+				break;
+		}
+	}
+
+	call_xp_read_unlock(&lock_lists);
+/* UNLOCK */
+
+	if (!use_aliases)
+	{
+		rsbac_sfree(dazuko_file_listnode_slab, kfs->aliases);
+		kfs->aliases = NULL;
+	}
+
+	return selected;
+}
+#endif
+
+static int dazuko_add_hash(struct xp_file *file, char *filename, int len)
+{
+	/* Add the given file and filename to the linked list
+	 * of files to scan once they are closed. */
+
+	struct hash	*h;
+
+	/* create a new struct hash structure making room for name also */
+	h = rsbac_kmalloc_unlocked(sizeof(struct hash) + len + 1);
+	if (h == NULL)
+		return XP_ERROR_FAULT;
+
+	/* fill in structure items */
+
+	call_xp_copy_file(&(h->file), file);
+	h->dirty = 0;
+	h->namelen = len;
+	memcpy(h->name, filename, len);
+	h->name[len] = 0;
+
+	/* add the new struct hash item to the head of the
+	 * struct hash linked list */
+
+/* LOCK */
+	call_xp_write_lock(&lock_hash);
+	h->next = hash;
+	hash = h;
+	call_xp_write_unlock(&lock_hash);
+/* UNLOCK */
+	return 0;
+}
+
+/* Code based on code from: Swade 12/08/02: Move dirty to end of list */
+static void dazuko_mark_hash_dirty(struct xp_file *file)
+{
+	struct hash	*h = NULL;
+	struct hash	*entry = NULL;
+	struct hash	*prev = NULL;
+	struct hash	*prev_entry = NULL;
+
+/* LOCK */
+	call_xp_write_lock(&lock_hash);
+
+	for (h=hash ; h ; h=h->next)
+	{
+		/* not found if hit first dirty entry */
+		if (h->dirty)
+		{
+			entry = NULL;
+			break;
+		}
+
+		if (call_xp_compare_file(&(h->file), file) == 0)
+		{
+			/* we found the entry */
+
+			prev_entry = prev;
+			entry = h;
+			break;
+		}
+
+		prev = h;
+	} 
+
+	if (entry)
+	{
+		if (!entry->dirty)
+		{
+			/* mark as dirty */
+			entry->dirty = 1;
+
+			/* If we already are last entry or next
+		 	 * entry dirty, we don't need to move */
+
+			if (entry->next)
+			{
+				if (!entry->next->dirty)
+				{
+					for (h=entry->next ; h ; h=h->next)
+					{
+						if (h->dirty)
+							break;
+
+						prev = h;
+					}
+
+					/* remove from current position */
+					if (prev_entry)
+						prev_entry->next = entry->next;
+					else
+						hash = entry->next;
+
+					if (prev == NULL)
+					{
+						/* insert as first item */
+						entry->next = hash;
+						hash = entry;
+					}
+					else if (h)
+					{
+						/* insert before h (after prev) */
+						entry->next = prev->next;
+						prev->next = entry;
+					}
+					else
+					{
+						/* insert as last item (after prev) */
+						entry->next = NULL;
+						prev->next = entry;
+					}
+				}
+			}
+		}
+	}
+
+	call_xp_write_unlock(&lock_hash);
+/* UNLOCK */
+
+}
+
+static struct hash *dazuko_get_hash(struct xp_file *file)
+{
+	/* Find the given file within our list
+	 * and then remove it from the list and
+	 * return it. */
+
+	struct hash	*prev;
+	struct hash	*cur;
+
+/* LOCK */
+	call_xp_write_lock(&lock_hash);
+
+	prev = NULL;
+	cur = hash;
+	while (cur)
+	{
+		if (call_xp_compare_file(&(cur->file), file) == 0)
+		{
+			/* we found the entry */
+
+			/* remove the item from the list */
+			if (!prev)
+				hash = cur->next;
+			else
+				prev->next = cur->next;
+			break;
+		}
+
+		prev = cur;
+		cur = cur->next;
+	}
+
+	call_xp_write_unlock(&lock_hash);
+/* UNLOCK */
+
+	return cur;
+}
+
+static int dazuko_should_scan(struct dazuko_file_struct *kfs)
+{
+	/* Check if we are supposed to scan this file.
+	 * This checks for all the correct file types,
+	 * permissions, and if it is within the desired
+	 * paths to scan. */
+
+	int result = 0;
+
+	/* check if we already know if we scan this file */
+	switch (kfs->should_scan)
+	{
+		/* case 0 means that we do not know yet. This is a little
+		 * confusing, because 0 represents uninitialized. However,
+		 * the should_scan variable is used in this function ONLY
+		 * so this optimization shouldn't cause any problems. */
+
+		case 1:
+			/* we already know it should be scanned */
+			return 1;
+
+		case 2:
+			/* we already know it should not be scanned */
+			return 2;
+	}
+
+	/* make necessary platform-dependent checks */
+	if (call_xp_fill_file_struct(kfs) == 0)
+	{
+#ifdef CONFIG_RSBAC_DAZ_SELECT
+		if (dazuko_is_selected(kfs))
+		{
+#endif
+			/* If we made it this far, we are supposed
+			 * to scan this file. We mark it so that
+			 * any further immediate inquiries don't have
+			 * to do all this work all over again. */
+ 
+			/* yes, should be scanned */
+			kfs->should_scan = 1;
+
+			result = 1;
+#ifdef CONFIG_RSBAC_DAZ_SELECT
+		}
+		else
+		{
+			/* We will still mark it so that any further
+			 * immediate inquiries don't have to do all
+			 * this work all over again. */
+
+			/* no, should not be scanned */
+			kfs->should_scan = 2;
+		}
+#endif
+	}
+
+	return result;
+}
+
+inline int dazuko_sys_check(unsigned long event, int daemon_is_allowed, struct xp_daemon_id *xp_id)
+{
+	/* is this event in our mask? */
+	switch (event)
+	{
+		case DAZUKO_ON_OPEN:
+			/* this is a special case because the on_close information needs
+			 * to be saved during the on_open event */
+
+			if ((SCAN_ON_OPEN || SCAN_ON_CLOSE || SCAN_ON_CLOSE_MODIFIED) == 0)
+				return -1;
+			break;
+
+		case DAZUKO_ON_CLOSE:
+			/* will need to scan if ON_CLOSE_MODIFIED is in the mask too */
+
+			if ((SCAN_ON_CLOSE || SCAN_ON_CLOSE_MODIFIED) == 0)
+				return -2;
+			break;
+
+		default:
+			if ((access_mask & event) == 0)
+				return -3;
+			break;
+	}
+
+	/* do we have any daemons? */
+	if (call_xp_atomic_read(&active) <= 0)
+		return -4;
+
+	/* should daemons be allowed this event without a scan? */
+	if (daemon_is_allowed)
+	{
+		if (dazuko_is_our_daemon(xp_id))
+		{
+			/* this is one of our daemons, so we will report as
+			 * as if this event was not in the mask */
+
+			return -5;
+		}
+	}
+
+	return 0;
+}
+
+inline int dazuko_sys_pre(unsigned long event, struct dazuko_file_struct *kfs, struct xp_file *file, struct event_properties *event_p)
+{
+	/* return codes:
+	 *   >0 -> access should be blocked
+	 *   <0 -> access should be blocked (because user interrupted)
+	 *    0 -> access is allowed
+	 *   -2 -> unscanned access should not be taken care of
+	 */
+
+	int		error = 0;
+	struct hash	*h = NULL;
+
+	switch (event)
+	{
+		case DAZUKO_ON_OPEN:
+			/* special case, because this pre may be called
+			 * in order to record ON_CLOSE events (in post) */
+
+			if (!SCAN_ON_OPEN)
+				return 2;
+			break;
+
+		case DAZUKO_ON_CLOSE:
+			/* handled in post */
+
+			return 2;
+
+		case DAZUKO_ON_CLOSE_MODIFIED:
+			/* (this is really sys_write) always permitted */
+
+			return 2;
+
+		default:
+			break;
+	}
+
+	if (kfs == NULL)
+	{
+		/* kfs is required */
+
+		rsbac_printk(KERN_WARNING "dazuko: kfs=NULL (possible bug)\n");
+
+		return XP_ERROR_PERMISSION;
+	}
+
+	if (file != NULL)
+	{
+		/* we search for the file descriptor first */
+
+/* LOCK */
+		call_xp_read_lock(&lock_hash);
+
+		for (h=hash ; h ; h=h->next)
+		{
+			if (call_xp_compare_file(&(h->file), file) == 0)
+			{
+				/* we found the file descriptor */
+
+				kfs->filename = rsbac_kmalloc_unlocked(h->namelen + 1);
+				if (kfs->filename != NULL)
+				{
+					memcpy(kfs->filename, h->name, h->namelen);
+					kfs->filename[h->namelen] = 0;
+					kfs->filename_length = h->namelen;
+					kfs->should_scan = 1;
+				}
+				else
+				{
+					/* error allocating, so we get out */
+					h = NULL;
+				}
+				break;
+			}
+		}
+
+		call_xp_read_unlock(&lock_hash);
+/* UNLOCK */
+
+		if (h == NULL && kfs->extra_data == NULL)
+		{
+			/* we don't know this file descriptor
+			 * and we cannot fallback on name lookups
+			 */
+
+			/* we should not scan this file */
+			kfs->should_scan = 2;
+
+			return 0;
+		}
+	}
+
+	/* make sure we should scan this file */
+	if (dazuko_should_scan(kfs))
+		error = dazuko_run_daemon(event, kfs->filename, kfs->filename_length, event_p, &(kfs->file_p));
+	else
+		return 2;
+
+	if (error > 0)
+	{
+		/* access will be blocked */
+
+		/* dazuko_sys_post should NOT be called! */
+
+		return XP_ERROR_PERMISSION;
+	}
+	else if (error < 0)
+	{
+		/* user interrupted */
+
+		/* dazuko_sys_post should NOT be called! */
+
+		return XP_ERROR_INTERRUPT;
+	}
+
+	/* access allowed */
+
+	return 0;
+}
+
+inline int dazuko_sys_post(unsigned long event, struct dazuko_file_struct *kfs, struct xp_file *file, struct event_properties *event_p)
+{
+	struct hash	*h = NULL;
+
+	switch (event)
+	{
+		case DAZUKO_ON_OPEN: /* kfs,file required */
+			/* if the file was opened and we are interested
+			 * in scanning on close, add this file to our struct hash list */
+
+			if ((call_xp_atomic_read(&active) > 0) && file != NULL && kfs != NULL)
+			{
+				if (SCAN_ON_OPEN || SCAN_ON_CLOSE || SCAN_ON_CLOSE_MODIFIED)
+				{
+					/* make sure we should scan this file */
+					if (dazuko_should_scan(kfs))
+					{
+						/* hash is added if we were given an xp_file */
+						if (file != NULL)
+							dazuko_add_hash(file, kfs->filename, kfs->filename_length);
+
+						/* this is a fallback in case we didn't process the event in "sys_pre" */
+						dazuko_run_daemon(event, kfs->filename, kfs->filename_length, event_p, &(kfs->file_p));
+					}
+				}
+			}
+			break;
+
+		case DAZUKO_ON_CLOSE: /* file,o_flags,o_mode,pid,uid required */
+			if (file != NULL)
+			{
+				/* find hash entry and remove it from list */
+				h = dazuko_get_hash(file);
+
+				/* if we found the file in our list and the file was
+	 			* successfully closed, we need to scan it */
+				if (h != NULL)
+				{
+					/* determine if we are scanning on close or close_modified */
+
+					/* note that close_modified has priority over just close */
+
+					if (SCAN_ON_CLOSE_MODIFIED && h->dirty)
+						dazuko_run_daemon(DAZUKO_ON_CLOSE_MODIFIED, h->name, h->namelen, event_p, NULL);
+					else if (SCAN_ON_CLOSE)
+						dazuko_run_daemon(DAZUKO_ON_CLOSE, h->name, h->namelen, event_p, NULL);
+
+					/* clean up the struct hash structure */
+					rsbac_kfree(h);
+				}
+			}
+			else
+			{
+				if (SCAN_ON_CLOSE)
+				{
+					if (dazuko_should_scan(kfs))
+					{
+						dazuko_run_daemon(DAZUKO_ON_CLOSE, kfs->filename, kfs->filename_length, event_p, &(kfs->file_p));
+					}
+				}
+			}
+			break;
+
+		case DAZUKO_ON_CLOSE_MODIFIED: /* file required */
+			if (file != NULL)
+			{
+				/* if we actually wrote something and we found the
+				 * file in our list, set it as dirty */
+
+				/* Swade 4/24/02: Move to end of clean list */
+				dazuko_mark_hash_dirty(file);
+			}
+			break;
+
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+inline int dazuko_init(void)
+{
+	int	i;
+	int	error;
+
+#ifdef CONFIG_RSBAC_DAZ_SELECT
+	dazuko_file_listnode_slab = rsbac_slab_create("rsbac_dazuko_file_listnode",
+					sizeof(struct dazuko_file_listnode));
+#endif
+	dazuko_request_slab = rsbac_slab_create("rsbac_dazuko_request",
+					sizeof(struct dazuko_request));
+	access_compat12_slab = rsbac_slab_create("rsbac_dazuko_access_compat12",
+					sizeof(struct access_compat12));
+
+	call_xp_init_mutex(&mutex_unique_count);
+
+	call_xp_init_rwlock(&lock_hash);
+	call_xp_init_rwlock(&lock_lists);
+
+	call_xp_init_queue(&wait_kernel_waiting_for_free_slot);
+	call_xp_init_queue(&wait_daemon_waiting_for_work);
+	call_xp_init_queue(&wait_kernel_waiting_while_daemon_works);
+	call_xp_init_queue(&wait_daemon_waiting_for_free);
+
+	dazuko_bzero(&slot_lists, sizeof(slot_lists));
+
+	for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+		call_xp_init_mutex(&(slot_lists[i].mutex));
+
+	call_xp_atomic_set(&active, 0);
+
+	error = call_xp_sys_hook();
+
+	if (error == 0)
+		rsbac_printk(KERN_INFO "dazuko: loaded, version=%s\n", VERSION);
+
+  	return error;
+}
+
+inline int dazuko_exit(void)
+{
+	int	error;
+	int	i;
+	int	j;
+
+	i = call_xp_atomic_read(&active);
+
+	if (i != 0)
+	{
+		rsbac_printk(KERN_INFO "dazuko: warning: trying to remove Dazuko with %d process%s still registered\n", i, i==1 ? "" : "es");
+		return -1;
+	}
+
+	dazuko_remove_all_paths();
+	dazuko_remove_all_hash();
+
+	error = call_xp_sys_unhook();
+
+	if (error == 0)
+	{
+		call_xp_destroy_mutex(&mutex_unique_count);
+
+		call_xp_destroy_rwlock(&lock_hash);
+		call_xp_destroy_rwlock(&lock_lists);
+
+		call_xp_destroy_queue(&wait_kernel_waiting_for_free_slot);
+		call_xp_destroy_queue(&wait_daemon_waiting_for_work);
+		call_xp_destroy_queue(&wait_kernel_waiting_while_daemon_works);
+		call_xp_destroy_queue(&wait_daemon_waiting_for_free);
+
+		for (i=0 ; i<NUM_SLOT_LISTS ; i++)
+		{
+			if (slot_lists[i].slot_list != NULL)
+			{
+				if (call_xp_atomic_read(&(slot_lists[i].slot_list->use_count)) != 0)
+					rsbac_printk(KERN_WARNING "dazuko: slot_list count was not 0 (possible bug)\n");
+
+				for (j=0 ; j<NUM_SLOTS ; j++)
+				{
+					call_xp_destroy_mutex(&(slot_lists[i].slot_list->slots[j].mutex));
+				}
+
+				rsbac_kfree(slot_lists[i].slot_list);
+				slot_lists[i].slot_list = NULL;
+			}
+
+			call_xp_destroy_mutex(&(slot_lists[i].mutex));
+		}
+
+		rsbac_printk(KERN_INFO "dazuko: unloaded, version=%s\n", VERSION);
+	}
+
+	return error;
+}
diff --git a/rsbac/adf/daz/dazuko_xp.h b/rsbac/adf/daz/dazuko_xp.h
new file mode 100644
index 0000000..d755c87
--- /dev/null
+++ b/rsbac/adf/daz/dazuko_xp.h
@@ -0,0 +1,225 @@
+/* DazukoXP. Allow cross platform file access control for 3rd-party applications.
+   Written by John Ogness <jogness@antivir.de>
+
+   Copyright (c) 2002, 2003, 2004, 2005 H+BEDV Datentechnik GmbH
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+   3. Neither the name of Dazuko nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DAZUKO_XP_H
+#define DAZUKO_XP_H
+
+#define VERSION	"2.0.5"
+
+#include "dazukoio_xp.h"
+
+/* various requests */
+#define SET_ACCESS_MASK		0
+#define ADD_INCLUDE_PATH	1
+#define ADD_EXCLUDE_PATH	2
+#define REGISTER		3
+#define REMOVE_ALL_PATHS	4
+#define UNREGISTER		5
+#define GET_AN_ACCESS		6
+#define RETURN_AN_ACCESS	7
+
+/* slot states */
+#define	DAZUKO_FREE	0	/* the daemon is not ready */
+#define	DAZUKO_READY	1	/* a daemon waits for something to do */
+#define	DAZUKO_WAITING	2	/* a request is waiting to be served */
+#define	DAZUKO_WORKING	3	/* daemon is currently in action */
+#define	DAZUKO_DONE	4	/* daemon response is available */
+#define	DAZUKO_BROKEN	5	/* invalid state (interrupt from ready,waiting) */
+
+/* file types */
+#define DAZUKO_NONE		0
+#define DAZUKO_REGULAR		1
+#define DAZUKO_DIRECTORY	2
+#define DAZUKO_LINK		3
+
+
+/*********************************************************
+ * structures that MUST be implemented by platform-layer *
+ *********************************************************/
+
+/*
+struct xp_file;
+struct xp_mutex;
+struct xp_atomic;
+struct xp_file_struct;
+struct xp_queue;
+struct xp_rwlock;
+struct xp_daemon_id;
+*/
+
+
+/******************************************
+ * structures available to platform-layer *
+ ******************************************/
+
+struct event_properties
+{
+	int	thrown;
+
+	int	flags;
+	char	set_flags;
+	int	mode;
+	char	set_mode;
+	int	uid;
+	char	set_uid;
+	int	pid;
+	char	set_pid;
+};
+
+struct file_properties
+{
+	unsigned long	size;
+	char		set_size;
+	int		uid;
+	char		set_uid;
+	int		gid;
+	char		set_gid;
+	int		mode;
+	char		set_mode;
+	int		device_type;
+	char		set_device_type;
+	int		type;
+	char		set_type;
+};
+
+struct dazuko_file_listnode
+{
+	char				*filename;
+	int				filename_length;
+	struct dazuko_file_listnode	*next;
+};
+
+struct dazuko_file_struct
+{
+	/* A structure designed for simple and
+	 * intelligent memory management when
+	 * doing filename lookups in the kernel. */
+
+	int				should_scan;		/* already know we need to scan? */
+	char				*filename;		/* filename to report (pointer in alias list) */
+	int				filename_length;	/* length of filename reported */
+	struct dazuko_file_listnode	*aliases;		/* list of file names (alias names) */
+	struct file_properties		file_p;			/* properties of file */
+	struct xp_file_struct		*extra_data;		/* extra platform-dependant data */
+};
+
+
+/********************************************************
+ * functions that MUST be implemented by platform-layer *
+ ********************************************************/
+
+/* mutex */
+int xp_init_mutex(struct xp_mutex *mutex);
+int xp_down(struct xp_mutex *mutex);
+int xp_up(struct xp_mutex *mutex);
+int xp_destroy_mutex(struct xp_mutex *mutex);
+
+/* read-write lock */
+int xp_init_rwlock(struct xp_rwlock *rwlock);
+int xp_write_lock(struct xp_rwlock *rwlock);
+int xp_write_unlock(struct xp_rwlock *rwlock);
+int xp_read_lock(struct xp_rwlock *rlock);
+int xp_read_unlock(struct xp_rwlock *rlock);
+int xp_destroy_rwlock(struct xp_rwlock *rwlock);
+
+/* wait-notify queue */
+int xp_init_queue(struct xp_queue *queue);
+int xp_wait_until_condition(struct xp_queue *queue, int (*cfunction)(void *), void *cparam, int allow_interrupt);
+int xp_notify(struct xp_queue *queue);
+int xp_destroy_queue(struct xp_queue *queue);
+
+/* memory */
+void* xp_malloc(size_t size);
+int xp_free(void *ptr);
+int xp_copyin(const void *user_src, void *kernel_dest, size_t size);
+int xp_copyout(const void *kernel_src, void *user_dest, size_t size);
+int xp_verify_user_writable(const void *user_ptr, size_t size);
+int xp_verify_user_readable(const void *user_ptr, size_t size);
+
+/* path attribute */
+int xp_is_absolute_path(const char *path);
+
+/* atomic */
+int xp_atomic_set(struct xp_atomic *atomic, int value);
+int xp_atomic_inc(struct xp_atomic *atomic);
+int xp_atomic_dec(struct xp_atomic *atomic);
+int xp_atomic_read(struct xp_atomic *atomic);
+
+/* file descriptor */
+int xp_copy_file(struct xp_file *dest, struct xp_file *src);
+int xp_compare_file(struct xp_file *file1, struct xp_file *file2);
+
+/* system hook */
+int xp_sys_hook(void);
+int xp_sys_unhook(void);
+
+/* file structure */
+int xp_fill_file_struct(struct dazuko_file_struct *dfs);
+
+/* daemon id */
+int xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2);
+int xp_id_free(struct xp_daemon_id *id);
+struct xp_daemon_id* xp_id_copy(struct xp_daemon_id *id);
+
+/* output */
+int xp_print(const char *fmt, ...);
+
+/* debug */
+#ifdef DEBUG
+#define DPRINT(fmt) xp_print fmt
+#else
+#define DPRINT(fmt)
+#endif
+
+
+/*****************************************
+ * functions available to platform-layer *
+ *****************************************/
+
+int dazuko_vsnprintf(char *str, size_t size, const char *format, va_list ap);
+int dazuko_snprintf(char *str, size_t size, const char *format, ...);
+int dazuko_is_our_daemon(struct xp_daemon_id *xp_id);
+int dazuko_get_value(const char *key, const char *string, char **value);
+int dazuko_unregister_daemon(struct xp_daemon_id *xp_id);
+int dazuko_handle_user_request(struct dazuko_request *user_request, struct xp_daemon_id *xp_id);
+int dazuko_handle_user_request_compat12(void *ptr, int cmd, struct xp_daemon_id *xp_id);
+int dazuko_get_filename_length(char *filename);
+void dazuko_bzero(void *p, int len);
+int dazuko_sys_check(unsigned long event, int daemon_is_allowed, struct xp_daemon_id *xp_id);
+int dazuko_sys_pre(unsigned long event, struct dazuko_file_struct *kfs, struct xp_file *file, struct event_properties *event_p);
+int dazuko_sys_post(unsigned long event, struct dazuko_file_struct *kfs, struct xp_file *file, struct event_properties *event_p);
+int dazuko_init(void);
+int dazuko_exit(void);
+
+#endif
diff --git a/rsbac/adf/daz/dazukoio.h b/rsbac/adf/daz/dazukoio.h
new file mode 100644
index 0000000..9c8ea39
--- /dev/null
+++ b/rsbac/adf/daz/dazukoio.h
@@ -0,0 +1,96 @@
+/* Dazuko Interface. Interace with Dazuko for file access control.
+   Written by John Ogness <jogness@antivir.de>
+
+   Copyright (c) 2002, 2003, 2004 H+BEDV Datentechnik GmbH
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+   3. Neither the name of Dazuko nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DAZUKOIO_H
+#define DAZUKOIO_H
+
+/* event types */
+#define	DAZUKO_ON_OPEN			1
+#define	DAZUKO_ON_CLOSE			2
+#define	DAZUKO_ON_EXEC 			4
+#define	DAZUKO_ON_CLOSE_MODIFIED	8
+#define	DAZUKO_ON_UNLINK		16
+#define	DAZUKO_ON_RMDIR			32
+
+struct dazuko_access
+{
+	int		deny;
+	int		event;
+	char		set_event;
+	int		flags;
+	char		set_flags;
+	int		mode;
+	char		set_mode;
+	int 		uid;
+	char		set_uid;
+	int		pid;
+	char		set_pid;
+	char		*filename;
+	char		set_filename;
+	unsigned long	file_size;
+	char		set_file_size;
+	int		file_uid;
+	char		set_file_uid;
+	int		file_gid;
+	char		set_file_gid;
+	int		file_mode;
+	char		set_file_mode;
+	int		file_device;
+	char		set_file_device;
+};
+
+struct dazuko_id;
+typedef struct dazuko_id dazuko_id_t;
+
+/* single-threaded API */
+int dazukoRegister(const char *groupName, const char *mode);
+int dazukoSetAccessMask(unsigned long accessMask);
+int dazukoAddIncludePath(const char *path);
+int dazukoAddExcludePath(const char *path);
+int dazukoRemoveAllPaths(void);
+int dazukoGetAccess(struct dazuko_access **acc);
+int dazukoReturnAccess(struct dazuko_access **acc);
+int dazukoUnregister(void);
+
+/* thread-safe API (as long as each thread has its own "dazuko_id_t") */
+int dazukoRegister_TS(dazuko_id_t **dazuko, const char *groupName, const char *mode);
+int dazukoSetAccessMask_TS(dazuko_id_t *dazuko, unsigned long accessMask);
+int dazukoAddIncludePath_TS(dazuko_id_t *dazuko, const char *path);
+int dazukoAddExcludePath_TS(dazuko_id_t *dazuko, const char *path);
+int dazukoRemoveAllPaths_TS(dazuko_id_t *dazuko);
+int dazukoGetAccess_TS(dazuko_id_t *dazuko, struct dazuko_access **acc);
+int dazukoReturnAccess_TS(dazuko_id_t *dazuko, struct dazuko_access **acc);
+int dazukoUnregister_TS(dazuko_id_t **dazuko);
+
+#endif
diff --git a/rsbac/adf/daz/dazukoio_xp.h b/rsbac/adf/daz/dazukoio_xp.h
new file mode 100644
index 0000000..4f8ccf0
--- /dev/null
+++ b/rsbac/adf/daz/dazukoio_xp.h
@@ -0,0 +1,100 @@
+/* DazukoXP Interface. Interace with Dazuko for file access control.
+   Written by John Ogness <jogness@antivir.de>
+
+   Copyright (c) 2002, 2003, 2004 H+BEDV Datentechnik GmbH
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+   2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+   3. Neither the name of Dazuko nor the names of its contributors may be used
+   to endorse or promote products derived from this software without specific
+   prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+   POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DAZUKOIO_XP_H
+#define DAZUKOIO_XP_H
+
+/* various requests */
+#define SET_ACCESS_MASK		0
+#define ADD_INCLUDE_PATH	1
+#define ADD_EXCLUDE_PATH	2
+#define REGISTER		3
+#define REMOVE_ALL_PATHS	4
+#define UNREGISTER		5
+#define GET_AN_ACCESS		6
+#define RETURN_AN_ACCESS	7
+
+/* this is just a large number to "guarentee"
+   to contain the full filename */
+#define DAZUKO_FILENAME_MAX_LENGTH	6144
+
+/* this is the hard-limit file length restriction from
+   the 1.x series */
+#define DAZUKO_FILENAME_MAX_LENGTH_COMPAT12	4095
+
+struct dazuko_request
+{
+	char	type[2];
+	int	buffer_size;
+	char	*buffer;
+	int	reply_buffer_size;
+	char	*reply_buffer;
+	int	reply_buffer_size_used;
+};
+
+struct dazuko_id
+{
+	int	device;
+	int	dev_major;
+	int	id;
+	int	write_mode;
+};
+
+/* compat12 ioctls */
+
+#define	IOCTL_SET_OPTION	0
+#define	IOCTL_GET_AN_ACCESS	1
+#define	IOCTL_RETURN_ACCESS	2
+
+/* compat12 structures */
+
+struct access_compat12
+{
+	int	deny;		/* set to deny file access */
+	int	event;		/* ON_OPEN, etc */
+	int	o_flags;	/* access flags */
+	int	o_mode;		/* access mode */
+	int	uid;		/* user id */
+	int	pid;		/* user process id */
+	char	filename[DAZUKO_FILENAME_MAX_LENGTH_COMPAT12];	/* accessed file */
+};
+
+struct option_compat12
+{
+	int	command;
+	int	buffer_length;
+	char	buffer[DAZUKO_FILENAME_MAX_LENGTH_COMPAT12];
+};
+
+#endif
diff --git a/rsbac/adf/ff/Makefile b/rsbac/adf/ff/Makefile
new file mode 100644
index 0000000..139b30b
--- /dev/null
+++ b/rsbac/adf/ff/Makefile
@@ -0,0 +1,9 @@
+#
+# File: rsbac/adf/ff/Makefile
+#
+# Makefile for the Linux rsbac ff decision module.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := ff_main.o
diff --git a/rsbac/adf/ff/ff_main.c b/rsbac/adf/ff/ff_main.c
new file mode 100644
index 0000000..2db6890
--- /dev/null
+++ b/rsbac/adf/ff/ff_main.c
@@ -0,0 +1,712 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - File Flags                       */
+/* File: rsbac/adf/ff/main.c                         */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+
+#include <asm/uaccess.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+
+static enum rsbac_adf_req_ret_t
+  check_flags_ff(enum rsbac_target_t target,
+                 union rsbac_target_id_t tid,
+                 rsbac_ff_flags_t flags)
+  {
+    union rsbac_attribute_value_t i_attr_val1;
+
+    /* get target's file flags */
+    if (rsbac_get_attr(SW_FF, target,
+                       tid,
+                       A_ff_flags,
+                       &i_attr_val1,
+                       TRUE))
+      {
+        rsbac_printk(KERN_WARNING "check_flags_ff(): rsbac_get_attr() returned error!\n");
+        return(NOT_GRANTED);
+      }
+
+    /* Access is granted, if none of the flags in argument flags is set */
+    if (i_attr_val1.ff_flags & flags)
+      return(NOT_GRANTED);
+    else
+      return(GRANTED);
+  }
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request_ff (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)
+  {
+    enum  rsbac_adf_req_ret_t result = DO_NOT_CARE;
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    int err=0;
+
+    switch (request)
+      {
+        case R_GET_STATUS_DATA:
+            switch(target)
+              {
+                case T_SCD:
+                  switch(tid.scd)
+                    {
+                      case ST_rsbac_log:
+                      case ST_rsbac_remote_log:
+                        break;
+                      default:
+                        return GRANTED;
+                    }
+                  i_tid.user = owner;
+                  if ((err=rsbac_get_attr(SW_FF, T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE)))
+                    {
+                      rsbac_printk(KERN_WARNING
+                             "rsbac_adf_request_ff(): rsbac_get_attr() returned error %i!\n",err);
+                      return(NOT_GRANTED);
+                    }
+                  if (   (i_attr_val1.system_role == SR_security_officer)
+                      || (i_attr_val1.system_role == SR_auditor)
+                     )
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+                default:
+                  return(DO_NOT_CARE);
+               }
+
+#if defined(CONFIG_RSBAC_FF_UM_PROT)
+        case R_GET_PERMISSIONS_DATA:
+            switch(target)
+              {
+                case T_USER:
+                case T_GROUP:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF,
+                                     T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_ff()", A_ff_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* We do not care about */
+                /* all other cases */
+                default: return(DO_NOT_CARE);
+              }
+#endif
+
+        case R_READ:
+            switch(target)
+              {
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_search_only));
+
+#ifdef CONFIG_RSBAC_RW
+                case T_FILE:
+                case T_FIFO:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_write_only));
+#endif
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_READ_OPEN:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_execute_only | FF_write_only));
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_search_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_MAP_EXEC:
+        case R_EXECUTE:
+            switch(target)
+              {
+                case T_FILE:
+                  return(check_flags_ff(target,tid,
+                                        FF_write_only | FF_no_execute | FF_append_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_APPEND_OPEN:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_READ_WRITE_OPEN:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only
+                                         | FF_write_only | FF_append_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_CHDIR:
+            switch(target)
+              {
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_search_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        /* Creating dir or (pseudo) file IN target dir! */
+        case R_CREATE:
+            switch(target)
+              {
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only));
+
+#if defined(CONFIG_RSBAC_FF_UM_PROT)
+                case T_USER:
+                case T_GROUP:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF,
+                                     T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_ff()", A_ff_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+#endif
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_DELETE:
+        case R_RENAME:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_SYMLINK:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only | FF_no_delete_or_rename
+                                         | FF_append_only));
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only | FF_no_delete_or_rename));
+
+#if defined(CONFIG_RSBAC_FF_UM_PROT)
+                case T_USER:
+                case T_GROUP:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF,
+                                     T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_ff()", A_ff_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+#endif
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_CHANGE_GROUP:
+        case R_MODIFY_PERMISSIONS_DATA:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_SYMLINK:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only | FF_append_only));
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only));
+
+#if defined(CONFIG_RSBAC_FF_UM_PROT)
+                case T_USER:
+                case T_GROUP:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF,
+                                     T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_ff()", A_ff_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+#endif
+
+                /* all other cases are undefined */
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_CHANGE_OWNER:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_SYMLINK:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only | FF_append_only));
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only));
+                /* all other cases are undefined */
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+	case R_SEARCH:
+	    switch(target)
+	    {
+		case T_FILE:
+		case T_DIR:
+		case T_SYMLINK:
+		case T_FIFO:
+		case T_UNIXSOCK:
+			i_tid.user = owner;
+			if ((err = rsbac_get_attr(SW_FF, T_USER,
+							i_tid,
+							A_ff_role,
+							&i_attr_val1, FALSE))) {
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_ff(): rsbac_get_attr() returned error %i!\n",err);
+				return (NOT_GRANTED);
+			}
+			if (i_attr_val1.system_role == (SR_security_officer || SR_auditor))
+					return (GRANTED);
+					else
+		  return(check_flags_ff(target,tid,
+					  FF_no_search));
+		default:
+		  return(DO_NOT_CARE);
+	    }
+
+	case R_LINK_HARD:
+            switch(target)
+              {
+                case T_FILE:
+                case T_UNIXSOCK:
+                case T_FIFO:
+                case T_SYMLINK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_MODIFY_ACCESS_DATA:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_SYMLINK:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only | FF_append_only));
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only));
+
+                /* all other cases are undefined */
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_MODIFY_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_ff_flags:
+                case A_system_role:
+                case A_ff_role:
+                #ifdef CONFIG_RSBAC_FF_AUTH_PROT
+                case A_auth_may_setuid:
+                case A_auth_may_set_cap:
+                case A_auth_start_uid:
+                case A_auth_start_euid:
+                case A_auth_start_gid:
+                case A_auth_start_egid:
+                case A_auth_learn:
+                case A_auth_add_f_cap:
+                case A_auth_remove_f_cap:
+                #endif
+                #ifdef CONFIG_RSBAC_FF_GEN_PROT
+                case A_log_array_low:
+                case A_log_array_high:
+                case A_log_program_based:
+                case A_log_user_based:
+                case A_symlink_add_remote_ip:
+                case A_symlink_add_uid:
+                case A_symlink_add_rc_role:
+                case A_linux_dac_disable:
+                case A_pseudo:
+                case A_fake_root_uid:
+                case A_audit_uid:
+                case A_auid_exempt:
+                case A_remote_ip:
+                case A_vset:
+                case A_program_file:
+                #endif
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF, T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_printk(KERN_WARNING
+                             "rsbac_adf_request_ff(): rsbac_get_attr() returned error!\n");
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_MODIFY_SYSTEM_DATA:
+            switch(target)
+              {
+                case T_SCD:
+                  switch(tid.scd)
+                    {
+                      case ST_rsbac_log:
+                      case ST_rsbac_remote_log:
+                        break;
+                      case ST_kmem:
+                        return NOT_GRANTED;
+                      default:
+                        return GRANTED;
+                    }
+                  /* Get role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF, T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_printk(KERN_WARNING
+                             "rsbac_adf_request_ff(): rsbac_get_attr() returned error!\n");
+                      return(NOT_GRANTED);
+                    }
+                  /* grant only for secoff */
+                  if (   (i_attr_val1.system_role == SR_security_officer)
+                      || (i_attr_val1.system_role == SR_auditor)
+                     )
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_MOUNT:
+        case R_UMOUNT:
+            switch(target)
+              {
+                case T_FILE:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only
+                                         | FF_write_only | FF_append_only | FF_no_mount));
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only | FF_no_mount));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_LOG:
+            switch(target)
+              {
+                case T_NONE:
+                  /* test owner's ff_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF, T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_printk(KERN_WARNING "rsbac_adf_request_ff(): rsbac_get_attr() returned error!\n");
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_MODULE:
+            switch(target)
+              {
+                case T_NONE:
+                  /* we need the switch_target */
+                  if(attr != A_switch_target)
+                    return NOT_GRANTED;
+                  /* do not care for other modules */
+                  if(   (attr_val.switch_target != SW_FF)
+                     #ifdef CONFIG_RSBAC_SOFTMODE
+                     && (attr_val.switch_target != SW_SOFTMODE)
+                     #endif
+                     #ifdef CONFIG_RSBAC_FREEZE
+                     && (attr_val.switch_target != SW_FREEZE)
+                     #endif
+                     #ifdef CONFIG_RSBAC_FF_AUTH_PROT
+                     && (attr_val.switch_target != SW_AUTH)
+                     #endif
+                    )
+                    return(DO_NOT_CARE);
+                  /* test owner's ff_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF, T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_printk(KERN_WARNING "rsbac_adf_request_ff(): rsbac_get_attr() returned error!\n");
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_TRUNCATE:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only | FF_append_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_WRITE_OPEN:
+            switch(target)
+              {
+                case T_FILE:
+                case T_FIFO:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only | FF_append_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_WRITE:
+            switch(target)
+              {
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only));
+
+#ifdef CONFIG_RSBAC_RW
+                case T_FILE:
+                case T_FIFO:
+                case T_UNIXSOCK:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_execute_only));
+#endif
+#if defined(CONFIG_RSBAC_FF_UM_PROT)
+                case T_USER:
+                case T_GROUP:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_FF,
+                                     T_USER,
+                                     i_tid,
+                                     A_ff_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_ff()", A_ff_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+#endif
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_MOVETO:
+            switch(target)
+              {
+                case T_DIR:
+                  return(check_flags_ff(target,tid,
+                                        FF_read_only | FF_search_only));
+
+                /* all other cases are undefined */
+                default: return(DO_NOT_CARE);
+              }
+
+
+/*********************/
+        default: return DO_NOT_CARE;
+      }
+
+    return result;
+  } /* end of rsbac_adf_request_ff() */
+
+
+/******************************************/
+#ifdef CONFIG_RSBAC_SECDEL
+inline rsbac_boolean_t rsbac_need_overwrite_ff(struct dentry * dentry_p)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    if(   !dentry_p
+       || !dentry_p->d_inode)
+      return FALSE;
+
+    i_tid.file.device = dentry_p->d_sb->s_dev;
+    i_tid.file.inode = dentry_p->d_inode->i_ino;
+    i_tid.file.dentry_p = dentry_p;
+    /* get target's file flags */
+    if (rsbac_get_attr(SW_FF, T_FILE,
+                       i_tid,
+                       A_ff_flags,
+                       &i_attr_val1,
+                       TRUE))
+      {
+        rsbac_printk(KERN_WARNING "rsbac_need_overwrite_ff(): rsbac_get_attr() returned error!\n");
+        return FALSE;
+      }
+
+    /* overwrite, if secure_delete is set */
+    if (i_attr_val1.ff_flags & FF_secure_delete)
+      return TRUE;
+    else
+      return FALSE;
+  }
+#endif
+
+/* end of rsbac/adf/ff/main.c */
diff --git a/rsbac/adf/jail/Makefile b/rsbac/adf/jail/Makefile
new file mode 100644
index 0000000..91607dc
--- /dev/null
+++ b/rsbac/adf/jail/Makefile
@@ -0,0 +1,10 @@
+#
+# File: rsbac/adf/jail/Makefile
+#
+# Makefile for the Linux rsbac jail decision module.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+obj-y   := jail_syscalls.o jail_main.o
+
diff --git a/rsbac/adf/jail/jail_main.c b/rsbac/adf/jail/jail_main.c
new file mode 100644
index 0000000..43ed5dd
--- /dev/null
+++ b/rsbac/adf/jail/jail_main.c
@@ -0,0 +1,1444 @@
+/**************************************************** */
+/* Rule Set Based Access Control                      */
+/* Implementation of the Access Control Decision      */
+/* Facility (ADF) - Authorization module              */
+/* File: rsbac/adf/jail/jail_main.c                   */
+/*                                                    */
+/* Author and (c) 1999-2017: Amon Ott <ao@rsbac.org>  */
+/*                                                    */
+/* Last modified: 28/Feb/2017                         */
+/**************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/network.h>
+#include <rsbac/debug.h>
+#include <rsbac/jail.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+static inline rsbac_boolean_t jail_dev_tty(struct rsbac_dev_desc_t dev)
+{
+	if (dev.type != D_char)
+		return FALSE;
+	if (((dev.major >= 2)
+	     && (dev.major <= 4)
+	    )
+	    || ((dev.major >= 128)
+		&& (dev.major <= 143)
+	    )
+	    )
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static rsbac_jail_id_t
+jail_get_id(enum rsbac_target_t target, union rsbac_target_id_t tid)
+{
+	int err;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	if ((err = rsbac_get_attr(SW_JAIL,
+				  target,
+				  tid, A_jail_id, &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_id()", A_jail_id);
+		return 0;
+	} else
+		return i_attr_val1.jail_id;
+}
+
+static rsbac_jail_id_t jail_get_id_process(rsbac_pid_t pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.process = pid;
+	if ((err = rsbac_get_attr(SW_JAIL, T_PROCESS,
+				  i_tid, A_jail_id, &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_id_process()", A_jail_id);
+		return 0;
+	} else
+		return i_attr_val1.jail_id;
+}
+
+static inline rsbac_jail_id_t jail_get_parent_process(rsbac_pid_t pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.process = pid;
+	if ((err = rsbac_get_attr(SW_JAIL, T_PROCESS,
+				  i_tid, A_jail_parent, &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_parent_process()", A_jail_parent);
+		return 0;
+	} else
+		return i_attr_val1.jail_parent;
+}
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+static inline rsbac_jail_ip_t jail_get_ip_process(rsbac_pid_t pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.process = pid;
+	if ((err = rsbac_get_attr(SW_JAIL, T_PROCESS,
+				  i_tid, A_jail_ip, &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_ip_process()", A_jail_ip);
+		return 0;
+	} else
+		return i_attr_val1.jail_ip;
+}
+#endif
+
+static rsbac_jail_flags_t jail_get_flags_process(rsbac_pid_t pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.process = pid;
+	if ((err = rsbac_get_attr(SW_JAIL, T_PROCESS, i_tid,
+				  A_jail_flags, &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_flags_process()",
+				   A_jail_flags);
+		return 0;
+	} else
+		return i_attr_val1.jail_flags;
+}
+
+static inline rsbac_jail_scd_vector_t jail_get_scd_get_process(rsbac_pid_t pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.process = pid;
+	if ((err = rsbac_get_attr(SW_JAIL, T_PROCESS, i_tid,
+				  A_jail_scd_get, &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_scd_get_process()",
+				   A_jail_scd_get);
+		return 0;
+	} else
+		return i_attr_val1.jail_scd_get;
+}
+
+static inline rsbac_jail_scd_vector_t jail_get_scd_modify_process(rsbac_pid_t pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.process = pid;
+	if ((err = rsbac_get_attr(SW_JAIL, T_PROCESS, i_tid,
+				  A_jail_scd_modify,
+				  &i_attr_val1, FALSE))) {
+		rsbac_ds_get_error("jail_get_scd_modify_process()",
+				   A_jail_scd_modify);
+		return 0;
+	} else
+		return i_attr_val1.jail_scd_modify;
+}
+
+static enum rsbac_adf_req_ret_t
+jail_check_sysrole(rsbac_uid_t owner,
+		enum rsbac_system_role_t role)
+{
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.user = owner;
+	if (rsbac_get_attr(SW_JAIL, T_USER, i_tid,
+			   A_jail_role, &i_attr_val1, FALSE)) {
+		rsbac_ds_get_error("jail_check_sysrole()", A_jail_role);
+		return (NOT_GRANTED);
+	}
+	/* if correct role, then grant */
+	if (i_attr_val1.system_role == role)
+		return (GRANTED);
+	else
+		return (NOT_GRANTED);
+}
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+enum rsbac_adf_req_ret_t
+jail_check_ip(rsbac_pid_t pid, union rsbac_target_id_t tid)
+{
+	rsbac_jail_ip_t jail_ip;
+	rsbac_jail_flags_t jail_flags;
+
+	if (!tid.netobj.sock_p) {
+		rsbac_printk(KERN_WARNING
+			     "jail_check_ip(): NULL sock_p!\n");
+		return NOT_GRANTED;
+	}
+	if (!tid.netobj.sock_p->ops) {
+		return DO_NOT_CARE;
+	}
+	switch (tid.netobj.sock_p->ops->family) {
+	case AF_UNIX:
+		return DO_NOT_CARE;
+
+	case AF_INET:
+		switch (tid.netobj.sock_p->type) {
+		case SOCK_STREAM:
+		case SOCK_DGRAM:
+		case SOCK_RDM:
+			jail_ip = jail_get_ip_process(pid);
+			if (jail_ip == INADDR_ANY)
+				return GRANTED;
+			jail_flags = jail_get_flags_process(pid);
+			if (tid.netobj.local_addr) {
+				struct sockaddr_in *addr =
+				    tid.netobj.local_addr;
+
+				if ((jail_ip == addr->sin_addr.s_addr)
+					|| (
+						(jail_flags &
+						JAIL_allow_inet_localhost)
+						&& (addr->sin_addr.s_addr ==
+						RSBAC_JAIL_LOCALHOST)
+					)
+#if defined(CONFIG_RSBAC_JAIL_NET_ADJUST)
+					|| (
+						(jail_flags &
+						JAIL_auto_adjust_inet_any)
+						&& (addr->sin_addr.s_addr ==
+						INADDR_ANY)
+					)
+#endif
+				    )
+					return GRANTED;
+				else {
+					rsbac_pr_debug(adf_jail, "local_addr does not match jail_ip -> NOT_GRANTED!\n");
+					return NOT_GRANTED;
+				}
+			} else if ((tid.netobj.remote_addr)
+				   && (jail_flags &
+				       JAIL_allow_inet_localhost)
+				   &&
+				   (((struct sockaddr_in *) tid.netobj.
+				     remote_addr)->sin_addr.s_addr ==
+				    RSBAC_JAIL_LOCALHOST)
+			    )
+				return GRANTED;
+			else {
+				if (((jail_ip ==
+				      inet_sk(tid.netobj.sock_p->sk)->
+				      inet_rcv_saddr)
+				     && (jail_ip ==
+					 inet_sk(tid.netobj.sock_p->sk)->
+					 inet_saddr)
+				    )
+				    || (
+					    (jail_flags &
+					     JAIL_allow_inet_localhost)
+					    &&
+					    ((inet_sk(tid.netobj.sock_p->sk)->
+					      inet_saddr == RSBAC_JAIL_LOCALHOST)
+				    || (
+					     inet_sk(tid.netobj.sock_p->sk)->
+					     inet_daddr == RSBAC_JAIL_LOCALHOST)
+				     )
+				     )
+#if defined(CONFIG_RSBAC_JAIL_NET_ADJUST)
+				    || (
+					    (jail_flags &
+					     JAIL_auto_adjust_inet_any)
+					    && (inet_sk(tid.netobj.sock_p->sk)->
+						    inet_rcv_saddr == INADDR_ANY)
+					    && (inet_sk(tid.netobj.sock_p->sk)->
+						    inet_saddr == INADDR_ANY)
+				    )
+#endif
+				    )
+					return GRANTED;
+				else {
+					rsbac_pr_debug(adf_jail, "sk->inet_rcv_saddr or sk->inet_saddr does not match jail_ip -> NOT_GRANTED!\n");
+					return NOT_GRANTED;
+				}
+			}
+
+		case SOCK_RAW:
+			if (jail_get_flags_process(pid) &
+			    JAIL_allow_inet_raw)
+				return GRANTED;
+			else {
+				rsbac_pr_debug(adf_jail, "network type is raw  and allow_inet_raw is not set -> NOT_GRANTED!\n");
+				return NOT_GRANTED;
+			}
+
+		default:
+			rsbac_pr_debug(adf_jail, "network type not STREAM, DGRAM, RDM or RAW -> NOT_GRANTED!\n");
+			return NOT_GRANTED;
+		}
+
+	case AF_NETLINK:
+		if (jail_get_flags_process(pid) &
+		    (JAIL_allow_all_net_family | JAIL_allow_netlink))
+			return GRANTED;
+		else {
+			rsbac_pr_debug(adf_jail, "network family is NETLINK and neither allow_netlink nor allow_all_net_family is set -> NOT_GRANTED!\n");
+			return NOT_GRANTED;
+		}
+
+	default:
+		if (jail_get_flags_process(pid) &
+		    JAIL_allow_all_net_family)
+			return GRANTED;
+		else {
+			rsbac_pr_debug(adf_jail, "network family not UNIX or INET and allow_all_net_family not set -> NOT_GRANTED!\n");
+			return NOT_GRANTED;
+		}
+	}
+}
+#endif
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+enum rsbac_adf_req_ret_t
+rsbac_adf_request_jail(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)
+{
+	rsbac_jail_id_t jail_id;
+	rsbac_jail_id_t jail_id2;
+	rsbac_jail_id_t jail_id_object;
+	rsbac_jail_flags_t jail_flags;
+
+	switch(target) {
+	case T_DEV:
+		switch(request) {
+		case R_SEND:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_APPEND_OPEN:
+		case R_WRITE_OPEN:
+			if (jail_get_id_process(caller_pid)) {
+				jail_flags =
+				    jail_get_flags_process(caller_pid);
+				if (!(jail_flags & JAIL_allow_dev_write))
+					return NOT_GRANTED;
+				else if (jail_dev_tty(tid.dev)
+					 && !(jail_flags &
+					      JAIL_allow_tty_open)
+				    )
+					return NOT_GRANTED;
+				else
+					return GRANTED;
+			} else
+				return GRANTED;
+		case R_READ_OPEN:
+			if (jail_get_id_process(caller_pid)) {
+				jail_flags =
+				    jail_get_flags_process(caller_pid);
+				if (!(jail_flags & JAIL_allow_dev_read))
+					return NOT_GRANTED;
+				else if (jail_dev_tty(tid.dev)
+					 && !(jail_flags &
+					      JAIL_allow_tty_open)
+				    )
+					return NOT_GRANTED;
+				else
+					return GRANTED;
+			} else
+				return GRANTED;
+		case R_READ_WRITE_OPEN:
+			if (jail_get_id_process(caller_pid)) {
+				jail_flags =
+				    jail_get_flags_process(caller_pid);
+				if (!(jail_flags & JAIL_allow_dev_read)
+				    || !(jail_flags & JAIL_allow_dev_write)
+				    )
+					return NOT_GRANTED;
+				else if (jail_dev_tty(tid.dev)
+					 && !(jail_flags &
+					      JAIL_allow_tty_open)
+				    )
+					return NOT_GRANTED;
+				else
+					return GRANTED;
+			} else
+				return GRANTED;
+		case R_GET_STATUS_DATA:
+			if (jail_get_id_process(caller_pid)
+			    && !(jail_get_flags_process(caller_pid) &
+				 JAIL_allow_dev_get_status)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_MODIFY_SYSTEM_DATA:
+			if (jail_get_id_process(caller_pid)
+			    && !(jail_get_flags_process(caller_pid) &
+				 JAIL_allow_dev_mod_system)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_READ:
+			if (jail_get_id_process(caller_pid)
+			    && !(jail_get_flags_process(caller_pid) &
+				 JAIL_allow_dev_read)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_WRITE:
+			if (jail_get_id_process(caller_pid)
+			    && !(jail_get_flags_process(caller_pid) &
+				 JAIL_allow_dev_write)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_DIR:
+		switch(request) {
+		case R_CREATE:
+			if (!jail_get_id_process(caller_pid))
+				return GRANTED;
+			/* no mknod for devices or suid/sgid */
+			if ((attr == A_create_data)
+			    && (S_ISCHR(attr_val.create_data.mode)
+				|| S_ISBLK(attr_val.create_data.mode)
+				|| ((attr_val.create_data.mode & (S_ISUID | S_ISGID))
+				    && !(jail_get_flags_process(caller_pid) & JAIL_allow_suid_files)
+				   )
+			    )
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_MODIFY_PERMISSIONS_DATA:
+			if (jail_get_id_process(caller_pid)
+			    && (attr == A_mode)
+			    && (attr_val.mode & (S_ISUID | S_ISGID))
+			    && !(jail_get_flags_process(caller_pid) & JAIL_allow_suid_files)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_FILE:
+		switch(request) {
+		case R_ADD_TO_KERNEL:
+		case R_REMOVE_FROM_KERNEL:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_MOUNT:
+		case R_UMOUNT:
+			if (!jail_get_id_process(caller_pid)
+			    || (jail_get_flags_process(caller_pid) & JAIL_allow_mount)
+			   )
+				return GRANTED;
+			else
+				return NOT_GRANTED;
+		case R_MODIFY_PERMISSIONS_DATA:
+			if (jail_get_id_process(caller_pid)
+			    && (attr == A_mode)
+			    && (attr_val.mode & (S_ISUID | S_ISGID))
+			    && !(jail_get_flags_process(caller_pid) & JAIL_allow_suid_files)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_PROCESS:
+		switch(request) {
+		case R_GET_STATUS_DATA:
+		case R_MODIFY_SYSTEM_DATA:
+		case R_TRACE:
+			jail_id = jail_get_id_process(caller_pid);
+			if (!jail_id
+			    || (jail_id == jail_get_id(target, tid))
+			    )
+				return GRANTED;
+			else
+				return NOT_GRANTED;
+		case R_SEND_SIGNAL:
+			jail_id = jail_get_id_process(caller_pid);
+			if (!jail_id)
+				return GRANTED;
+			jail_id2 = jail_get_id(target, tid);
+			if (jail_id == jail_id2)
+				return GRANTED;
+			if (!jail_id2 && (attr == A_signal) && (attr_val.signal == SIGCHLD))
+				return DO_NOT_CARE;
+			return NOT_GRANTED;
+		case R_MODIFY_ATTRIBUTE:
+			switch (attr) {
+			case A_jail_id:
+			case A_jail_ip:
+	 		case A_jail_flags:
+			case A_jail_max_caps:
+			case A_jail_parent:
+			case A_jail_scd_get:
+			case A_jail_scd_modify:
+			/* All attributes (remove target!) */
+			case A_none:
+				if (jail_get_id_process(caller_pid))
+					return NOT_GRANTED;
+
+				/* Security Officer? */
+				return jail_check_sysrole(owner,
+							  SR_security_officer);
+			default:
+				return DO_NOT_CARE;
+			}
+		case R_READ_ATTRIBUTE:
+			switch (attr) {
+			case A_jail_id:
+			case A_jail_ip:
+	 		case A_jail_flags:
+			case A_jail_max_caps:
+			case A_jail_parent:
+			case A_jail_scd_get:
+			case A_jail_scd_modify:
+			/* All attributes (remove target!) */
+			case A_none:
+				if (jail_get_id_process(caller_pid))
+					return NOT_GRANTED;
+
+				/* Security Officer? */
+				if (jail_check_sysrole(owner, SR_administrator) ==
+				    NOT_GRANTED)
+					return jail_check_sysrole(owner,
+								  SR_security_officer);
+				else
+					return GRANTED;
+			default:
+				return (DO_NOT_CARE);
+			}
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_UNIXSOCK:
+		switch(request) {
+		case R_SEND:
+		case R_CONNECT:
+		case R_LISTEN:
+		case R_ACCEPT:
+		case R_RECEIVE:
+#ifdef CONFIG_RSBAC_RW
+		case R_READ:
+		case R_WRITE:
+#endif
+		case R_BIND:
+			jail_id = jail_get_id_process(caller_pid);
+			if (!jail_id)
+				return GRANTED;
+			if (attr == A_process) {
+				union rsbac_target_id_t i_tid;
+				rsbac_jail_id_t jail_id_parent;
+
+				i_tid.process = attr_val.process;
+				jail_id_parent = jail_get_parent_process(caller_pid);
+				if((jail_id != (jail_id_object = jail_get_id(T_PROCESS, i_tid)))
+				   && !((jail_flags = jail_get_flags_process(caller_pid)) & JAIL_allow_external_ipc)
+				   && (!(jail_flags & JAIL_allow_parent_ipc)
+					|| (jail_id_object != jail_id_parent)
+				      )
+				   && (!(jail_flags & JAIL_allow_ipc_to_syslog)
+					|| (jail_id_object != rsbac_jail_syslog_jail_id)
+				      )
+				   && (!(jail_get_flags_process(attr_val.process) & JAIL_allow_parent_ipc)
+					|| (jail_get_parent_process(attr_val.process) != jail_id)
+				      )
+				  ) {
+					if (rsbac_log_levels[request][target] != LL_none) {
+						rsbac_pr_debug(adf_jail,
+							"process jail %u does not match partner process jail %u, parent jail is %u -> NOT_GRANTED!\n",
+							jail_id, jail_id_object, jail_id_parent);
+					}
+					return NOT_GRANTED;
+				}
+			} else {
+				if(!(jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)) {
+					if (rsbac_log_levels[request][target] != LL_none) {
+						rsbac_pr_debug(adf_jail,
+							"process jail is %u, no allow_ipc and partner process unknown -> NOT_GRANTED!\n",
+							jail_id);
+					}
+					return NOT_GRANTED;
+				}
+			}
+			return GRANTED;
+		default:
+			return DO_NOT_CARE;
+		}
+#ifdef CONFIG_RSBAC_NET_OBJ
+	case T_NETOBJ:
+		switch(request) {
+		case R_SEND:
+		case R_RECEIVE:
+		case R_CONNECT:
+		case R_LISTEN:
+		case R_ACCEPT:
+		case R_GET_PERMISSIONS_DATA:
+		case R_MODIFY_PERMISSIONS_DATA:
+		case R_GET_STATUS_DATA:
+		case R_READ:
+		case R_WRITE:
+		case R_BIND:
+			if (!jail_get_id_process(caller_pid))
+				return GRANTED;
+			return (jail_check_ip(caller_pid, tid));
+		case R_CREATE:
+			if (!jail_get_id_process(caller_pid))
+				return GRANTED;
+			if (!tid.netobj.sock_p) {
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_jail(): NULL sock_p on CREATE!\n");
+				return NOT_GRANTED;
+			}
+			if (!tid.netobj.sock_p->ops) {
+				return DO_NOT_CARE;
+			}
+			switch (tid.netobj.sock_p->ops->family) {
+			case AF_UNIX:
+				return (GRANTED);
+
+			case AF_INET:
+				switch (tid.netobj.sock_p->type) {
+				case SOCK_STREAM:
+				case SOCK_DGRAM:
+				case SOCK_RDM:
+					if (tid.netobj.sock_p->sk
+					    && (tid.netobj.sock_p->sk->
+						sk_protocol == IPPROTO_RAW)
+					    ) {
+						jail_flags =
+						    jail_get_flags_process
+						    (caller_pid);
+						if (jail_flags &
+						    JAIL_allow_inet_raw)
+							return (GRANTED);
+						else
+							return NOT_GRANTED;
+					} else
+						return GRANTED;
+
+				case SOCK_RAW:
+					jail_flags =
+					    jail_get_flags_process
+					    (caller_pid);
+					if (jail_flags &
+					    JAIL_allow_inet_raw)
+						return (GRANTED);
+					else
+						return NOT_GRANTED;
+
+				default:
+					return (NOT_GRANTED);
+				}
+
+			case AF_NETLINK:
+				jail_flags = jail_get_flags_process(caller_pid);
+				if (jail_flags &
+				    (JAIL_allow_all_net_family | JAIL_allow_netlink))
+					return GRANTED;
+				else {
+					if (rsbac_log_levels[request][target] != LL_none) {
+						rsbac_pr_debug(adf_jail, "network family is NETLINK and neither allow_netlink nor allow_all_net_family is set -> NOT_GRANTED!\n");
+					}
+					return NOT_GRANTED;
+				}
+			default:
+				jail_flags = jail_get_flags_process(caller_pid);
+				if (jail_flags & JAIL_allow_all_net_family)
+					return GRANTED;
+				else
+					return NOT_GRANTED;
+			}
+		default:
+			return DO_NOT_CARE;
+		}
+#endif				/* NET_OBJ */
+	case T_IPC:
+		switch(request) {
+		case R_ALTER:
+		case R_APPEND_OPEN:
+		case R_WRITE_OPEN:
+		case R_READ_OPEN:
+		case R_READ_WRITE_OPEN:
+		case R_DELETE:
+		case R_MODIFY_PERMISSIONS_DATA:
+		case R_GET_STATUS_DATA:
+			jail_id = jail_get_id_process(caller_pid);
+			if (!jail_id
+			    || (jail_id == (jail_id_object = jail_get_id(target, tid)))
+			    || ((jail_flags = jail_get_flags_process(caller_pid)) &
+				JAIL_allow_external_ipc)
+			    || ((jail_flags & JAIL_allow_parent_ipc)
+			    	&& (jail_get_parent_process(caller_pid) == jail_id_object)
+			    	)
+			    || ((jail_flags & JAIL_allow_ipc_to_syslog)
+			    	&& (rsbac_jail_syslog_jail_id == jail_id_object)
+			    	)
+			    )
+				return GRANTED;
+			else {
+				if (rsbac_log_levels[request][target] != LL_none) {
+					rsbac_pr_debug(adf_jail,
+						"process jail %u does not match IPC object jail %u -> NOT_GRANTED!\n",
+						jail_id, jail_id_object);
+				}
+				return NOT_GRANTED;
+			}
+		case R_CREATE:
+			return GRANTED;
+		case R_MODIFY_ATTRIBUTE:
+			switch (attr) {
+			case A_jail_id:
+			/* All attributes (remove target!) */
+			case A_none:
+				if (jail_get_id_process(caller_pid))
+					return NOT_GRANTED;
+
+				/* Security Officer? */
+				return jail_check_sysrole(owner,
+							  SR_security_officer);
+			default:
+				return DO_NOT_CARE;
+			}
+		case R_READ_ATTRIBUTE:
+			switch (attr) {
+			case A_jail_id:
+			/* All attributes (remove target!) */
+			case A_none:
+				if (jail_get_id_process(caller_pid))
+					return NOT_GRANTED;
+
+				/* Security Officer? */
+				if (jail_check_sysrole(owner, SR_administrator) ==
+				    NOT_GRANTED)
+					return jail_check_sysrole(owner,
+								  SR_security_officer);
+				else
+					return GRANTED;
+			default:
+				return (DO_NOT_CARE);
+			}
+		default:
+			jail_id = jail_get_id_process(caller_pid);
+			if (!jail_id)
+				return GRANTED;
+			if((jail_flags = jail_get_flags_process(caller_pid)) &
+					JAIL_allow_external_ipc)
+				return GRANTED;
+			jail_id_object = jail_get_id(target, tid);
+			if((jail_flags & JAIL_allow_parent_ipc)
+			   && (jail_get_parent_process(caller_pid) == jail_id_object))
+				return GRANTED;
+			if((attr == A_process)
+				&& (jail_get_flags_process(attr_val.process) & JAIL_allow_parent_ipc)
+				&& (jail_get_parent_process(attr_val.process) == jail_id))
+				return GRANTED;
+			if((jail_flags & JAIL_allow_ipc_to_syslog)
+			   && (rsbac_jail_syslog_jail_id == jail_id_object))
+				return GRANTED;
+			if(jail_id != jail_id_object) {
+				if (rsbac_log_levels[request][target] != LL_none) {
+					rsbac_pr_debug(adf_jail,
+						"process jail %u does not match IPC object jail %u -> NOT_GRANTED!\n",
+						jail_id, jail_id_object);
+				}
+				return NOT_GRANTED;
+			}
+			if (attr == A_process) {
+				union rsbac_target_id_t i_tid;
+				rsbac_jail_id_t jail_id_parent;
+
+				i_tid.process = attr_val.process;
+				jail_id_parent = jail_get_parent_process(caller_pid);
+				if((jail_id != (jail_id_object = jail_get_id(T_PROCESS, i_tid)))
+				   && !(jail_flags & JAIL_allow_external_ipc)
+				   && (!(jail_flags & JAIL_allow_parent_ipc)
+					|| (jail_id_object != jail_id_parent)
+				      )
+				  ) {
+					if (rsbac_log_levels[request][target] != LL_none) {
+						rsbac_pr_debug(adf_jail,
+							"process jail %u does not match partner process jail %u, parent jail is %u -> NOT_GRANTED!\n",
+							jail_id, jail_id_object, jail_id_parent);
+					}
+					return NOT_GRANTED;
+				}
+			}
+			return GRANTED;
+		}
+	case T_FIFO:
+	case T_SYMLINK:
+		switch(request) {
+		case R_MODIFY_PERMISSIONS_DATA:
+			if (jail_get_id_process(caller_pid)
+			    && (attr == A_mode)
+			    && (attr_val.mode & (S_ISUID | S_ISGID))
+			    && !(jail_get_flags_process(caller_pid) & JAIL_allow_suid_files)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_SCD:
+		switch(request) {
+		case R_MODIFY_PERMISSIONS_DATA:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_GET_STATUS_DATA:
+			if (jail_get_id_process(caller_pid)) {
+				if (jail_get_scd_get_process(caller_pid) &
+				    RSBAC_SCD_VECTOR(tid.scd))
+					return GRANTED;
+				else
+					return NOT_GRANTED;
+			} else
+				return GRANTED;
+		case R_MODIFY_SYSTEM_DATA:
+			if (jail_get_id_process(caller_pid)) {
+				if (jail_get_scd_modify_process(caller_pid)
+				    & RSBAC_SCD_VECTOR(tid.scd))
+					return (GRANTED);
+				else
+					return NOT_GRANTED;
+			} else
+				return GRANTED;
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_NONE:
+		switch(request) {
+		case R_ADD_TO_KERNEL:
+		case R_REMOVE_FROM_KERNEL:
+		case R_SHUTDOWN:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+		case R_SWITCH_LOG:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			/* test owner's fc_role */
+			return jail_check_sysrole(owner,
+						  SR_security_officer);
+		case R_SWITCH_MODULE:
+			/* we need the switch_target */
+			if (attr != A_switch_target)
+				return NOT_GRANTED;
+			/* do not care for other modules */
+			if ((attr_val.switch_target != SW_JAIL)
+#ifdef CONFIG_RSBAC_SOFTMODE
+			    && (attr_val.switch_target != SW_SOFTMODE)
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+			    && (attr_val.switch_target != SW_FREEZE)
+#endif
+			    )
+				return (DO_NOT_CARE);
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			/* test owner's fc_role */
+			return jail_check_sysrole(owner,
+						  SR_security_officer);
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+		/* switching Linux DAC */
+		case R_MODIFY_PERMISSIONS_DATA:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+		default:
+			return DO_NOT_CARE;
+		}
+	case T_NETDEV:
+		switch(request) {
+#ifdef CONFIG_RSBAC_JAIL_NET_DEV_PROT
+		case R_MODIFY_SYSTEM_DATA:
+			if (jail_get_id_process(caller_pid)) {
+				if(jail_get_flags_process(caller_pid) &	JAIL_allow_netdev_mod_system)
+					return GRANTED;
+				else
+					return NOT_GRANTED;
+			} else
+				return GRANTED;
+		case R_BIND:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+		default:
+			return DO_NOT_CARE;
+		}
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	case T_NETTEMP:
+		switch(request) {
+		case R_CREATE:
+		case R_DELETE:
+		case R_WRITE:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			return jail_check_sysrole(owner, SR_security_officer);
+		case R_READ:
+			if (jail_get_id_process(caller_pid))
+				return NOT_GRANTED;
+			if (jail_check_sysrole(owner, SR_security_officer)
+			    == GRANTED)
+				return GRANTED;
+			return jail_check_sysrole(owner, SR_administrator);
+		default:
+			return DO_NOT_CARE;
+		}
+#endif
+
+	case T_USER:
+		switch(request) {
+		case R_MODIFY_ATTRIBUTE:
+			switch (attr) {
+			case A_system_role:
+			case A_jail_role:
+			/* All attributes (remove target!) */
+			case A_none:
+				if (jail_get_id_process(caller_pid))
+					return NOT_GRANTED;
+
+				/* Security Officer? */
+				return jail_check_sysrole(owner,
+							  SR_security_officer);
+			default:
+				return DO_NOT_CARE;
+			}
+		case R_READ_ATTRIBUTE:
+			switch (attr) {
+			case A_system_role:
+			case A_jail_role:
+			/* All attributes (remove target!) */
+			case A_none:
+				if (jail_get_id_process(caller_pid))
+					return NOT_GRANTED;
+
+				/* Security Officer? */
+				if (jail_check_sysrole(owner, SR_administrator) ==
+				    NOT_GRANTED)
+					return jail_check_sysrole(owner,
+								  SR_security_officer);
+				else
+					return GRANTED;
+			default:
+				return (DO_NOT_CARE);
+			}
+		default:
+			return DO_NOT_CARE;
+		}
+
+	/* all other cases are unknown */
+	default:
+		return DO_NOT_CARE;
+	}
+}
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up.                                                              */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+int rsbac_adf_set_attr_jail(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)
+{
+#ifdef CONFIG_RSBAC_JAIL_NET_ADJUST
+	int err;
+#endif
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_attribute_value_t i_attr_val2;
+
+	switch (request) {
+	case R_CHANGE_OWNER:
+		switch (target) {
+		case T_PROCESS:
+			/* Adjust Linux caps */
+			i_tid.process = caller_pid;
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+			{
+				if (rsbac_get_attr(SW_JAIL,
+						   T_PROCESS,
+						   i_tid,
+						   A_jail_max_caps,
+						   &i_attr_val1, FALSE)) {
+					rsbac_ds_get_error
+					    ("rsbac_adf_set_attr_jail()",
+					     A_jail_max_caps);
+				} else {
+					struct cred *override_cred;
+
+					override_cred = prepare_creds();
+					if (!override_cred)
+						return -ENOMEM;
+					if (   ((override_cred->cap_permitted.cap[0] & i_attr_val1.jail_max_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+					    || ((override_cred->cap_effective.cap[0] & i_attr_val1.jail_max_caps.cap[0]) != override_cred->cap_effective.cap[0])
+					    || ((override_cred->cap_inheritable.cap[0] & i_attr_val1.jail_max_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+					    || ((override_cred->cap_permitted.cap[1] & i_attr_val1.jail_max_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+					    || ((override_cred->cap_effective.cap[1] & i_attr_val1.jail_max_caps.cap[1]) != override_cred->cap_effective.cap[1])
+					    || ((override_cred->cap_inheritable.cap[1] & i_attr_val1.jail_max_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+					   ) {
+						override_cred->cap_permitted.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+						override_cred->cap_effective.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+						override_cred->cap_inheritable.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+						override_cred->cap_permitted.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+						override_cred->cap_effective.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+						override_cred->cap_inheritable.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+						commit_creds(override_cred);
+					} else {
+						abort_creds(override_cred);
+					}
+				}
+			}
+			return 0;
+
+		/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_CLONE:
+		if (target == T_PROCESS) {
+			union rsbac_attribute_value_t i_attr_val3;
+			union rsbac_attribute_value_t i_attr_val4;
+			union rsbac_attribute_value_t i_attr_val5;
+			union rsbac_attribute_value_t i_attr_val6;
+
+			/* Get jail_id from first process */
+			if (rsbac_get_attr(SW_JAIL,
+					   T_PROCESS,
+					   tid,
+					   A_jail_id,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_id);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Do not copy anything, if not jailed - defaults are fine */
+			if(!i_attr_val1.jail_id)
+			  return 0;
+			/* Get jail_ip from first process */
+			if (rsbac_get_attr(SW_JAIL,
+					   T_PROCESS,
+					   tid,
+					   A_jail_ip,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_ip);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get jail_flags from first process */
+			if (rsbac_get_attr(SW_JAIL,
+					   T_PROCESS,
+					   tid,
+					   A_jail_flags,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_flags);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get jail_max_caps from first process */
+			if (rsbac_get_attr(SW_JAIL,
+					   T_PROCESS,
+					   tid,
+					   A_jail_max_caps,
+					   &i_attr_val4, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_max_caps);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get jail_scd_get from first process */
+			if (rsbac_get_attr(SW_JAIL,
+					   T_PROCESS,
+					   tid,
+					   A_jail_scd_get,
+					   &i_attr_val5, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_scd_get);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get jail_scd_modify from first process */
+			if (rsbac_get_attr(SW_JAIL,
+					   T_PROCESS,
+					   tid,
+					   A_jail_scd_modify,
+					   &i_attr_val6, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_scd_modify);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set jail_id for new process */
+			if (i_attr_val1.jail_id && rsbac_set_attr(SW_JAIL,
+					   T_PROCESS,
+					   new_tid,
+					   A_jail_id, i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_id);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set jail_ip for new process */
+			if (i_attr_val2.jail_ip && rsbac_set_attr(SW_JAIL,
+					   T_PROCESS,
+					   new_tid,
+					   A_jail_ip, i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_ip);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set jail_flags for new process */
+			if (i_attr_val3.jail_flags && rsbac_set_attr(SW_JAIL,
+					   T_PROCESS,
+					   new_tid,
+					   A_jail_flags, i_attr_val3)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_flags);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set jail_max_caps for new process */
+			if (rsbac_set_attr(SW_JAIL,
+					   T_PROCESS,
+					   new_tid,
+					   A_jail_max_caps, i_attr_val4)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_max_caps);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set jail_scd_get for new process */
+			if (i_attr_val5.jail_scd_get && rsbac_set_attr(SW_JAIL,
+					   T_PROCESS,
+					   new_tid,
+					   A_jail_scd_get, i_attr_val5)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_scd_get);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set jail_scd_modify for new process */
+			if (i_attr_val6.jail_scd_modify && rsbac_set_attr(SW_JAIL,
+					   T_PROCESS,
+					   new_tid,
+					   A_jail_scd_modify,
+					   i_attr_val6)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_jail()",
+				     A_jail_scd_modify);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			return 0;
+		} else
+			return 0;
+
+	case R_EXECUTE:
+		switch (target) {
+		case T_FILE:
+			/* Adjust Linux caps */
+			i_tid.process = caller_pid;
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+			{
+				if (rsbac_get_attr(SW_JAIL,
+						   T_PROCESS,
+						   i_tid,
+						   A_jail_max_caps,
+						   &i_attr_val1, FALSE)) {
+					rsbac_ds_get_error
+					    ("rsbac_adf_set_attr_jail()",
+					     A_jail_max_caps);
+				} else {
+					struct cred *override_cred;
+
+					override_cred = prepare_creds();
+					if (!override_cred)
+						return -ENOMEM;
+					if (   ((override_cred->cap_permitted.cap[0] & i_attr_val1.jail_max_caps.cap[0]) != override_cred->cap_permitted.cap[0])
+					    || ((override_cred->cap_effective.cap[0] & i_attr_val1.jail_max_caps.cap[0]) != override_cred->cap_effective.cap[0])
+					    || ((override_cred->cap_inheritable.cap[0] & i_attr_val1.jail_max_caps.cap[0]) != override_cred->cap_inheritable.cap[0])
+					    || ((override_cred->cap_permitted.cap[1] & i_attr_val1.jail_max_caps.cap[1]) != override_cred->cap_permitted.cap[1])
+					    || ((override_cred->cap_effective.cap[1] & i_attr_val1.jail_max_caps.cap[1]) != override_cred->cap_effective.cap[1])
+					    || ((override_cred->cap_inheritable.cap[1] & i_attr_val1.jail_max_caps.cap[1]) != override_cred->cap_inheritable.cap[1])
+					   ) {
+						override_cred->cap_permitted.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+						override_cred->cap_effective.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+						override_cred->cap_inheritable.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+						override_cred->cap_permitted.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+						override_cred->cap_effective.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+						override_cred->cap_inheritable.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+						commit_creds(override_cred);
+					} else {
+						abort_creds(override_cred);
+					}
+				}
+			}
+			return 0;
+
+		/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_CREATE:
+		switch (target) {
+			case T_IPC:
+				/* Get jail_id from process */
+				i_tid.process = caller_pid;
+				if (rsbac_get_attr(SW_JAIL,
+						   T_PROCESS,
+						   i_tid,
+						   A_jail_id,
+						   &i_attr_val1, FALSE)) {
+					rsbac_ds_get_error
+					    ("rsbac_adf_set_attr_jail()",
+					     A_jail_id);
+					return -RSBAC_EREADFAILED;
+				}
+				if (i_attr_val1.jail_id) {
+					/* Set jail_id for new IPC */
+					if (rsbac_set_attr(SW_JAIL,
+							   T_IPC,
+							   tid, A_jail_id, i_attr_val1)) {
+						rsbac_ds_set_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_id);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+				return 0;
+
+#ifdef CONFIG_RSBAC_JAIL_NET_ADJUST
+			case T_NETOBJ:
+				if (!tid.netobj.sock_p) {
+					rsbac_printk(KERN_WARNING
+						     "rsbac_adf_set_attr_jail(): NULL sock_p!\n");
+					return 0;
+				}
+				if (!tid.netobj.sock_p->ops) {
+					return 0;
+				}
+				switch (tid.netobj.sock_p->ops->family) {
+				case AF_INET:
+					i_tid.process = caller_pid;
+					if ((err = rsbac_get_attr(SW_JAIL,
+								  T_PROCESS,
+								  i_tid,
+								  A_jail_ip,
+								  &i_attr_val1, FALSE))) {
+						rsbac_ds_get_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_ip);
+						return -RSBAC_EREADFAILED;
+					}
+					if (i_attr_val1.jail_ip == INADDR_ANY)
+						return 0;
+					if ((err = rsbac_get_attr(SW_JAIL,
+								  T_PROCESS,
+								  i_tid,
+								  A_jail_flags,
+								  &i_attr_val2, FALSE))) {
+						rsbac_ds_get_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_flags);
+						return -RSBAC_EREADFAILED;
+					}
+					if (i_attr_val2.
+					    jail_flags & JAIL_auto_adjust_inet_any) {
+						inet_sk(tid.netobj.sock_p->sk)->inet_rcv_saddr =
+						    i_attr_val1.jail_ip;
+						inet_sk(tid.netobj.sock_p->sk)->inet_saddr =
+						    i_attr_val1.jail_ip;
+					}
+					return 0;
+
+				default:
+					break;
+				}
+#endif
+
+			default:
+				return 0;
+		}
+
+	case R_BIND:
+		switch (target) {
+			case T_IPC:
+				/* Get jail_id from process */
+				i_tid.process = caller_pid;
+				if (rsbac_get_attr(SW_JAIL,
+						   T_PROCESS,
+						   i_tid,
+						   A_jail_id,
+						   &i_attr_val1, FALSE)) {
+					rsbac_ds_get_error
+					    ("rsbac_adf_set_attr_jail()",
+					     A_jail_id);
+					return -RSBAC_EREADFAILED;
+				}
+				if (i_attr_val1.jail_id) {
+					/* Set jail_id for new IPC */
+					if (rsbac_set_attr(SW_JAIL,
+							   T_IPC,
+							   tid, A_jail_id, i_attr_val1)) {
+						rsbac_ds_set_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_id);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+				return 0;
+
+#ifdef CONFIG_RSBAC_JAIL_NET_ADJUST
+			case T_NETOBJ:
+				if (!tid.netobj.sock_p) {
+					rsbac_printk(KERN_WARNING
+						     "rsbac_adf_set_attr_jail(): NULL sock_p!\n");
+					return 0;
+				}
+				if (!tid.netobj.sock_p->ops) {
+					return 0;
+				}
+				switch (tid.netobj.sock_p->ops->family) {
+				case AF_INET:
+					i_tid.process = caller_pid;
+					if ((err = rsbac_get_attr(SW_JAIL,
+								  T_PROCESS,
+								  i_tid,
+								  A_jail_ip,
+								  &i_attr_val1, FALSE))) {
+						rsbac_ds_get_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_ip);
+						return -RSBAC_EREADFAILED;
+					}
+					if (i_attr_val1.jail_ip == INADDR_ANY)
+						return 0;
+					if ((err = rsbac_get_attr(SW_JAIL,
+								  T_PROCESS,
+								  i_tid,
+								  A_jail_flags,
+								  &i_attr_val2, FALSE))) {
+						rsbac_ds_get_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_flags);
+						return -RSBAC_EREADFAILED;
+					}
+					if (i_attr_val2.
+					    jail_flags & JAIL_auto_adjust_inet_any) {
+						inet_sk(tid.netobj.sock_p->sk)->inet_rcv_saddr =
+						    i_attr_val1.jail_ip;
+						inet_sk(tid.netobj.sock_p->sk)->inet_saddr =
+						    i_attr_val1.jail_ip;
+					}
+					return 0;
+
+				default:
+					break;
+				}
+#endif
+			default:
+				return 0;
+		}
+
+	case R_CONNECT:
+		switch (target) {
+			case T_IPC:
+				if (new_target != T_IPC)
+					return 0;
+				/* Get jail_id from old IPC */
+				i_tid.process = caller_pid;
+				if (rsbac_get_attr(SW_JAIL,
+						   T_IPC,
+						   tid,
+						   A_jail_id,
+						   &i_attr_val1, FALSE)) {
+					rsbac_ds_get_error
+					    ("rsbac_adf_set_attr_jail()",
+					     A_jail_id);
+					return -RSBAC_EREADFAILED;
+				}
+				if (i_attr_val1.jail_id) {
+					/* Set jail_id for new IPC */
+					if (rsbac_set_attr(SW_JAIL,
+							   T_IPC,
+							   new_tid, A_jail_id, i_attr_val1)) {
+						rsbac_ds_set_error
+						    ("rsbac_adf_set_attr_jail()",
+						     A_jail_id);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+				return 0;
+
+			default:
+				return 0;
+		}
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
diff --git a/rsbac/adf/jail/jail_syscalls.c b/rsbac/adf/jail/jail_syscalls.c
new file mode 100644
index 0000000..00a808d
--- /dev/null
+++ b/rsbac/adf/jail/jail_syscalls.c
@@ -0,0 +1,301 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - JAIL module                      */
+/* File: rsbac/adf/jail/syscalls.c                   */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/version.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/error.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/debug.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/network.h>
+#include <rsbac/jail.h>
+#include <asm/uaccess.h>
+
+static rsbac_jail_id_t next_id = 1;
+
+/* Create a jail for current process */
+/* Note: It is allowed to create jails within jails, but with restrictions */
+int rsbac_jail_sys_jail(rsbac_version_t version,
+		char __user * path,
+		rsbac_jail_ip_t ip,
+		rsbac_jail_flags_t flags,
+		rsbac_cap_vector_t max_caps,
+		rsbac_jail_scd_vector_t scd_get,
+		rsbac_jail_scd_vector_t scd_modify)
+{
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	int err = 0;
+	rsbac_jail_id_t parent = 0;
+#ifdef CONFIG_RSBAC_NET
+	int chk_addr_ret;
+#endif
+
+	if(version != RSBAC_JAIL_VERSION)
+		return -RSBAC_EINVALIDVERSION;
+
+#ifdef CONFIG_RSBAC_NET
+	chk_addr_ret = inet_addr_type(&init_net, ip);
+	if (ip != INADDR_ANY &&
+			chk_addr_ret != RTN_LOCAL &&
+			chk_addr_ret != RTN_MULTICAST &&
+			chk_addr_ret != RTN_BROADCAST)
+		return -EADDRNOTAVAIL;
+#endif
+
+	/* Get jail_id for this process */
+	i_tid.process = task_pid(current);
+	if (rsbac_get_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_id,
+				&i_attr_val1,
+				FALSE))
+	{
+		rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_id);
+		return(-RSBAC_EREADFAILED);
+	}
+
+	if (i_attr_val1.jail_id)
+	{ /* this process is already in a jail -> limit ip and flags */
+		parent = i_attr_val1.jail_id;
+		if (rsbac_get_attr(SW_JAIL,
+					T_PROCESS,
+					i_tid,
+					A_jail_flags,
+					&i_attr_val1,
+					FALSE))
+		{
+			rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_flags);
+			return(-RSBAC_EREADFAILED);
+		}
+
+		flags &= i_attr_val1.jail_flags | JAIL_allow_parent_ipc;
+		if (rsbac_get_attr(SW_JAIL,
+					T_PROCESS,
+					i_tid,
+					A_jail_scd_get,
+					&i_attr_val1,
+					FALSE))
+		{
+			rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_scd_get);
+			return(-RSBAC_EREADFAILED);
+		}
+
+		scd_get &= i_attr_val1.jail_scd_get;
+		if (rsbac_get_attr(SW_JAIL,
+					T_PROCESS,
+					i_tid,
+					A_jail_scd_modify,
+					&i_attr_val1,
+					FALSE))
+		{
+			rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_scd_modify);
+			return(-RSBAC_EREADFAILED);
+		}
+
+		scd_modify &= i_attr_val1.jail_scd_modify;
+		if (rsbac_get_attr(SW_JAIL,
+					T_PROCESS,
+					i_tid,
+					A_jail_ip,
+					&i_attr_val1,
+					FALSE))
+		{
+			rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_ip);
+			return(-RSBAC_EREADFAILED);
+		}
+
+		if(i_attr_val1.jail_ip)
+			ip = i_attr_val1.jail_ip;
+
+		if (rsbac_get_attr(SW_JAIL,
+					T_PROCESS,
+					i_tid,
+					A_jail_max_caps,
+					&i_attr_val1,
+					FALSE))
+		{
+			rsbac_ds_get_error("rsbac_jail_sys_jail()", A_jail_max_caps);
+			return(-RSBAC_EREADFAILED);
+		}
+
+		max_caps.cap[0] &= i_attr_val1.jail_max_caps.cap[0];
+		max_caps.cap[1] &= i_attr_val1.jail_max_caps.cap[1];
+	}
+
+	/* check syslog id */
+	if(flags & JAIL_this_is_syslog) {
+		if(   rsbac_jail_syslog_jail_id
+				&& rsbac_jail_exists(rsbac_jail_syslog_jail_id)
+		  )
+			return -RSBAC_EEXISTS;
+	}
+
+	if(path)
+	{
+		mm_segment_t oldfs;
+		struct file * file;
+		struct files_struct *files = current->files;
+		struct fdtable *fdt;
+		int fd;
+
+		err = sys_chroot(path);
+		if(err)
+			return err;
+		/* Set current user space to kernel space, because sys_chdir() takes name */
+		/* from user space */
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+		err = sys_chdir("/");
+		/* Set current user space back to user space */
+		set_fs(oldfs);
+
+restart:
+		rcu_read_lock();
+		fdt = files_fdtable(files);
+		fdt = rcu_dereference((files)->fdt);
+
+		for(fd=0; fd < fdt->max_fds; fd++)
+		{
+			file = fcheck(fd);
+			if(   file
+					&& file->f_path.dentry
+					&& file->f_path.dentry->d_inode
+					&& S_ISDIR(file->f_path.dentry->d_inode->i_mode)
+			  )
+			{
+				char * filename;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				filename = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + 4);
+				if(filename)
+					rsbac_get_full_path(file->f_path.dentry, filename, CONFIG_RSBAC_MAX_PATH_LEN);
+#else
+				filename = rsbac_kmalloc(RSBAC_MAXNAMELEN + 4);
+				if(filename)
+					rsbac_get_full_path(file->f_path.dentry, filename, RSBAC_MAXNAMELEN);
+#endif
+
+				rsbac_printk(KERN_INFO
+						"rsbac_jail_sys_jail(): avoid possible chroot breakout by closing open dir fd %u, inode %lu, device %02u:%02u, path %s\n",
+						fd,
+						file->f_path.dentry->d_inode->i_ino,
+						MAJOR(file->f_path.dentry->d_sb->s_dev),
+						MINOR(file->f_path.dentry->d_sb->s_dev),
+						filename);
+				if(filename)
+					rsbac_kfree(filename);
+
+				rcu_read_unlock();
+				sys_close(fd);
+				goto restart;
+			}
+		}
+		rcu_read_unlock();
+	}
+
+	/* Set jail_id for this process - number might wrap, so better check */
+	i_attr_val1.jail_id = next_id++;
+	while (!i_attr_val1.jail_id || rsbac_jail_exists(i_attr_val1.jail_id))
+		i_attr_val1.jail_id = next_id++;
+
+	if (rsbac_set_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_id,
+				i_attr_val1))
+	{
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_id);
+		return(-RSBAC_EWRITEFAILED);
+	}
+
+	if (flags & JAIL_this_is_syslog) {
+		rsbac_jail_syslog_jail_id = i_attr_val1.jail_id;
+	}
+
+	/* Set jail_parent for this process */
+	i_attr_val1.jail_parent = parent;
+	if (rsbac_set_attr(SW_JAIL, T_PROCESS, i_tid, A_jail_parent, i_attr_val1)) {
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_parent);
+		return (-RSBAC_EWRITEFAILED);
+	}
+
+	/* Set jail_ip for this process */
+	i_attr_val1.jail_ip = ip;
+	if (rsbac_set_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_ip,
+				i_attr_val1))
+	{
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_ip);
+		return(-RSBAC_EWRITEFAILED);
+	}
+
+	/* Set jail_flags for this process */
+	i_attr_val1.jail_flags = flags;
+	if (rsbac_set_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_flags,
+				i_attr_val1))
+	{
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_flags);
+		return(-RSBAC_EWRITEFAILED);
+	}
+
+	/* Set jail_max_caps for this process */
+	i_attr_val1.jail_max_caps.cap[0] = max_caps.cap[0];
+	i_attr_val1.jail_max_caps.cap[1] = max_caps.cap[1];
+	if (rsbac_set_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_max_caps,
+				i_attr_val1))
+	{
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_max_caps);
+		return(-RSBAC_EWRITEFAILED);
+	}
+
+	/* Set jail_scd_get for this process */
+	i_attr_val1.jail_scd_get = scd_get;
+	if (rsbac_set_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_scd_get,
+				i_attr_val1))
+	{
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_scd_get);
+		return(-RSBAC_EWRITEFAILED);
+	}
+
+	/* Set jail_scd_modify for this process */
+	i_attr_val1.jail_scd_modify = scd_modify;
+	if (rsbac_set_attr(SW_JAIL,
+				T_PROCESS,
+				i_tid,
+				A_jail_scd_modify,
+				i_attr_val1))
+	{
+		rsbac_ds_set_error("rsbac_jail_sys_jail()", A_jail_scd_modify);
+		return(-RSBAC_EWRITEFAILED);
+	}
+	return err;
+}
diff --git a/rsbac/adf/mac/Makefile b/rsbac/adf/mac/Makefile
new file mode 100644
index 0000000..50c4357
--- /dev/null
+++ b/rsbac/adf/mac/Makefile
@@ -0,0 +1,9 @@
+#
+# File: rsbac/adf/mac/Makefile
+#
+# Makefile for the Linux rsbac mac decision module.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := mac_syscalls.o mac_main.o
diff --git a/rsbac/adf/mac/mac_main.c b/rsbac/adf/mac/mac_main.c
new file mode 100644
index 0000000..5b1cd07
--- /dev/null
+++ b/rsbac/adf/mac/mac_main.c
@@ -0,0 +1,4910 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Mandatory Access Control         */
+/* File: rsbac/adf/mac/main.c                        */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/* MAC_LIGHT Modifications (c) 2000 Stanislav Ievlev */
+/*                     and (c) 2001 Amon Ott         */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/aci.h>
+#include <rsbac/mac.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+#include <rsbac/rkmem.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+static enum rsbac_adf_req_ret_t
+mac_check_role(rsbac_uid_t owner,
+		enum rsbac_system_role_t role)
+{
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	i_tid.user = owner;
+	if (rsbac_get_attr(SW_MAC,
+			   T_USER,
+			   i_tid, A_mac_role, &i_attr_val1, FALSE)) {
+		rsbac_ds_get_error("mac_check_role", A_mac_role);
+		return NOT_GRANTED;
+	}
+	/* if correct role, then grant */
+	if (i_attr_val1.system_role == role)
+		return GRANTED;
+	else {
+		rsbac_pr_debug(adf_mac, "pid %u(%s): wrong mac_role %u -> NOT_GRANTED!\n",
+			       current->pid, current->comm,
+			       i_attr_val1.system_role);
+		return NOT_GRANTED;
+	}
+}
+
+/* auto_write() */
+/* This function builds a decision for write-only access based on      */
+/* ss-property and *-property. The Subject is given by process-id pid, */
+/* its attributes are taken from the data structures module. */
+/* For the object, only security_level is given to become independent  */
+/* from different object/target types.                                 */
+/* If attribute mac_auto is set, the current_security_level is changed */
+/* within min_write and max_read boundaries to allow for more accesses.*/
+/* If set_level is TRUE, the current_security_level and read/write     */
+/* boundaries are set to appropiate values, otherwise they are only    */
+/* checked. This provides only one function for decision and attribute */
+/* setting.                                                            */
+/* Trusted processes (attr. mac_trusted set) are always granted write  */
+/* access.                                                             */
+
+static enum rsbac_adf_req_ret_t
+auto_write_attr(rsbac_pid_t pid,
+		enum rsbac_target_t target,
+		union rsbac_target_id_t tid,
+		enum rsbac_attribute_t t_level_attr,
+		enum rsbac_attribute_t t_cat_attr,
+		rsbac_boolean_t set_level)
+{
+	rsbac_security_level_t curr_level;
+	rsbac_mac_category_vector_t curr_categories;
+	rsbac_security_level_t target_sec_level;
+	rsbac_mac_category_vector_t target_categories;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t attr_val1;
+	union rsbac_attribute_value_t attr_val2;
+	rsbac_mac_process_flags_t flags;
+	rsbac_boolean_t mac_auto_used_level = FALSE;
+	rsbac_boolean_t mac_auto_used_cat = FALSE;
+	rsbac_boolean_t raise_object_level = FALSE;
+	rsbac_boolean_t raise_object_cat = FALSE;
+
+	/* first check for mac_override, which allows everything */
+	i_tid.process = pid;
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_process_flags, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_write", A_mac_process_flags);
+		return NOT_GRANTED;
+	}
+	flags = attr_val1.mac_process_flags;
+	if (flags & MAC_override)
+		return GRANTED;
+
+	/* Get current security level */
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_current_sec_level, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_write", A_current_sec_level);
+		return NOT_GRANTED;
+	}
+	curr_level = attr_val1.security_level;
+	/* Get current categories */
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_curr_categories, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_write", A_mac_curr_categories);
+		return NOT_GRANTED;
+	}
+	curr_categories = attr_val1.mac_categories;
+	/* Get target security level */
+	if (rsbac_get_attr(SW_MAC, target, tid, t_level_attr, &attr_val1, TRUE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_write", t_level_attr);
+		return NOT_GRANTED;
+	}
+	target_sec_level = attr_val1.security_level;
+	/* Get target categories */
+	if (rsbac_get_attr(SW_MAC, target, tid, t_cat_attr, &attr_val1, TRUE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_write", t_cat_attr);
+		return NOT_GRANTED;
+	}
+	target_categories = attr_val1.mac_categories;
+
+	if (target_sec_level > curr_level) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_security_level, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_write", A_security_level);
+			return NOT_GRANTED;
+		}
+		if (attr_val1.security_level < target_sec_level) {
+			rsbac_pr_debug(adf_mac, "pid %u(%s): security_level %u under target_sec_level %u, no override -> NOT_GRANTED!\n",
+				       current->pid, current->comm,
+				       attr_val1.security_level,
+				       target_sec_level);
+			return NOT_GRANTED;
+		}
+		/* curr_level < target_level <= max_level -> need mac_auto,
+		 * write_up, trusted (at process)
+		 * or shared (at object) */
+		if (flags & MAC_auto)
+			mac_auto_used_level = TRUE;
+		else {
+			if (!(flags & MAC_write_up)
+			    && !(flags & MAC_trusted)
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags & MAC_write_up)
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+					    ) {
+						break;
+					}
+					/* fall through */
+
+				default:
+					rsbac_pr_debug(adf_mac, "pid %u(%s): current security_level %u under target_sec_level %u, no auto, write_up, trusted -> NOT_GRANTED!\n",
+						       current->pid,
+						       current->comm,
+						       curr_level,
+						       target_sec_level);
+					return NOT_GRANTED;
+				}
+			}
+		}
+	} else if (target_sec_level < curr_level) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_security_level, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_write", A_min_security_level);
+			return NOT_GRANTED;
+		}
+		if (attr_val1.security_level > target_sec_level) {
+			rsbac_pr_debug(adf_mac, "pid %u(%s): min_security_level %u over target_sec_level %u, no override -> NOT_GRANTED!\n",
+				       current->pid,
+				       current->comm, attr_val1.security_level,
+				       target_sec_level);
+			return NOT_GRANTED;
+		}
+		/* min_level <= target_level < curr_level -> need mac_auto,
+		 * write_down or trusted */
+		if (flags & MAC_auto) {
+			/* check max_read boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_open, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_write",
+						   A_max_read_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.security_level > target_sec_level) {
+				if (!(flags & MAC_write_down)
+				    && !(flags & MAC_trusted)
+				    ) {
+					/* Try mac_file_flags on the target,
+					 * if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_write",
+							     A_mac_file_flags);
+							return (NOT_GRANTED);
+						}
+						if ((attr_val1.
+						     mac_file_flags &
+						     MAC_write_down)
+						    || (attr_val1.
+							mac_file_flags &
+							MAC_trusted)
+						    ) {
+							if (attr_val1.
+							    mac_file_flags
+							    & MAC_auto) {
+								raise_object_level
+								    = TRUE;
+							}
+							break;
+						}
+						/* fall through */
+
+					default:
+						rsbac_pr_debug(adf_mac, "pid %u(%s): max_read_open %u over target_sec_level %u, no write_down or trusted -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     attr_val1.
+							     security_level,
+							     target_sec_level);
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				mac_auto_used_level = TRUE;
+		} else {
+			if (!(flags & MAC_write_down)
+			    && !(flags & MAC_trusted)
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags &
+					     MAC_write_down)
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+					    ) {
+						if (attr_val1.
+						    mac_file_flags &
+						    MAC_auto) {
+							raise_object_level
+							    = TRUE;
+						}
+						break;
+					}
+					/* fall through */
+
+				default:
+					rsbac_pr_debug(adf_mac, "pid %u(%s): current security_level %u over target_sec_level %u, no auto, write_down or trusted -> NOT_GRANTED!\n",
+						       current->pid,
+						       current->comm,
+						       curr_level,
+						       target_sec_level);
+					return NOT_GRANTED;
+				}
+			}
+		}
+	}
+
+	if ((target_categories & curr_categories) != target_categories) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_categories, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_write", A_mac_categories);
+			return NOT_GRANTED;
+		}
+		if ((target_categories & attr_val1.mac_categories) !=
+		    target_categories) {
+#ifdef CONFIG_RSBAC_DEBUG
+			if (rsbac_debug_adf_mac) {
+				char *tmp =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+				if (tmp) {
+					char *tmp2 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+
+					if (tmp2) {
+						u64tostrmac(tmp,
+							    attr_val1.
+							    mac_categories);
+						u64tostrmac(tmp2,
+							    target_categories);
+						rsbac_pr_debug(adf_mac, "pid %u(%s): max_categories %s under target categories %s, no override -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     tmp, tmp2);
+						rsbac_kfree(tmp2);
+					}
+					rsbac_kfree(tmp);
+				}
+			}
+#endif
+			return NOT_GRANTED;
+		}
+		/* curr_categories < target_categories <= max_categories -> need mac_auto,
+		 * write_up or trusted */
+		if (flags & MAC_auto)
+			mac_auto_used_cat = TRUE;
+		else {
+			if (!(flags & MAC_write_up)
+			    && !(flags & MAC_trusted)
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags & MAC_write_up)
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+					    )
+						break;
+					/* fall through */
+
+				default:
+#ifdef CONFIG_RSBAC_DEBUG
+					if (rsbac_debug_adf_mac) {
+						char *tmp =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+
+						if (tmp) {
+							char *tmp2 =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp2) {
+								u64tostrmac
+								    (tmp,
+								     curr_categories);
+								u64tostrmac
+								    (tmp2,
+								     target_categories);
+								rsbac_pr_debug(adf_mac, "pid %u(%s): curr_categories %s under target categories %s, no auto, write_up or trusted -> NOT_GRANTED!\n",
+								     current->
+								     pid,
+								     current->
+								     comm,
+								     tmp,
+								     tmp2);
+								rsbac_kfree
+								    (tmp2);
+							}
+							rsbac_kfree(tmp);
+						}
+					}
+#endif
+					return NOT_GRANTED;
+				}
+			}
+		}
+	} else
+	    if ((target_categories & curr_categories) != curr_categories) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_min_categories, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_write", A_mac_min_categories);
+			return NOT_GRANTED;
+		}
+		if ((target_categories & attr_val1.mac_categories) !=
+		    attr_val1.mac_categories) {
+#ifdef CONFIG_RSBAC_DEBUG
+			if (rsbac_debug_adf_mac) {
+				char *tmp =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+				if (tmp) {
+					char *tmp2 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+
+					if (tmp2) {
+						u64tostrmac(tmp,
+							    attr_val1.
+							    mac_categories);
+						u64tostrmac(tmp2,
+							    target_categories);
+						rsbac_pr_debug(adf_mac, "pid %u(%s): min_categories %s over target categories %s, no override -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     tmp, tmp2);
+						rsbac_kfree(tmp2);
+					}
+					rsbac_kfree(tmp);
+				}
+			}
+#endif
+			return NOT_GRANTED;
+		}
+		/* min_level <= target_level < curr_level -> need mac_auto,
+		 * write_down or trusted */
+		if (flags & MAC_auto) {
+			/* check max_read boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_categories, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_write",
+						   A_max_read_categories);
+				return NOT_GRANTED;
+			}
+			if ((target_categories & attr_val1.
+			     mac_categories) != attr_val1.mac_categories) {
+				if (!(flags & MAC_write_down)
+				    && !(flags & MAC_trusted)
+				    ) {
+					/* Try mac_file_flags on the target,
+					 * if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_write",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if ((attr_val1.
+						     mac_file_flags &
+						     MAC_write_down)
+						    || (attr_val1.
+							mac_file_flags &
+							MAC_trusted)
+						    ) {
+							if (attr_val1.
+							    mac_file_flags
+							    & MAC_auto) {
+								raise_object_cat
+								    = TRUE;
+							}
+							break;
+						}
+						/* fall through */
+
+					default:
+#ifdef CONFIG_RSBAC_DEBUG
+						if (rsbac_debug_adf_mac) {
+							char *tmp =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp) {
+								char *tmp2
+								    =
+								    rsbac_kmalloc
+								    (RSBAC_MAXNAMELEN);
+
+								if (tmp2) {
+									u64tostrmac
+									    (tmp,
+									     attr_val1.
+									     mac_categories);
+									u64tostrmac
+									    (tmp2,
+									     target_categories);
+									rsbac_pr_debug(adf_mac, "pid %u(%s): max_read_categories %s over target categories %s, no write_down or trusted -> NOT_GRANTED!\n",
+									     current->
+									     pid,
+									     current->
+									     comm,
+									     tmp,
+									     tmp2);
+									rsbac_kfree
+									    (tmp2);
+								}
+								rsbac_kfree
+								    (tmp);
+							}
+						}
+#endif
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				mac_auto_used_cat = TRUE;
+		} else {
+			if (!(flags & MAC_write_down)
+			    && !(flags & MAC_trusted)
+			    ) {
+				/* Try mac_file_flags on the target, if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags &
+					     MAC_write_down)
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+					    ) {
+						if (attr_val1.
+						    mac_file_flags &
+						    MAC_auto) {
+							raise_object_cat =
+							    TRUE;
+						}
+						break;
+					}
+					/* fall through */
+
+				default:
+#ifdef CONFIG_RSBAC_DEBUG
+					if (rsbac_debug_adf_mac) {
+						char *tmp =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+
+						if (tmp) {
+							char *tmp2 =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp2) {
+								u64tostrmac
+								    (tmp,
+								     curr_categories);
+								u64tostrmac
+								    (tmp2,
+								     target_categories);
+								rsbac_pr_debug(adf_mac, "pid %u(%s): curr_categories %s over target categories %s, no auto, write_down or trusted -> NOT_GRANTED!\n",
+								     current->
+								     pid,
+								     current->
+								     comm,
+								     tmp,
+								     tmp2);
+								rsbac_kfree
+								    (tmp2);
+							}
+							rsbac_kfree(tmp);
+						}
+					}
+#endif
+					return NOT_GRANTED;
+				}
+			}
+		}
+	}
+
+	/* grant area */
+
+	/* adjust current_sec_level and min_write_level, */
+	/* if set_level is true and mac_auto has been used */
+	if (set_level && (mac_auto_used_level || raise_object_level)
+	    ) {
+#ifdef CONFIG_RSBAC_MAC_LOG_LEVEL_CHANGE
+		{
+			char *target_type_name;
+			char *target_id_name;
+
+			target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (target_type_name) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				target_id_name
+				    =
+				    rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN
+						  + RSBAC_MAXNAMELEN);
+				/* max. path name len + some extra */
+#else
+				target_id_name =
+				    rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+				/* max. file name len + some extra */
+#endif
+				if (target_id_name) {
+					get_target_name(target_type_name,
+							target,
+							target_id_name,
+							tid);
+
+					if (mac_auto_used_level) {
+						rsbac_printk(KERN_INFO "mac_auto_write(): Changing process %u (%s, owner %u) current level from %u to %u for %s %s\n",
+							     pid,
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     curr_level,
+							     target_sec_level,
+							     target_type_name,
+							     target_id_name);
+					} else {
+						rsbac_printk(KERN_INFO "mac_auto_write(): Process %u (%s, owner %u): Raising object level from %u to %u for %s %s\n",
+							     pid,
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     target_sec_level,
+							     curr_level,
+							     target_type_name,
+							     target_id_name);
+					}
+					rsbac_kfree(target_id_name);
+				}
+				rsbac_kfree(target_type_name);
+			}
+		}
+#endif
+		if (mac_auto_used_level) {
+			i_tid.process = pid;
+			attr_val1.current_sec_level = target_sec_level;
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_open, &attr_val2, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_write",
+						   A_min_write_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.min_write_open <
+			    attr_val2.min_write_open) {
+				if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_open, attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("mac_auto_write", A_min_write_open);
+					return NOT_GRANTED;
+				}
+			}
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_current_sec_level, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		} else {
+			attr_val1.security_level = curr_level;
+			if (rsbac_set_attr(SW_MAC, target, tid, A_security_level, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		}
+	}
+	/* adjust current_categories and min_write_categories, */
+	/* if set_level is true and mac_auto has been used */
+	if (set_level && (mac_auto_used_cat || raise_object_cat)
+	    ) {
+#ifdef CONFIG_RSBAC_MAC_LOG_LEVEL_CHANGE
+		{
+			char *target_type_name =
+			    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (target_type_name) {
+				char *target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				target_id_name
+				    =
+				    rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN
+						  + RSBAC_MAXNAMELEN);
+				/* max. path name len + some extra */
+#else
+				target_id_name =
+				    rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+				/* max. file name len + some extra */
+#endif
+				if (target_id_name) {
+					char *tmp1 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+					if (tmp1) {
+						char *tmp2 =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+						if (tmp2) {
+							get_target_name
+							    (target_type_name,
+							     target,
+							     target_id_name,
+							     tid);
+
+							if (mac_auto_used_cat) {
+								rsbac_printk
+								    (KERN_INFO "mac_auto_write(): Changing process %u (%s, owner %u) current categories from %s to %s for %s %s\n",
+								     pid,
+								     current->
+								     comm,
+								     __kuid_val(current_uid()),
+								     u64tostrmac
+								     (tmp1,
+								      curr_categories),
+								     u64tostrmac
+								     (tmp2,
+								      target_categories),
+								     target_type_name,
+								     target_id_name);
+							} else {
+								rsbac_printk
+								    (KERN_INFO "mac_auto_write(): Process %u (%s, owner %u): raising current categories from %s to %s for %s %s\n",
+								     pid,
+								     current->
+								     comm,
+								     __kuid_val(current_uid()),
+								     u64tostrmac
+								     (tmp2,
+								      target_categories),
+								     u64tostrmac
+								     (tmp1,
+								      curr_categories),
+								     target_type_name,
+								     target_id_name);
+							}
+							rsbac_kfree(tmp2);
+						}
+						rsbac_kfree(tmp1);
+					}
+					rsbac_kfree(target_id_name);
+				}
+				rsbac_kfree(target_type_name);
+			}
+		}
+#endif
+		if (mac_auto_used_cat) {
+			i_tid.process = pid;
+			attr_val1.mac_categories = target_categories;
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_categories, &attr_val2, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_write",
+						   A_min_write_categories);
+				return NOT_GRANTED;
+			}
+			if ((attr_val1.mac_categories & attr_val2.
+			     mac_categories)
+			    != attr_val2.mac_categories) {
+				if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_categories, attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("mac_auto_write", A_min_write_categories);
+					return NOT_GRANTED;
+				}
+			}
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_mac_curr_categories, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		} else {
+			attr_val1.mac_categories = curr_categories;
+			if (rsbac_set_attr(SW_MAC, target, tid, A_mac_categories, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		}
+	}
+
+	/* Everything done, so return */
+	return GRANTED;
+}
+
+static enum rsbac_adf_req_ret_t
+auto_write(rsbac_pid_t pid,
+	   enum rsbac_target_t target,
+	   union rsbac_target_id_t tid, rsbac_boolean_t set_level)
+{
+	return auto_write_attr(pid,
+			       target,
+			       tid,
+			       A_security_level,
+			       A_mac_categories, set_level);
+}
+
+/* auto_read() */
+/* This function works similar to auto_write() */
+
+static enum rsbac_adf_req_ret_t
+auto_read_attr(rsbac_pid_t pid,
+	       enum rsbac_target_t target,
+	       union rsbac_target_id_t tid,
+	       enum rsbac_attribute_t t_level_attr,
+	       enum rsbac_attribute_t t_cat_attr,
+	       rsbac_boolean_t set_level)
+{
+	rsbac_security_level_t curr_level;
+	rsbac_mac_category_vector_t curr_categories;
+	rsbac_security_level_t target_sec_level;
+	rsbac_mac_category_vector_t target_categories;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t attr_val1;
+	union rsbac_attribute_value_t attr_val2;
+	rsbac_mac_process_flags_t flags;
+	rsbac_boolean_t mac_auto_used_level = FALSE;
+	rsbac_boolean_t mac_auto_used_cat = FALSE;
+	rsbac_boolean_t set_level_level = FALSE;
+	rsbac_boolean_t set_level_cat = FALSE;
+
+	/* first check for mac_override, which allows everything */
+	i_tid.process = pid;
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_process_flags, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read", A_mac_process_flags);
+		return NOT_GRANTED;
+	}
+	flags = attr_val1.mac_process_flags;
+	if (flags & MAC_override)
+		return GRANTED;
+
+	/* Get current security level */
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_current_sec_level, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read", A_current_sec_level);
+		return NOT_GRANTED;
+	}
+	curr_level = attr_val1.security_level;
+	/* Get current categories */
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_curr_categories, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read", A_mac_curr_categories);
+		return NOT_GRANTED;
+	}
+	curr_categories = attr_val1.mac_categories;
+	/* Get target security level */
+	if (rsbac_get_attr(SW_MAC, target, tid, t_level_attr, &attr_val1, TRUE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read", t_level_attr);
+		return NOT_GRANTED;
+	}
+	target_sec_level = attr_val1.security_level;
+	/* Get target categories */
+	if (rsbac_get_attr(SW_MAC, target, tid, t_cat_attr, &attr_val1, TRUE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read", t_cat_attr);
+		return NOT_GRANTED;
+	}
+	target_categories = attr_val1.mac_categories;
+
+	if (target_sec_level > curr_level) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_security_level, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read", A_security_level);
+			return NOT_GRANTED;
+		}
+		if (attr_val1.security_level < target_sec_level) {
+			rsbac_pr_debug(adf_mac, "pid %u(%s): security_level %u under target_sec_level %u, no override -> NOT_GRANTED!\n",
+				       current->pid, current->comm,
+				       attr_val1.security_level,
+				       target_sec_level);
+			return NOT_GRANTED;
+		}
+		/* curr_level < target_level <= max_level -> need mac_auto, read_up or trusted (with read option) */
+		if (flags & MAC_auto) {
+			/* check min_write boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_open, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read",
+						   A_min_write_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.security_level < target_sec_level) {
+				if (!(flags & MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+				    && !(flags & MAC_trusted)
+#endif
+				    ) {
+					/* Try mac_file_flags on the target, if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_read",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if ((attr_val1.
+						     mac_file_flags &
+						     MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+						    || (attr_val1.
+							mac_file_flags &
+							MAC_trusted)
+#endif
+						    ) {
+							break;
+						}
+						/* fall through */
+
+					default:
+						rsbac_pr_debug(adf_mac, "pid %u(%s): min_write_open %u under target_sec_level %u, no read_up or trusted -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     attr_val1.
+							     security_level,
+							     target_sec_level);
+						return NOT_GRANTED;
+					}
+				}
+			} else {
+				mac_auto_used_level = TRUE;
+				set_level_level = TRUE;
+			}
+		} else {
+			if (!(flags & MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+			    && !(flags & MAC_trusted)
+#endif
+			    ) {
+				/* Try mac_file_flags on the target, if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_read",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags & MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+#endif
+					    ) {
+						break;
+					}
+					/* fall through */
+
+				default:
+					rsbac_pr_debug(adf_mac, "pid %u(%s): current level %u under target_sec_level %u, no auto, read_up or trusted -> NOT_GRANTED!\n",
+						       current->pid,
+						       current->comm,
+						       curr_level,
+						       target_sec_level);
+					return NOT_GRANTED;
+				}
+			}
+		}
+	} else if (target_sec_level < curr_level) {
+		if (flags & MAC_auto) {
+			mac_auto_used_level = TRUE;
+		}
+	}
+	if ((target_categories & curr_categories) != target_categories) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_categories, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read", A_mac_categories);
+			return NOT_GRANTED;
+		}
+		if ((target_categories & attr_val1.mac_categories) !=
+		    target_categories) {
+#ifdef CONFIG_RSBAC_DEBUG
+			if (rsbac_debug_adf_mac) {
+				char *tmp =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+				if (tmp) {
+					char *tmp2 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+
+					if (tmp2) {
+						u64tostrmac(tmp,
+							    attr_val1.
+							    mac_categories);
+						u64tostrmac(tmp2,
+							    target_categories);
+						rsbac_pr_debug(adf_mac, "pid %u(%s): max_categories %s under target categories %s, no override -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     tmp, tmp2);
+						rsbac_kfree(tmp2);
+					}
+					rsbac_kfree(tmp);
+				}
+			}
+#endif
+			return NOT_GRANTED;
+		}
+		/* curr_categories < target_categories <= max_categories -> need mac_auto,
+		 * read_up or trusted */
+		if (flags & MAC_auto) {
+			/* check min_write boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_categories, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read",
+						   A_min_write_categories);
+				return NOT_GRANTED;
+			}
+			if ((target_categories & attr_val1.
+			     mac_categories) != target_categories) {
+				if (!(flags & MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+				    && !(flags & MAC_trusted)
+#endif
+				    ) {
+					/* Try mac_file_flags on the target,
+					 * if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_read",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if ((attr_val1.
+						     mac_file_flags &
+						     MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+						    || (attr_val1.
+							mac_file_flags &
+							MAC_trusted)
+#endif
+						    ) {
+							break;
+						}
+						/* fall through */
+
+					default:
+#ifdef CONFIG_RSBAC_DEBUG
+						if (rsbac_debug_adf_mac) {
+							char *tmp =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp) {
+								char *tmp2
+								    =
+								    rsbac_kmalloc
+								    (RSBAC_MAXNAMELEN);
+
+								if (tmp2) {
+									u64tostrmac
+									    (tmp,
+									     attr_val1.
+									     mac_categories);
+									u64tostrmac
+									    (tmp2,
+									     target_categories);
+									rsbac_pr_debug(adf_mac, "pid %u(%s): min_write_categories %s under target categories %s, no read_up or trusted with read option -> NOT_GRANTED!\n",
+									     current->
+									     pid,
+									     current->
+									     comm,
+									     tmp,
+									     tmp2);
+									rsbac_kfree
+									    (tmp2);
+								}
+								rsbac_kfree
+								    (tmp);
+							}
+						}
+#endif
+						return NOT_GRANTED;
+					}
+				}
+			} else {
+				mac_auto_used_cat = TRUE;
+				set_level_cat = TRUE;
+			}
+		} else {
+			if (!(flags & MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+			    && !(flags & MAC_trusted)
+#endif
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_read",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags & MAC_read_up)
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+#endif
+					    ) {
+						break;
+					}
+					/* fall through */
+
+				default:
+#ifdef CONFIG_RSBAC_DEBUG
+					if (rsbac_debug_adf_mac) {
+						char *tmp =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+
+						if (tmp) {
+							char *tmp2 =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp2) {
+								u64tostrmac
+								    (tmp,
+								     curr_categories);
+								u64tostrmac
+								    (tmp2,
+								     target_categories);
+								rsbac_pr_debug(adf_mac, "pid %u(%s): curr_categories %s under target categories %s, no auto, read_up or trusted with read option -> NOT_GRANTED!\n",
+								     current->
+								     pid,
+								     current->
+								     comm,
+								     tmp,
+								     tmp2);
+								rsbac_kfree
+								    (tmp2);
+							}
+							rsbac_kfree(tmp);
+						}
+					}
+#endif
+					return NOT_GRANTED;
+				}
+			}
+		}
+	} else
+	    if ((target_categories & curr_categories) != curr_categories) {
+		if (flags & MAC_auto) {
+			mac_auto_used_level = TRUE;
+		}
+	}
+
+	/* grant area */
+
+	/* adjust current_sec_level and max_read_level, */
+	/* if set_level is true and mac_auto has been used */
+	if (set_level && mac_auto_used_level) {
+		i_tid.process = pid;
+		attr_val1.current_sec_level = target_sec_level;
+		if (set_level_level) {
+#ifdef CONFIG_RSBAC_MAC_LOG_LEVEL_CHANGE
+			char *target_type_name;
+			char *target_id_name;
+
+			target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (target_type_name) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				target_id_name
+				    =
+				    rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN
+						  + RSBAC_MAXNAMELEN);
+				/* max. path name len + some extra */
+#else
+				target_id_name =
+				    rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+				/* max. file name len + some extra */
+#endif
+				if (target_id_name) {
+					get_target_name(target_type_name,
+							target,
+							target_id_name,
+							tid);
+
+					rsbac_printk(KERN_INFO "mac_auto_read(): Changing process %u (%s, owner %u) current level from %u to %u for %s %s\n",
+						     pid,
+						     current->comm,
+						     __kuid_val(current_uid()),
+						     curr_level,
+						     target_sec_level,
+						     target_type_name,
+						     target_id_name);
+					rsbac_kfree(target_id_name);
+				}
+				rsbac_kfree(target_type_name);
+			}
+#endif
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_current_sec_level, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		}
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_open, &attr_val2, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read", A_max_read_open);
+			return NOT_GRANTED;
+		}
+		if (attr_val1.max_read_open > attr_val2.max_read_open) {
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_open, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		}
+	}
+	/* adjust current_categories and max_read_categories, */
+	/* if set_level is true and mac_auto has been used */
+	if (set_level && mac_auto_used_cat) {
+		i_tid.process = pid;
+		attr_val1.mac_categories = target_categories;
+		if (set_level_cat) {
+#ifdef CONFIG_RSBAC_MAC_LOG_LEVEL_CHANGE
+			char *target_type_name =
+			    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (target_type_name) {
+				char *target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				target_id_name
+				    =
+				    rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN
+						  + RSBAC_MAXNAMELEN);
+				/* max. path name len + some extra */
+#else
+				target_id_name =
+				    rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+				/* max. file name len + some extra */
+#endif
+				if (target_id_name) {
+					char *tmp1 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+					if (tmp1) {
+						char *tmp2 =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+						if (tmp2) {
+							get_target_name
+							    (target_type_name,
+							     target,
+							     target_id_name,
+							     tid);
+
+							rsbac_printk
+							    (KERN_INFO "mac_auto_read(): Changing process %u (15%s, owner %u) current categories from %s to %s for %s %s\n",
+							     pid,
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     u64tostrmac
+							     (tmp1,
+							      curr_categories),
+							     u64tostrmac
+							     (tmp2,
+							      target_categories),
+							     target_type_name,
+							     target_id_name);
+							rsbac_kfree(tmp2);
+						}
+						rsbac_kfree(tmp1);
+					}
+					rsbac_kfree(target_id_name);
+				}
+				rsbac_kfree(target_type_name);
+			}
+#endif
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_mac_curr_categories, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read",
+						   A_mac_curr_categories);
+				return NOT_GRANTED;
+			}
+		}
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_categories, &attr_val2, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read", A_max_read_categories);
+			return NOT_GRANTED;
+		}
+		if ((attr_val1.mac_categories & attr_val2.mac_categories)
+		    != attr_val1.mac_categories) {
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_categories, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read",
+						   A_max_read_categories);
+				return NOT_GRANTED;
+			}
+		}
+	}
+
+	/* Everything done, so return */
+	return GRANTED;
+}
+
+static enum rsbac_adf_req_ret_t
+auto_read(rsbac_pid_t pid,
+	  enum rsbac_target_t target,
+	  union rsbac_target_id_t tid, rsbac_boolean_t set_level)
+{
+	return auto_read_attr(pid,
+			      target,
+			      tid,
+			      A_security_level,
+			      A_mac_categories, set_level);
+}
+
+
+/* auto-read-write() */
+/* combines auto-read and auto-write */
+
+static enum rsbac_adf_req_ret_t
+auto_read_write_attr(rsbac_pid_t pid,
+		     enum rsbac_target_t target,
+		     union rsbac_target_id_t tid,
+		     enum rsbac_attribute_t t_level_attr,
+		     enum rsbac_attribute_t t_cat_attr,
+		     rsbac_boolean_t set_level)
+{
+	rsbac_security_level_t curr_level;
+	rsbac_mac_category_vector_t curr_categories;
+	rsbac_security_level_t target_sec_level;
+	rsbac_mac_category_vector_t target_categories;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t attr_val1;
+	union rsbac_attribute_value_t attr_val2;
+	rsbac_mac_process_flags_t flags;
+	rsbac_boolean_t mac_auto_used_level = FALSE;
+	rsbac_boolean_t mac_auto_used_cat = FALSE;
+	rsbac_boolean_t raise_object_level = FALSE;
+	rsbac_boolean_t raise_object_cat = FALSE;
+
+	/* first check for mac_override, which allows everything */
+	i_tid.process = pid;
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_process_flags, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read_write", A_mac_process_flags);
+		return NOT_GRANTED;
+	}
+	flags = attr_val1.mac_process_flags;
+	if (flags & MAC_override)
+		return GRANTED;
+
+	/* Get current security level */
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_current_sec_level, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read_write", A_current_sec_level);
+		return NOT_GRANTED;
+	}
+	curr_level = attr_val1.security_level;
+	/* Get current categories */
+	if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_curr_categories, &attr_val1, FALSE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read_write", A_mac_curr_categories);
+		return NOT_GRANTED;
+	}
+	curr_categories = attr_val1.mac_categories;
+	/* Get target security level */
+	if (rsbac_get_attr(SW_MAC, target, tid, t_level_attr, &attr_val1, TRUE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read_write", t_level_attr);
+		return NOT_GRANTED;
+	}
+	target_sec_level = attr_val1.security_level;
+	/* Get target categories */
+	if (rsbac_get_attr(SW_MAC, target, tid, t_cat_attr, &attr_val1, TRUE)) {	/* failed! */
+		rsbac_ds_get_error("mac_auto_read_write", t_cat_attr);
+		return NOT_GRANTED;
+	}
+	target_categories = attr_val1.mac_categories;
+
+	if (target_sec_level > curr_level) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_security_level, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read_write", A_security_level);
+			return NOT_GRANTED;
+		}
+		if (attr_val1.security_level < target_sec_level) {
+			rsbac_pr_debug(adf_mac, "pid %u(%s): security_level %u under target_sec_level %u, no override -> NOT_GRANTED!\n",
+				       current->pid, current->comm,
+				       attr_val1.security_level,
+				       target_sec_level);
+			return NOT_GRANTED;
+		}
+		/* curr_level < target_level <= max_level */
+		/* -> need mac_auto, (write_up && read_up)
+		 * or trusted (with read option) */
+		if (flags & MAC_auto) {
+			/* check min_write boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_open, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_min_write_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.security_level < target_sec_level) {
+				if (!
+				    ((flags & MAC_write_up)
+				     && (flags & MAC_read_up))
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+&& !(flags & MAC_trusted)
+#endif
+				    ) {
+					/* Try mac_file_flags on the target, if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_read_write",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if (((attr_val1.
+						      mac_file_flags &
+						      MAC_write_up)
+						     && (attr_val1.
+							 mac_file_flags &
+							 MAC_read_up)
+						    )
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+						    || (flags &
+							MAC_trusted)
+#endif
+						    ) {
+							break;
+						}
+						/* fall through */
+
+					default:
+						rsbac_pr_debug(adf_mac, "pid %u(%s): min_write_open %u under target_sec_level %u, no read_up or trusted -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     attr_val1.
+							     security_level,
+							     target_sec_level);
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				mac_auto_used_level = TRUE;
+		} else {
+			if (!
+			    ((flags & MAC_write_up)
+			     && (flags & MAC_read_up))
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+&& !(flags & MAC_trusted)
+#endif
+			    ) {
+				/* Try mac_file_flags on the target, if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_read_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if (((attr_val1.
+					      mac_file_flags &
+					      MAC_write_up)
+					     && (attr_val1.
+						 mac_file_flags &
+						 MAC_read_up)
+					    )
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+					    || (flags & MAC_trusted)
+#endif
+					    ) {
+						break;
+					}
+					/* fall through */
+
+				default:
+					rsbac_pr_debug(adf_mac, "pid %u(%s): current level %u under target_sec_level %u, no auto, (write_up && read_up) or trusted -> NOT_GRANTED!\n",
+						       current->pid,
+						       current->comm,
+						       curr_level,
+						       target_sec_level);
+					return NOT_GRANTED;
+				}
+			}
+		}
+	} else if (target_sec_level < curr_level) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_security_level, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read_write", A_min_security_level);
+			return NOT_GRANTED;
+		}
+		if (attr_val1.security_level > target_sec_level) {
+			rsbac_pr_debug(adf_mac, "pid %u(%s): min_security_level %u over target_sec_level %u, no override -> NOT_GRANTED!\n",
+				       current->pid,
+				       current->comm, attr_val1.security_level,
+				       target_sec_level);
+			return NOT_GRANTED;
+		}
+		/* min_level <= target_level < curr_level -> need mac_auto,
+		 * write_down or trusted */
+		if (flags & MAC_auto) {
+			/* check max_read boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_open, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_max_read_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.security_level > target_sec_level) {
+				if (!(flags & MAC_write_down)
+				    && !(flags & MAC_trusted)
+				    ) {
+					/* Try mac_file_flags on the target,
+					 * if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_read_write",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if ((attr_val1.
+						     mac_file_flags &
+						     MAC_write_down)
+						    || (attr_val1.
+							mac_file_flags &
+							MAC_trusted)
+						    ) {
+							if (attr_val1.
+							    mac_file_flags
+							    & MAC_auto) {
+								raise_object_level
+								    = TRUE;
+							}
+							break;
+						}
+						/* fall through */
+
+					default:
+						rsbac_pr_debug(adf_mac, "pid %u(%s): max_read_open %u over target_sec_level %u, no write_down or trusted -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     attr_val1.
+							     security_level,
+							     target_sec_level);
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				mac_auto_used_level = TRUE;
+		} else {
+			if (!(flags & MAC_write_down)
+			    && !(flags & MAC_trusted)
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_read_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags &
+					     MAC_write_down)
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+					    ) {
+						if (attr_val1.
+						    mac_file_flags &
+						    MAC_auto) {
+							raise_object_level
+							    = TRUE;
+						}
+						break;
+					}
+					/* fall through */
+
+				default:
+					rsbac_pr_debug(adf_mac, "pid %u(%s): current security_level %u over target_sec_level %u, no auto, write_down or trusted -> NOT_GRANTED!\n",
+						       current->pid,
+						       current->comm,
+						       curr_level,
+						       target_sec_level);
+					return NOT_GRANTED;
+				}
+			}
+		}
+	}
+	if ((target_categories & curr_categories) != target_categories) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_categories, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read_write", A_mac_categories);
+			return NOT_GRANTED;
+		}
+		if ((target_categories & attr_val1.mac_categories) !=
+		    target_categories) {
+#ifdef CONFIG_RSBAC_DEBUG
+			if (rsbac_debug_adf_mac) {
+				char *tmp =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+				if (tmp) {
+					char *tmp2 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+
+					if (tmp2) {
+						u64tostrmac(tmp,
+							    attr_val1.
+							    mac_categories);
+						u64tostrmac(tmp2,
+							    target_categories);
+						rsbac_pr_debug(adf_mac, "pid %u(%s): max_categories %s under target categories %s, no override -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     tmp, tmp2);
+						rsbac_kfree(tmp2);
+					}
+					rsbac_kfree(tmp);
+				}
+			}
+#endif
+			return NOT_GRANTED;
+		}
+		/* curr_categories < target_categories <= max_categories */
+		/* -> need mac_auto, (read_up && write_up) or 
+		 * trusted (with read option) */
+		if (flags & MAC_auto) {
+			/* check min_write boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_categories, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_min_write_categories);
+				return NOT_GRANTED;
+			}
+			if ((target_categories & attr_val1.
+			     mac_categories) != target_categories) {
+				if (!
+				    ((flags & MAC_write_up)
+				     && (flags & MAC_read_up))
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+&& !(flags & MAC_trusted)
+#endif
+				    ) {
+					/* Try mac_file_flags on the target,
+					 * if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_read_write",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if (((attr_val1.
+						      mac_file_flags &
+						      MAC_write_up)
+						     && (attr_val1.
+							 mac_file_flags &
+							 MAC_read_up)
+						    )
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+						    || (flags &
+							MAC_trusted)
+#endif
+						    ) {
+							break;
+						}
+						/* fall through */
+
+					default:
+#ifdef CONFIG_RSBAC_DEBUG
+						if (rsbac_debug_adf_mac) {
+							char *tmp =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp) {
+								char *tmp2
+								    =
+								    rsbac_kmalloc
+								    (RSBAC_MAXNAMELEN);
+
+								if (tmp2) {
+									u64tostrmac
+									    (tmp,
+									     attr_val1.
+									     mac_categories);
+									u64tostrmac
+									    (tmp2,
+									     target_categories);
+									rsbac_pr_debug(adf_mac, "pid %u(%s): min_write_categories %s under target categories %s, no (read_up and write_up) or trusted with read option -> NOT_GRANTED!\n",
+									     current->
+									     pid,
+									     current->
+									     comm,
+									     tmp,
+									     tmp2);
+									rsbac_kfree
+									    (tmp2);
+								}
+								rsbac_kfree
+								    (tmp);
+							}
+						}
+#endif
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				mac_auto_used_cat = TRUE;
+		} else {
+			if (!
+			    ((flags & MAC_write_up)
+			     && (flags & MAC_read_up))
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+&& !(flags & MAC_trusted)
+#endif
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_read_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if (((attr_val1.
+					      mac_file_flags &
+					      MAC_write_up)
+					     && (attr_val1.
+						 mac_file_flags &
+						 MAC_read_up)
+					    )
+#ifdef CONFIG_RSBAC_MAC_TRUSTED_READ
+					    || (flags & MAC_trusted)
+#endif
+					    ) {
+						break;
+					}
+					/* fall through */
+
+				default:
+#ifdef CONFIG_RSBAC_DEBUG
+					if (rsbac_debug_adf_mac) {
+						char *tmp =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+
+						if (tmp) {
+							char *tmp2 =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp2) {
+								u64tostrmac
+								    (tmp,
+								     curr_categories);
+								u64tostrmac
+								    (tmp2,
+								     target_categories);
+								rsbac_pr_debug(adf_mac, "pid %u(%s): curr_categories %s under target categories %s, no auto, (read_up and write_up) or trusted -> NOT_GRANTED!\n",
+								     current->
+								     pid,
+								     current->
+								     comm,
+								     tmp,
+								     tmp2);
+								rsbac_kfree
+								    (tmp2);
+							}
+							rsbac_kfree(tmp);
+						}
+					}
+#endif
+					return NOT_GRANTED;
+				}
+			}
+		}
+	} else
+	    if ((target_categories & curr_categories) != curr_categories) {
+		if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_mac_min_categories, &attr_val1, FALSE)) {	/* failed! */
+			rsbac_ds_get_error("mac_auto_read_write", A_mac_min_categories);
+			return NOT_GRANTED;
+		}
+		if ((target_categories & attr_val1.mac_categories) !=
+		    attr_val1.mac_categories) {
+#ifdef CONFIG_RSBAC_DEBUG
+			if (rsbac_debug_adf_mac) {
+				char *tmp =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+				if (tmp) {
+					char *tmp2 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+
+					if (tmp2) {
+						u64tostrmac(tmp,
+							    attr_val1.
+							    mac_categories);
+						u64tostrmac(tmp2,
+							    target_categories);
+						rsbac_pr_debug(adf_mac, "pid %u(%s): min_categories %s over target categories %s, no override -> NOT_GRANTED!\n",
+							     current->pid,
+							     current->comm,
+							     tmp, tmp2);
+						rsbac_kfree(tmp2);
+					}
+					rsbac_kfree(tmp);
+				}
+			}
+#endif
+			return NOT_GRANTED;
+		}
+		/* min_level <= target_level < curr_level -> need mac_auto,
+		 * write_down or trusted */
+		if (flags & MAC_auto) {
+			/* check max_read boundary */
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_categories, &attr_val1, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_max_read_categories);
+				return NOT_GRANTED;
+			}
+			if ((target_categories & attr_val1.
+			     mac_categories) != attr_val1.mac_categories) {
+				if (!(flags & MAC_write_down)
+				    && !(flags & MAC_trusted)
+				    ) {
+					/* Try mac_file_flags on the target,
+					 * if FD object */
+					switch (target) {
+					case T_FILE:
+					case T_DIR:
+					case T_FIFO:
+					case T_SYMLINK:
+					case T_UNIXSOCK:
+						if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+							rsbac_ds_get_error
+							    ("mac_auto_read_write",
+							     A_mac_file_flags);
+							return
+							    (NOT_GRANTED);
+						}
+						if ((attr_val1.
+						     mac_file_flags &
+						     MAC_write_down)
+						    || (attr_val1.
+							mac_file_flags &
+							MAC_trusted)
+						    ) {
+							if (attr_val1.
+							    mac_file_flags
+							    & MAC_auto) {
+								raise_object_cat
+								    = TRUE;
+							}
+							break;
+						}
+						/* fall through */
+
+					default:
+#ifdef CONFIG_RSBAC_DEBUG
+						if (rsbac_debug_adf_mac) {
+							char *tmp =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp) {
+								char *tmp2
+								    =
+								    rsbac_kmalloc
+								    (RSBAC_MAXNAMELEN);
+
+								if (tmp2) {
+									u64tostrmac
+									    (tmp,
+									     attr_val1.
+									     mac_categories);
+									u64tostrmac
+									    (tmp2,
+									     target_categories);
+									rsbac_pr_debug(adf_mac, "pid %u(%s): max_read_categories %s over target categories %s, no write_down or trusted -> NOT_GRANTED!\n",
+									     current->
+									     pid,
+									     current->
+									     comm,
+									     tmp,
+									     tmp2);
+									rsbac_kfree
+									    (tmp2);
+								}
+								rsbac_kfree
+								    (tmp);
+							}
+						}
+#endif
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				mac_auto_used_cat = TRUE;
+		} else {
+			if (!(flags & MAC_write_down)
+			    && !(flags & MAC_trusted)
+			    ) {
+				/* Try mac_file_flags on the target,
+				 * if FD object */
+				switch (target) {
+				case T_FILE:
+				case T_DIR:
+				case T_FIFO:
+				case T_SYMLINK:
+				case T_UNIXSOCK:
+					if (rsbac_get_attr(SW_MAC, target, tid, A_mac_file_flags, &attr_val1, FALSE)) {	/* failed! */
+						rsbac_ds_get_error
+						    ("mac_auto_read_write",
+						     A_mac_file_flags);
+						return NOT_GRANTED;
+					}
+					if ((attr_val1.
+					     mac_file_flags &
+					     MAC_write_down)
+					    || (attr_val1.
+						mac_file_flags &
+						MAC_trusted)
+					    ) {
+						if (attr_val1.
+						    mac_file_flags &
+						    MAC_auto) {
+							raise_object_cat =
+							    TRUE;
+						}
+						break;
+					}
+					/* fall through */
+
+				default:
+#ifdef CONFIG_RSBAC_DEBUG
+					if (rsbac_debug_adf_mac) {
+						char *tmp =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+
+						if (tmp) {
+							char *tmp2 =
+							    rsbac_kmalloc
+							    (RSBAC_MAXNAMELEN);
+
+							if (tmp2) {
+								u64tostrmac
+								    (tmp,
+								     curr_categories);
+								u64tostrmac
+								    (tmp2,
+								     target_categories);
+								rsbac_pr_debug(adf_mac, "pid %u(%s): curr_categories %s over target categories %s, no auto, write_down or trusted -> NOT_GRANTED!\n",
+								     current->
+								     pid,
+								     current->
+								     comm,
+								     tmp,
+								     tmp2);
+								rsbac_kfree
+								    (tmp2);
+							}
+							rsbac_kfree(tmp);
+						}
+					}
+#endif
+					return NOT_GRANTED;
+				}
+			}
+		}
+	}
+
+	/* grant area */
+
+	/* adjust current_sec_level and min_write_level, */
+	/* if set_level is true and mac_auto has been used */
+	if (set_level && (mac_auto_used_level || raise_object_level)
+	    ) {
+#ifdef CONFIG_RSBAC_MAC_LOG_LEVEL_CHANGE
+		{
+			char *target_type_name;
+			char *target_id_name;
+
+			target_type_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (target_type_name) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				target_id_name
+				    =
+				    rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN
+						  + RSBAC_MAXNAMELEN);
+				/* max. path name len + some extra */
+#else
+				target_id_name =
+				    rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+				/* max. file name len + some extra */
+#endif
+				if (target_id_name) {
+					get_target_name(target_type_name,
+							target,
+							target_id_name,
+							tid);
+
+					if (mac_auto_used_level) {
+						rsbac_printk(KERN_INFO "mac_auto_read_write(): Changing process %u (%s, owner %u) current level from %u to %u for %s %s\n",
+							     pid,
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     curr_level,
+							     target_sec_level,
+							     target_type_name,
+							     target_id_name);
+					} else {
+						rsbac_printk(KERN_INFO "mac_auto_read_write(): Process %u (%s, owner %u): Raising object level from %u to %u for %s %s\n",
+							     pid,
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     target_sec_level,
+							     curr_level,
+							     target_type_name,
+							     target_id_name);
+					}
+					rsbac_kfree(target_id_name);
+				}
+				rsbac_kfree(target_type_name);
+			}
+		}
+#endif
+		if (mac_auto_used_level) {
+			i_tid.process = pid;
+			attr_val1.current_sec_level = target_sec_level;
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_open, &attr_val2, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_min_write_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.min_write_open <
+			    attr_val2.min_write_open) {
+				if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_open, attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("mac_auto_read_write",
+					     A_min_write_open);
+					return NOT_GRANTED;
+				}
+			}
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_open, &attr_val2, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_max_read_open);
+				return NOT_GRANTED;
+			}
+			if (attr_val1.max_read_open >
+			    attr_val2.max_read_open) {
+				if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_open, attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("mac_auto_read_write",
+					     A_max_read_open);
+					return NOT_GRANTED;
+				}
+			}
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_current_sec_level, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		} else {
+			attr_val1.security_level = curr_level;
+			if (rsbac_set_attr(SW_MAC, target, tid, A_security_level, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		}
+	}
+	/* adjust current_categories and min_write_categories, */
+	/* if set_level is true and mac_auto has been used */
+	if (set_level && (mac_auto_used_cat || raise_object_cat)
+	    ) {
+#ifdef CONFIG_RSBAC_MAC_LOG_LEVEL_CHANGE
+		{
+			char *target_type_name =
+			    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (target_type_name) {
+				char *target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				target_id_name
+				    =
+				    rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN
+						  + RSBAC_MAXNAMELEN);
+				/* max. path name len + some extra */
+#else
+				target_id_name =
+				    rsbac_kmalloc(2 * RSBAC_MAXNAMELEN);
+				/* max. file name len + some extra */
+#endif
+				if (target_id_name) {
+					char *tmp1 =
+					    rsbac_kmalloc
+					    (RSBAC_MAXNAMELEN);
+					if (tmp1) {
+						char *tmp2 =
+						    rsbac_kmalloc
+						    (RSBAC_MAXNAMELEN);
+						if (tmp2) {
+							get_target_name
+							    (target_type_name,
+							     target,
+							     target_id_name,
+							     tid);
+
+							if (mac_auto_used_cat) {
+								rsbac_printk
+								    (KERN_INFO "mac_auto_read_write(): Changing process %u (%s, owner %u) current categories from %s to %s for %s %s\n",
+								     pid,
+								     current->
+								     comm,
+								     __kuid_val(current_uid()),
+								     u64tostrmac
+								     (tmp1,
+								      curr_categories),
+								     u64tostrmac
+								     (tmp2,
+								      target_categories),
+								     target_type_name,
+								     target_id_name);
+							} else {
+								rsbac_printk
+								    (KERN_INFO "mac_auto_read_write(): Process %u (%s, owner %u): raising current categories from %s to %s for %s %s\n",
+								     pid,
+								     current->
+								     comm,
+								     __kuid_val(current_uid()),
+								     u64tostrmac
+								     (tmp2,
+								      target_categories),
+								     u64tostrmac
+								     (tmp1,
+								      curr_categories),
+								     target_type_name,
+								     target_id_name);
+							}
+							rsbac_kfree(tmp2);
+						}
+						rsbac_kfree(tmp1);
+					}
+					rsbac_kfree(target_id_name);
+				}
+				rsbac_kfree(target_type_name);
+			}
+		}
+#endif
+		if (mac_auto_used_cat) {
+			i_tid.process = pid;
+			attr_val1.mac_categories = target_categories;
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_categories, &attr_val2, FALSE)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read_write",
+						   A_min_write_categories);
+				return NOT_GRANTED;
+			}
+			if ((attr_val1.mac_categories & attr_val2.
+			     mac_categories)
+			    != attr_val2.mac_categories) {
+				if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_min_write_categories, attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("mac_auto_read_write",
+					     A_min_write_categories);
+					return NOT_GRANTED;
+				}
+			}
+			if (rsbac_get_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_categories, &attr_val2, FALSE)) {	/* failed! */
+				rsbac_ds_get_error("mac_auto_read_write",
+						   A_max_read_categories);
+				return NOT_GRANTED;
+			}
+			if ((attr_val1.mac_categories & attr_val2.
+			     mac_categories)
+			    != attr_val1.mac_categories) {
+				if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_max_read_categories, attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("mac_auto_read_write",
+					     A_max_read_categories);
+					return NOT_GRANTED;
+				}
+			}
+			if (rsbac_set_attr(SW_MAC, T_PROCESS, i_tid, A_mac_curr_categories, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		} else {
+			attr_val1.mac_categories = curr_categories;
+			if (rsbac_set_attr(SW_MAC, target, tid, A_mac_categories, attr_val1)) {	/* failed! */
+				rsbac_ds_set_error("mac_auto_read_write",
+						   A_none);
+				return NOT_GRANTED;
+			}
+		}
+	}
+
+	/* Everything done, so return */
+	return GRANTED;
+}
+
+static enum rsbac_adf_req_ret_t
+auto_read_write(rsbac_pid_t pid,
+		enum rsbac_target_t target,
+		union rsbac_target_id_t tid, rsbac_boolean_t set_level)
+{
+	return auto_read_write_attr(pid,
+				    target,
+				    tid,
+				    A_security_level,
+				    A_mac_categories, set_level);
+}
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+inline enum rsbac_adf_req_ret_t
+rsbac_adf_request_mac(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)
+{
+	enum rsbac_adf_req_ret_t result = DO_NOT_CARE;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+#if defined(CONFIG_RSBAC_MAC_NET_OBJ_PROT)
+	union rsbac_attribute_value_t i_attr_val2;
+#endif
+
+	switch (request) {
+	case R_ADD_TO_KERNEL:
+		switch (target) {
+		case T_FILE:
+		case T_DEV:
+		case T_NONE:
+			/* test owner's mac_role */
+			return mac_check_role(owner, SR_administrator);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_ALTER:
+		/* only for IPC */
+		if (target == T_IPC) {
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+		} else
+			/* all other targets are unknown */
+			return DO_NOT_CARE;
+		break;
+
+	case R_APPEND_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_UNIXSOCK:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+		case T_IPC:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CHANGE_GROUP:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+		case T_IPC:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+			/* We do not care about */
+			/* all other cases */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CHANGE_OWNER:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+		case T_IPC:
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CHDIR:
+		switch (target) {
+		case T_DIR:
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CREATE:
+		switch (target) {
+			/* Creating dir or (pseudo) file IN target dir! */
+		case T_DIR:
+#ifdef CONFIG_RSBAC_MAC_LIGHT
+			return GRANTED;
+#else
+			/* Mode of created item is ignored! */
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+#endif
+			break;
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETTEMP:
+			return mac_check_role(owner, SR_security_officer);
+
+		case T_NETOBJ:
+			/* and perform auto-write without setting attributes */
+			return (auto_write_attr(caller_pid,
+						target,
+						tid,
+						A_local_sec_level,
+						A_local_mac_categories,
+						FALSE));
+#endif
+
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_DELETE:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+		case T_IPC:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETTEMP:
+			return mac_check_role(owner, SR_security_officer);
+#endif
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_EXECUTE:
+	case R_MAP_EXEC:
+		switch (target) {
+		case T_FILE:
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_GET_PERMISSIONS_DATA:
+		switch (target) {
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			/* and perform auto-read without setting attributes */
+			return (auto_read_attr(caller_pid,
+					       target,
+					       tid,
+					       A_local_sec_level,
+					       A_local_mac_categories,
+					       FALSE));
+#endif
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_GET_STATUS_DATA:
+		switch (target) {
+		case T_SCD:
+			/* target rsbaclog? only for secoff */
+			if (tid.scd != ST_rsbac_log)
+				return GRANTED;
+			/* Secoff? */
+			if (mac_check_role(owner, SR_security_officer) ==
+			    NOT_GRANTED)
+				return mac_check_role(owner, SR_auditor);
+			else
+				return GRANTED;
+
+		case T_PROCESS:
+			/* perform auto-read without setting attributes */
+			return (auto_read_attr(caller_pid,
+					       target,
+					       tid,
+					       A_current_sec_level,
+					       A_mac_curr_categories,
+					       FALSE));
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			/* and perform auto-read without setting attributes */
+			return (auto_read_attr(caller_pid,
+					       target,
+					       tid,
+					       A_local_sec_level,
+					       A_local_mac_categories,
+					       FALSE));
+#endif
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_LINK_HARD:
+		switch (target) {
+		case T_FILE:
+		case T_UNIXSOCK:
+		case T_FIFO:
+		case T_SYMLINK:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_ACCESS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_ATTRIBUTE:
+		switch (attr) {
+		case A_security_level:
+		case A_initial_security_level:
+		case A_local_sec_level:
+		case A_remote_sec_level:
+		case A_min_security_level:
+		case A_mac_categories:
+		case A_mac_initial_categories:
+		case A_local_mac_categories:
+		case A_remote_mac_categories:
+		case A_mac_min_categories:
+		case A_mac_user_flags:
+		case A_mac_process_flags:
+		case A_mac_file_flags:
+		case A_system_role:
+		case A_mac_role:
+		case A_current_sec_level:
+		case A_mac_curr_categories:
+		case A_min_write_open:
+		case A_max_read_open:
+		case A_min_write_categories:
+		case A_max_read_categories:
+		case A_mac_check:
+		case A_mac_auto:
+		case A_mac_prop_trusted:
+		case A_symlink_add_mac_level:
+#ifdef CONFIG_RSBAC_MAC_GEN_PROT
+		case A_pseudo:
+		case A_log_array_low:
+		case A_log_array_high:
+		case A_local_log_array_low:
+		case A_local_log_array_high:
+		case A_remote_log_array_low:
+		case A_remote_log_array_high:
+		case A_log_program_based:
+		case A_log_user_based:
+		case A_symlink_add_remote_ip:
+		case A_symlink_add_uid:
+		case A_linux_dac_disable:
+		case A_fake_root_uid:
+		case A_audit_uid:
+		case A_auid_exempt:
+		case A_remote_ip:
+		case A_kernel_thread:
+		case A_vset:
+		case A_program_file:
+#endif
+#ifdef CONFIG_RSBAC_MAC_AUTH_PROT
+		case A_auth_may_setuid:
+		case A_auth_may_set_cap:
+		case A_auth_start_uid:
+		case A_auth_start_euid:
+		case A_auth_start_gid:
+		case A_auth_start_egid:
+		case A_auth_learn:
+		case A_auth_add_f_cap:
+		case A_auth_remove_f_cap:
+		case A_auth_last_auth:
+#endif
+			/* All attributes (remove target!) */
+		case A_none:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_PERMISSIONS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+
+		case T_SCD:
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+			if (tid.scd == ST_ioports)
+				return GRANTED;
+#endif
+			/* Security Officer? */
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_role,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_role);
+				return NOT_GRANTED;
+			}
+			/* if sec_officer, then grant */
+			if (i_attr_val1.system_role == SR_security_officer)
+				return GRANTED;
+			/* For booting: if administrator and ioports, then grant */
+			if ((i_attr_val1.system_role == SR_administrator)
+			    && (tid.scd == ST_ioports))
+				return GRANTED;
+			else
+				return NOT_GRANTED;
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			/* and perform auto-write without setting attributes */
+			return (auto_write_attr(caller_pid,
+						target,
+						tid,
+						A_local_sec_level,
+						A_local_mac_categories,
+						FALSE));
+#endif
+
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+			/* switching Linux DAC */
+		case T_NONE:
+			/* Security Officer? */
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_role,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_role);
+				return NOT_GRANTED;
+			}
+			/* if sec_officer, then grant */
+			if (i_attr_val1.system_role == SR_security_officer)
+				return GRANTED;
+			else
+				return NOT_GRANTED;
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_SYSTEM_DATA:
+		switch (target) {
+		case T_SCD:
+			/* target rlimit? no problem, but needed -> grant */
+			if (   (tid.scd == ST_rlimit)
+			    || (tid.scd == ST_priority)
+			    || (tid.scd == ST_mlock)
+			   )
+				return GRANTED;
+			/* Get role */
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_role,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_role);
+				return NOT_GRANTED;
+			}
+			/* if rsbaclog: grant only for secoff and auditor */
+			if (tid.scd == ST_rsbac_log) {
+				if ((i_attr_val1.system_role ==
+				     SR_security_officer)
+				    || (i_attr_val1.system_role ==
+					SR_auditor)
+				    )
+					return GRANTED;
+				else
+					return NOT_GRANTED;
+			}
+			/* if rsbac_log_remote: grant only for secoff */
+			if (tid.scd == ST_rsbac_remote_log) {
+				if ((i_attr_val1.system_role ==
+				     SR_security_officer)
+				    )
+					return GRANTED;
+				else
+					return NOT_GRANTED;
+			}
+			/* if rsbac: grant for secoff and adminr */
+			if (tid.scd == ST_rsbac) {
+				if ((i_attr_val1.system_role ==
+				     SR_security_officer)
+				    || (i_attr_val1.system_role ==
+					SR_administrator)
+				    )
+					return GRANTED;
+				else
+					return NOT_GRANTED;
+			}
+			/* if administrator, then grant */
+			if (i_attr_val1.system_role == SR_administrator)
+				return GRANTED;
+			else
+				return NOT_GRANTED;
+
+		case T_DEV:
+			if (tid.dev.type == D_block)
+				return mac_check_role(owner,
+						      SR_administrator);
+			else
+				return DO_NOT_CARE;
+
+		case T_PROCESS:
+			/* and perform auto-write without setting attributes */
+			return (auto_write_attr(caller_pid,
+						target,
+						tid,
+						A_current_sec_level,
+						A_mac_curr_categories,
+						FALSE));
+
+#ifdef CONFIG_RSBAC_MAC_NET_DEV_PROT
+		case T_NETDEV:
+			return mac_check_role(owner, SR_administrator);
+#endif
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			/* and perform auto-write without setting attributes */
+			return (auto_write_attr(caller_pid,
+						target,
+						tid,
+						A_local_sec_level,
+						A_local_mac_categories,
+						FALSE));
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MOUNT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_DEV:
+			/* test owner's mac_role: Administrator? */
+#ifndef CONFIG_RSBAC_MAC_LIGHT
+			if (mac_check_role(owner, SR_administrator) ==
+			    NOT_GRANTED)
+				return NOT_GRANTED;
+#endif
+			/* test read-write access to mount dir / dev: */
+			/* and perform auto-read(-write) without setting of attributes */
+			if ((target == T_DEV)
+			    && (attr == A_mode)
+			    && (attr_val.mode & MS_RDONLY))
+				return (auto_read(caller_pid,
+						  target, tid, FALSE));
+			else
+				return (auto_read_write(caller_pid,
+							target,
+							tid, FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_READ:
+		switch (target) {
+		case T_DIR:
+#ifdef CONFIG_RSBAC_RW
+		case T_IPC:
+		case T_FILE:
+		case T_FIFO:
+		case T_UNIXSOCK:
+#endif
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+			break;
+
+#ifdef CONFIG_RSBAC_RW
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+			break;
+#endif
+
+#if defined(CONFIG_RSBAC_MAC_NET_OBJ_PROT)
+		case T_NETTEMP:
+			if (mac_check_role(owner, SR_security_officer) ==
+			    GRANTED)
+				return GRANTED;
+			return mac_check_role(owner, SR_administrator);
+
+		case T_NETOBJ:
+			/* and perform auto-read without setting attributes */
+			return (auto_read_attr(caller_pid,
+					       target,
+					       tid,
+					       A_remote_sec_level,
+					       A_remote_mac_categories,
+					       FALSE));
+#endif
+
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+			/* Security Officer or Admin? */
+			if (mac_check_role(owner, SR_security_officer) ==
+			    GRANTED)
+				return GRANTED;
+			else
+				return mac_check_role(owner,
+						      SR_administrator);
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+
+	case R_READ_ATTRIBUTE:
+		switch (attr) {
+		case A_owner:
+		case A_security_level:
+		case A_local_sec_level:
+		case A_remote_sec_level:
+		case A_min_security_level:
+		case A_mac_categories:
+		case A_local_mac_categories:
+		case A_remote_mac_categories:
+		case A_mac_min_categories:
+		case A_pseudo:
+		case A_system_role:
+		case A_mac_role:
+		case A_current_sec_level:
+		case A_min_write_open:
+		case A_max_read_open:
+		case A_mac_user_flags:
+		case A_mac_process_flags:
+		case A_mac_check:
+		case A_mac_auto:
+		case A_mac_prop_trusted:
+		case A_mac_file_flags:
+		case A_initial_security_level:
+		case A_mac_initial_categories:
+		case A_symlink_add_mac_level:
+#ifdef CONFIG_RSBAC_MAC_GEN_PROT
+		case A_log_array_low:
+		case A_log_array_high:
+		case A_log_program_based:
+		case A_log_user_based:
+		case A_symlink_add_remote_ip:
+		case A_symlink_add_uid:
+		case A_fake_root_uid:
+		case A_audit_uid:
+		case A_auid_exempt:
+		case A_remote_ip:
+		case A_kernel_thread:
+		case A_vset:	
+		case A_program_file:
+#endif
+#ifdef CONFIG_RSBAC_MAC_AUTH_PROT
+		case A_auth_may_setuid:
+		case A_auth_may_set_cap:
+		case A_auth_start_uid:
+		case A_auth_start_euid:
+		case A_auth_start_gid:
+		case A_auth_start_egid:
+		case A_auth_learn:
+		case A_auth_last_auth:
+#endif
+			/* Security Officer ot Admin? */
+			if (mac_check_role(owner, SR_security_officer) ==
+			    GRANTED)
+				return GRANTED;
+			else
+				return mac_check_role(owner,
+						      SR_administrator);
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_READ_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+			break;
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_READ_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-read-write without setting attributes */
+			return (auto_read_write(caller_pid,
+						target, tid, FALSE));
+
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-read-write without setting attributes */
+			return (auto_read_write(caller_pid,
+						target, tid, FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_REMOVE_FROM_KERNEL:
+		switch (target) {
+		case T_FILE:
+		case T_DEV:
+		case T_NONE:
+			/* test owner's mac_role */
+			return mac_check_role(owner, SR_administrator);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SHUTDOWN:
+		switch (target) {
+		case T_NONE:
+			/* test owner's mac_role */
+			return mac_check_role(owner, SR_administrator);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_RENAME:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			/* and perform auto-write without setting attributes */
+			result = auto_write(caller_pid,
+					    target, tid, FALSE);
+			/* if parent dir might change, convert inherit to explicit level/cat:
+			   get and set effective value */
+			if (((result == GRANTED)
+			     || (result == DO_NOT_CARE)
+			    )
+			    && ((attr != A_new_dir_dentry_p)
+				|| (attr_val.new_dir_dentry_p !=
+				    tid.file.dentry_p->d_parent)
+			    )
+			    ) {
+				if (rsbac_get_attr(SW_MAC, target, tid, A_security_level, &i_attr_val1, TRUE)) {	/* failed! */
+					rsbac_ds_get_error
+					    ("rsbac_adf_request_mac",
+					     A_security_level);
+					return NOT_GRANTED;
+				}
+				if (rsbac_set_attr(SW_MAC, target, tid, A_security_level, i_attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("rsbac_adf_request_mac",
+					     A_security_level);
+					return NOT_GRANTED;
+				}
+				if (rsbac_get_attr(SW_MAC, target, tid, A_mac_categories, &i_attr_val1, TRUE)) {	/* failed! */
+					rsbac_ds_get_error
+					    ("rsbac_adf_request_mac",
+					     A_mac_categories);
+					return NOT_GRANTED;
+				}
+				if (rsbac_set_attr(SW_MAC, target, tid, A_mac_categories, i_attr_val1)) {	/* failed! */
+					rsbac_ds_set_error
+					    ("rsbac_adf_request_mac",
+					     A_none);
+					return NOT_GRANTED;
+				}
+			}
+			return result;
+			break;
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+
+	case R_SEARCH:
+		switch (target) {
+		case T_DIR:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			/* and perform auto-read without setting attributes */
+			return (auto_read(caller_pid, target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SEND_SIGNAL:
+		switch (target) {
+		case T_PROCESS:
+			/* and perform auto-write without setting attributes */
+			return (auto_write_attr(caller_pid,
+						target,
+						tid,
+						A_current_sec_level,
+						A_mac_curr_categories,
+						FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SWITCH_LOG:
+		switch (target) {
+		case T_NONE:
+			/* test owner's mac_role */
+			return mac_check_role(owner, SR_security_officer);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SWITCH_MODULE:
+		switch (target) {
+		case T_NONE:
+			/* we need the switch_target */
+			if (attr != A_switch_target)
+				return NOT_GRANTED;
+			/* do not care for other modules */
+			if ((attr_val.switch_target != SW_MAC)
+#ifdef CONFIG_RSBAC_MAC_AUTH_PROT
+			    && (attr_val.switch_target != SW_AUTH)
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE
+			    && (attr_val.switch_target != SW_SOFTMODE)
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+			    && (attr_val.switch_target != SW_FREEZE)
+#endif
+			    )
+				return DO_NOT_CARE;
+			/* test owner's mac_role */
+			return mac_check_role(owner, SR_security_officer);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_TRACE:
+		switch (target) {
+		case T_PROCESS:
+			/* and perform auto-read-write without setting attributes */
+			return (auto_read_write_attr(caller_pid,
+						     target,
+						     tid,
+						     A_current_sec_level,
+						     A_mac_curr_categories,
+						     FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_TRUNCATE:
+		switch (target) {
+		case T_FILE:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_UMOUNT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_DEV:
+#ifdef CONFIG_RSBAC_MAC_LIGHT
+			return GRANTED;
+#else
+			return mac_check_role(owner, SR_administrator);
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_WRITE:
+		switch (target) {
+		case T_DIR:
+		case T_IPC:
+#ifdef CONFIG_RSBAC_RW
+		case T_FILE:
+		case T_FIFO:
+		case T_UNIXSOCK:
+#endif
+			/* Mode of created item is ignored! */
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+
+#ifdef CONFIG_RSBAC_RW
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+#endif
+
+#if defined(CONFIG_RSBAC_MAC_NET_OBJ_PROT)
+		case T_NETTEMP:
+			return mac_check_role(owner, SR_security_officer);
+
+		case T_NETOBJ:
+			/* test write access to target: get its sec_level */
+			if (rsbac_get_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_remote_sec_level,
+					   &i_attr_val1, TRUE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_remote_sec_level);
+				return NOT_GRANTED;
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_remote_mac_categories,
+					   &i_attr_val2, TRUE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_remote_mac_categories);
+				return NOT_GRANTED;
+			}
+			/* and perform auto-write without setting attributes */
+			return (auto_write_attr(caller_pid,
+						target,
+						tid,
+						A_remote_sec_level,
+						A_remote_mac_categories,
+						FALSE));
+#endif
+
+#if defined(CONFIG_RSBAC_MAC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+			/* Security Officer? */
+			return mac_check_role(owner, SR_security_officer);
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MOVETO:
+		switch (target) {
+		case T_DIR:
+			/* Mode of created item is ignored! */
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+		case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+			break;
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+						   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SEND:
+		switch (target) {
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error("rsbac_adf_request_mac",
+                                                   A_mac_check);
+				return NOT_GRANTED;
+			}
+			if (!i_attr_val1.mac_check)
+				return DO_NOT_CARE;
+			/* and perform auto-write without setting attributes */
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+		case T_UNIXSOCK:
+			return (auto_write(caller_pid,
+					   target, tid, FALSE));
+
+#if defined(CONFIG_RSBAC_MAC_NET_OBJ_PROT)
+		case T_NETOBJ:
+			/* and perform auto-read-write without setting attributes */
+			return (auto_read_write_attr(caller_pid,
+						     target,
+						     tid,
+						     A_remote_sec_level,
+						     A_remote_mac_categories,
+						     FALSE));
+
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_BIND:
+	case R_LISTEN:
+		switch (target) {
+		case T_UNIXSOCK:
+			return (auto_read(caller_pid,
+					   target, tid, FALSE));
+#if defined(CONFIG_RSBAC_MAC_NET_OBJ_PROT)
+		case T_NETOBJ:
+			/* and perform auto-read-write without setting attributes */
+			return (auto_read_write_attr(caller_pid,
+						     target,
+						     tid,
+						     A_local_sec_level,
+						     A_local_mac_categories,
+						     FALSE));
+
+			/* all other cases are unknown */
+#endif
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_ACCEPT:
+	case R_CONNECT:
+	case R_RECEIVE:
+		switch (target) {
+		case T_UNIXSOCK:
+			return (auto_read_write(caller_pid,
+					   target, tid, FALSE));
+#if defined(CONFIG_RSBAC_MAC_NET_OBJ_PROT)
+		case T_NETOBJ:
+			/* and perform auto-read-write without setting attributes */
+			return (auto_read_write_attr(caller_pid,
+						     target,
+						     tid,
+						     A_remote_sec_level,
+						     A_remote_mac_categories,
+						     FALSE));
+#endif
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	default:
+		return DO_NOT_CARE;
+	}
+
+	return result;
+}
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up. Because of this, the write boundary is not adjusted - there  */
+/* is no user-level writing anyway...                                        */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+inline int rsbac_adf_set_attr_mac(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)
+{
+	enum rsbac_adf_req_ret_t result = DO_NOT_CARE;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_attribute_value_t i_attr_val2;
+	union rsbac_attribute_value_t i_attr_val3;
+	union rsbac_attribute_value_t i_attr_val4;
+	union rsbac_attribute_value_t i_attr_val5;
+	union rsbac_attribute_value_t i_attr_val6;
+	union rsbac_attribute_value_t i_attr_val7;
+	union rsbac_attribute_value_t i_attr_val8;
+	union rsbac_attribute_value_t i_attr_val9;
+	rsbac_boolean_t inherit;
+
+	switch (request) {
+	case R_APPEND_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_IPC:
+			/* test write access to target: get its sec_level */
+			if ((target == T_FILE)
+			    || (target == T_FIFO)
+			    )
+				inherit = TRUE;
+			else
+				inherit = FALSE;
+			if (rsbac_get_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_security_level,
+					   &i_attr_val1, inherit)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_mac_categories,
+					   &i_attr_val2, inherit)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* and perform auto-write with setting attributes */
+			result = auto_write(caller_pid, target, tid, TRUE);
+			if ((result == GRANTED) || (result == DO_NOT_CARE))
+				return 0;
+			else
+				return (-RSBAC_EDECISIONMISMATCH);
+			break;
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_check);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (!i_attr_val1.mac_check)
+				return 0;
+			/* and perform auto-write with setting attributes */
+			result = auto_write(caller_pid, target, tid, TRUE);
+			if ((result == GRANTED) || (result == DO_NOT_CARE))
+				return 0;
+			else
+				return (-RSBAC_EDECISIONMISMATCH);
+			break;
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_CHANGE_OWNER:
+		switch (target) {
+			/*  Changing process owner affects access decisions, */
+			/*  so attributes have to be adjusted.               */
+		case T_PROCESS:
+			/* For target process there MUST be a new owner specified */
+			if (attr != A_owner)
+				return (-RSBAC_EINVALIDATTR);
+
+			/* Get owner-sec-level and mac_categories for new owner */
+			i_tid.user = attr_val.owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_security_level,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_categories,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* set owner-sec-level and mac_categories for process to new values */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_security_level,
+					   i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_categories,
+					   i_attr_val3)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Get min_write_open and min_write_categories of process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_min_write_open,
+					   &i_attr_val4, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_write_open);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_min_write_categories,
+					   &i_attr_val5, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_write_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* adjust min_write_open and min_write_categories, if too high */
+			if (i_attr_val2.security_level <
+			    i_attr_val4.min_write_open) {
+				i_attr_val4.min_write_open =
+				    i_attr_val2.security_level;
+				if (rsbac_set_attr
+				    (SW_MAC, T_PROCESS, tid, A_min_write_open,
+				     i_attr_val4)) {
+					rsbac_ds_set_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_none);
+					return (-RSBAC_EWRITEFAILED);
+				}
+			}
+			/* does process have categories in min_write
+			 * that the new owner has not? */
+			/* If yes, throw them out. */
+			if ((i_attr_val3.mac_categories & i_attr_val5.
+			     mac_categories)
+			    != i_attr_val5.mac_categories) {
+				i_attr_val5.mac_categories &=
+				    i_attr_val3.mac_categories;
+				if (rsbac_set_attr
+				    (SW_MAC, T_PROCESS, tid,
+				     A_min_write_categories,
+				     i_attr_val5)) {
+					rsbac_ds_set_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_none);
+					return (-RSBAC_EWRITEFAILED);
+				}
+			}
+			/* Get owner-initial-sec-level and
+			 * mac_initial_categories for new owner */
+			/* These values will be adjusted by 
+			 * max_read / min_write and then used as */
+			/* new current level/categories. */
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_initial_security_level,
+					   &i_attr_val6, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_initial_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_initial_security_level,
+					   i_attr_val6)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_initial_security_level);
+				return (-RSBAC_EWRITEFAILED);
+			}
+#if 0
+			/* restrict current_level to be a maximum of min_write */
+			if (i_attr_val6.security_level >
+			    i_attr_val4.min_write_open)
+				i_attr_val6.security_level =
+				    i_attr_val4.min_write_open;
+#endif
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_initial_categories,
+					   &i_attr_val7, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_initial_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_initial_categories,
+					   i_attr_val7)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_mac_initial_categories);
+				return (-RSBAC_EWRITEFAILED);
+			}
+#if 0
+			/* restrict current_categories to be a maximum of min_write */
+			if ((i_attr_val7.mac_categories & i_attr_val5.
+			     mac_categories) != i_attr_val7.mac_categories)
+				i_attr_val7.mac_categories &=
+				    i_attr_val5.mac_categories;
+#endif
+			/* Get owner-min-sec-level and mac_min_categories for new owner */
+			i_tid.user = owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_min_security_level,
+					   &i_attr_val8, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_min_categories,
+					   &i_attr_val9, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_min_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* set owner-sec-level and mac_categories for process to new values */
+			/* owner is set by main dispatcher! */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_min_security_level,
+					   i_attr_val8)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_min_categories,
+					   i_attr_val9)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Get max_read_open and max_read_categories of process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_max_read_open,
+					   &i_attr_val4, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_max_read_open);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_max_read_categories,
+					   &i_attr_val5, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_max_read_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* adjust max_read_open and max_read_categories, if too low */
+			if (i_attr_val8.security_level >
+			    i_attr_val4.max_read_open) {
+				i_attr_val4.max_read_open =
+				    i_attr_val8.security_level;
+				if (rsbac_set_attr
+				    (SW_MAC, T_PROCESS, tid, A_max_read_open,
+				     i_attr_val4)) {
+					rsbac_ds_set_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_none);
+					return (-RSBAC_EWRITEFAILED);
+				}
+			}
+#if 0
+			/* adjust current sec level to a minimum of max_read */
+			if (i_attr_val6.security_level <
+			    i_attr_val4.max_read_open)
+				i_attr_val6.security_level =
+				    i_attr_val4.max_read_open;
+#endif
+			/* but never set it over new max_level or under new min_level */
+			if (i_attr_val6.security_level >
+			    i_attr_val2.security_level)
+				i_attr_val6.security_level =
+				    i_attr_val2.security_level;
+			else if (i_attr_val6.security_level <
+				 i_attr_val8.security_level)
+				i_attr_val6.security_level =
+				    i_attr_val8.security_level;
+			if (rsbac_set_attr
+			    (SW_MAC, T_PROCESS, tid, A_current_sec_level,
+			     i_attr_val6)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+
+			/* does new owner have categories in min_categories that the process max_read 
+			   has not? */
+			/* If yes, add them. */
+			if ((i_attr_val9.mac_categories & i_attr_val5.
+			     mac_categories)
+			    != i_attr_val9.mac_categories) {
+				i_attr_val5.mac_categories |=
+				    i_attr_val9.mac_categories;
+				if (rsbac_set_attr
+				    (SW_MAC, T_PROCESS, tid,
+				     A_max_read_categories, i_attr_val5)) {
+					rsbac_ds_set_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_none);
+					return (-RSBAC_EWRITEFAILED);
+				}
+			}
+#if 0
+			/* adjust current categories to include all from max_read (from initial) */
+			if ((i_attr_val7.mac_categories & i_attr_val5.
+			     mac_categories) != i_attr_val5.mac_categories)
+				i_attr_val7.mac_categories |=
+				    i_attr_val5.mac_categories;
+#endif
+			/* but never set it over new max_cats or under new min_cats */
+			if ((i_attr_val7.mac_categories & i_attr_val3.
+			     mac_categories) != i_attr_val7.mac_categories)
+				i_attr_val7.mac_categories &=
+				    i_attr_val3.mac_categories;
+			else if ((i_attr_val7.mac_categories & i_attr_val9.
+				  mac_categories) !=
+				 i_attr_val9.mac_categories)
+				i_attr_val7.mac_categories |=
+				    i_attr_val9.mac_categories;
+			if (rsbac_set_attr
+			    (SW_MAC, T_PROCESS, tid, A_mac_curr_categories,
+			     i_attr_val7)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+
+			/* Get mac_user_flags from user */
+			i_tid.user = attr_val.owner;
+			if (rsbac_get_attr(SW_MAC,
+					   T_USER,
+					   i_tid,
+					   A_mac_user_flags,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_user_flags);
+				return (-RSBAC_EREADFAILED);
+			}
+			i_attr_val1.mac_process_flags =
+			    i_attr_val3.mac_user_flags;
+			/* adjust flags - first get old process flags */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_process_flags,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_process_flags);
+				return (-RSBAC_EREADFAILED);
+			}
+			if ((i_attr_val2.
+			     mac_process_flags & MAC_program_auto)
+			    && (i_attr_val3.
+				mac_user_flags & MAC_allow_auto)
+			    )
+				i_attr_val1.mac_process_flags |= MAC_auto;
+
+			i_attr_val1.mac_process_flags &= RSBAC_MAC_P_FLAGS;
+
+			if (!(i_attr_val1.mac_process_flags & MAC_trusted)) {
+				if (rsbac_mac_p_truset_member
+				    (caller_pid, owner))
+					i_attr_val1.mac_process_flags |=
+					    MAC_trusted;
+			}
+			/* Set mac_process_flags on process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_process_flags,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* OK, we are ready */
+			return 0;
+
+			/* We do not care about other cases here */
+		default:
+			return 0;
+		}
+
+	case R_CLONE:
+		if (target == T_PROCESS) {
+			/* Get owner-sec-level from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_security_level,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get current-sec-level from first process... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_current_sec_level,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_current_sec_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get min_write_open from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_min_write_open,
+					   &i_attr_val4, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_write_open);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get max_read_open from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_max_read_open,
+					   &i_attr_val5, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_max_read_open);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get mac_process_flags from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_process_flags,
+					   &i_attr_val7, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_process_flags);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set owner_sec_level for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_security_level,
+					   i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set current_sec_level for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_current_sec_level,
+					   i_attr_val3)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set min_write_open for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_min_write_open,
+					   i_attr_val4)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set max_read_open for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_max_read_open, i_attr_val5)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set mac_process_flags for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_mac_process_flags,
+					   i_attr_val7)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+
+			/* Get mac_categories from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_categories,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get mac_curr_categories from first process... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_curr_categories,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_curr_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get min_write_categories from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_min_write_categories,
+					   &i_attr_val4, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_write_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get max_read_categories from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_max_read_categories,
+					   &i_attr_val5, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_max_read_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get initial_sec_level from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_initial_security_level,
+					   &i_attr_val6, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_initial_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get initial_categories from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_initial_categories,
+					   &i_attr_val7, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_initial_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set mac_categories for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_mac_categories,
+					   i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set mac_curr_categories for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_mac_curr_categories,
+					   i_attr_val3)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set min_write_categories for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_min_write_categories,
+					   i_attr_val4)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set max_read_categories for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_max_read_categories,
+					   i_attr_val5)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set initial_security_level for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_initial_security_level,
+					   i_attr_val6)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set initial_categories for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_mac_initial_categories,
+					   i_attr_val7)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Get owner-min_sec-level/cat from first process */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_min_security_level,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   tid,
+					   A_mac_min_categories,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_min_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set min_security_level for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_min_security_level,
+					   i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Set min_categories for new process */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   new_tid,
+					   A_mac_min_categories,
+					   i_attr_val3)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			if (rsbac_mac_copy_pp_truset
+			    (tid.process, new_tid.process)) {
+				rsbac_printk(KERN_WARNING
+					     "rsbac_adf_set_attr_mac(): rsbac_mac_copy_pp_truset() returned error!\n");
+				return (-RSBAC_EWRITEFAILED);
+			}
+			return 0;
+		} else
+			return 0;
+
+	case R_CREATE:
+		switch (target) {
+			/* Creating dir or (pseudo) file IN target dir! */
+		case T_DIR:
+			/* Mode of created item is ignored! */
+			/* and perform auto-write without(!) 
+			 * setting of attributes - no need */
+			/* -> decision consistency check only */
+			/* only check, if not MAC_LIGHT */
+#ifndef CONFIG_RSBAC_MAC_LIGHT
+			result = auto_write(caller_pid,
+					    target, tid, FALSE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+#endif
+			/* test write access to target: get its sec_level */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DIR,
+					   tid,
+					   A_security_level,
+					   &i_attr_val1, TRUE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_DIR,
+					   tid,
+					   A_mac_categories,
+					   &i_attr_val2, TRUE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Get current_sec_level from process (initialized to owner_sec_level)... */
+			i_tid.process = caller_pid;
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_current_sec_level,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_current_sec_level);
+				return (-RSBAC_EREADFAILED);
+			}
+#ifdef CONFIG_RSBAC_MAC_SMART_INHERIT
+			/* Only set, if different than inherited value */
+			if (i_attr_val3.security_level !=
+			    i_attr_val1.security_level)
+#endif
+				/* Set security-level for new item */
+				if (rsbac_set_attr(SW_MAC,
+						   new_target,
+						   new_tid,
+						   A_security_level,
+						   i_attr_val3)) {
+					rsbac_ds_set_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_none);
+					return (-RSBAC_EWRITEFAILED);
+				}
+			/* Get current_categories from process (initialized to owner_categories)... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_curr_categories,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_curr_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+#ifdef CONFIG_RSBAC_MAC_SMART_INHERIT
+			/* Only set, if different than inherited value */
+			if (i_attr_val3.mac_categories !=
+			    i_attr_val2.mac_categories)
+#endif
+				/* Set mac_categories for new item */
+				if (rsbac_set_attr(SW_MAC,
+						   new_target,
+						   new_tid,
+						   A_mac_categories,
+						   i_attr_val3)) {
+					rsbac_ds_set_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_none);
+					return (-RSBAC_EWRITEFAILED);
+				}
+			return 0;
+			break;
+
+		case T_IPC:
+			i_tid.process = caller_pid;
+			/* Get current-sec-level from process... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_current_sec_level,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_current_sec_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set security-level for this ipc item */
+			if (rsbac_set_attr(SW_MAC,
+					   T_IPC,
+					   tid,
+					   A_security_level,
+					   i_attr_val1)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Get mac_curr_categories from process... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_curr_categories,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_curr_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set curr_categories for new item */
+			if (rsbac_set_attr(SW_MAC,
+					   T_IPC,
+					   tid,
+					   A_mac_categories,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			return 0;
+			break;
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			i_tid.process = caller_pid;
+			/* Get current-sec-level from process... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_current_sec_level,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_current_sec_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set local security-level for this netobj item */
+			if (rsbac_set_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_local_sec_level,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* Get mac_curr_categories from process... */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_curr_categories,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_curr_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			/* Set local curr_categories for new item */
+			if (rsbac_set_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_local_mac_categories,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			return 0;
+			break;
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+		/* removal of targets is done in main adf dispatcher! */
+	case R_DELETE:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-write without(!) setting of attributes */
+			/* - no information flow apart from missing file */
+			/* -> decision consistency check only */
+			result = auto_write(caller_pid,
+					    target, tid, FALSE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			else
+				return 0;
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_EXECUTE:
+		switch (target) {
+		case T_FILE:
+			/* copy trusted user list from file to process */
+			if (rsbac_mac_copy_fp_truset(tid.file, caller_pid)) {
+				rsbac_printk(KERN_WARNING
+					     "rsbac_adf_set_attr_mac(): rsbac_mac_copy_fp_truset() returned error!\n");
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* perform auto-read with setting of attributes */
+			result = auto_read(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+
+			/* reset current_sec_level, mac_auto, min_write_open */
+			/* and max_read_open for process */
+			i_tid.process = caller_pid;
+
+#ifdef CONFIG_RSBAC_MAC_RESET_CURR
+			/* First, set current_sec_level and min_write_open to process owner's initial and seclevel */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_initial_security_level,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_initial_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_initial_categories,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_initial_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_current_sec_level,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_curr_categories,
+					   i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+#endif
+#if 0
+			/* Now, set min_write_open to process owner's seclevel */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_security_level,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+#endif
+			i_attr_val1.min_write_open = SL_max;
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_min_write_open,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+#if 0
+			/* Next, set min_write_categories to process owner's mac_categories */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_categories,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+#endif
+			i_attr_val2.mac_categories =
+			    RSBAC_MAC_MAX_CAT_VECTOR;
+			if (rsbac_set_attr
+			    (SW_MAC, T_PROCESS, i_tid, A_min_write_categories,
+			     i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* reset max_read boundary */
+#if 0
+			/* Get owner-min-sec-level and mac_min_categories for owner */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_min_security_level,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_min_security_level);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_min_categories,
+					   &i_attr_val2, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_min_categories);
+				return (-RSBAC_EREADFAILED);
+			}
+#endif
+			i_attr_val1.max_read_open = SL_min;
+			i_attr_val2.mac_categories =
+			    RSBAC_MAC_MIN_CAT_VECTOR;
+			if (rsbac_set_attr
+			    (SW_MAC, T_PROCESS, i_tid, A_max_read_open,
+			     i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* reset category max_read boundary */
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_max_read_categories,
+					   i_attr_val2)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			/* set flags */
+			if (rsbac_get_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_process_flags,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_process_flags);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   target,
+					   tid,
+					   A_mac_auto,
+					   &i_attr_val2, TRUE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_auto);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (i_attr_val2.mac_auto) {
+				i_attr_val1.mac_process_flags |=
+				    MAC_program_auto;
+				i_tid.user = owner;
+				if (rsbac_get_attr(SW_MAC,
+						   T_USER,
+						   i_tid,
+						   A_mac_user_flags,
+						   &i_attr_val2, FALSE)) {
+					rsbac_ds_get_error
+					    ("rsbac_adf_set_attr_mac",
+					     A_mac_user_flags);
+					return (-RSBAC_EREADFAILED);
+				}
+				if (i_attr_val2.
+				    mac_user_flags & MAC_allow_auto)
+					i_attr_val1.mac_process_flags |=
+					    MAC_auto;
+				else
+					i_attr_val1.mac_process_flags &=
+					    ~MAC_auto;
+				i_tid.process = caller_pid;
+			} else {
+				i_attr_val1.mac_process_flags &=
+				    ~MAC_program_auto;
+				i_attr_val1.mac_process_flags &= ~MAC_auto;
+			}
+			if (rsbac_get_attr(SW_MAC,
+					   T_FILE,
+					   tid,
+					   A_mac_prop_trusted,
+					   &i_attr_val3, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_prop_trusted);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (!(i_attr_val3.mac_prop_trusted)
+			    || !(i_attr_val1.
+				 mac_process_flags & MAC_trusted)
+			    ) {
+				if (rsbac_mac_p_truset_member
+				    (caller_pid, owner))
+					i_attr_val1.mac_process_flags |=
+					    MAC_trusted;
+				else {
+					i_tid.user = owner;
+					if (rsbac_get_attr(SW_MAC,
+							   T_USER,
+							   i_tid,
+							   A_mac_user_flags,
+							   &i_attr_val2,
+							   FALSE)) {
+						rsbac_ds_get_error
+						    ("rsbac_adf_set_attr_mac",
+						     A_mac_user_flags);
+						return(-RSBAC_EREADFAILED);
+					}
+					if (i_attr_val2.
+					    mac_user_flags & MAC_trusted)
+						i_attr_val1.
+						    mac_process_flags |=
+						    MAC_trusted;
+					else
+						i_attr_val1.
+						    mac_process_flags &=
+						    ~MAC_trusted;
+					i_tid.process = caller_pid;
+				}
+			}
+			if (rsbac_set_attr(SW_MAC,
+					   T_PROCESS,
+					   i_tid,
+					   A_mac_process_flags,
+					   i_attr_val1)) {
+				rsbac_ds_set_error
+				    ("rsbac_adf_set_attr_mac", A_none);
+				return (-RSBAC_EWRITEFAILED);
+			}
+			return 0;
+
+			/* all other cases */
+		default:
+			return 0;
+		}
+
+	case R_MOUNT:
+		switch (target) {
+		case T_DIR:
+		case T_DEV:
+			/* and perform auto-read(-write) with setting of attributes */
+			if ((target == T_DEV)
+			    && (attr == A_mode)
+			    && (attr_val.mode & MS_RDONLY))
+				result = auto_read(caller_pid,
+						   target, tid, TRUE);
+			else
+				result = auto_read_write(caller_pid,
+							 target,
+							 tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			else
+				return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_READ:
+		switch (target) {
+		case T_DIR:
+#ifdef CONFIG_RSBAC_RW
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_IPC:
+#endif
+			/* and perform auto-read with setting of attributes */
+			result = auto_read(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+#ifdef CONFIG_RSBAC_RW
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_check);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (!i_attr_val1.mac_check)
+				return 0;
+			/* and perform auto-read with setting of attributes */
+			result = auto_read(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+#endif
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			/* and perform auto-read with setting of attributes */
+			result = auto_read_attr(caller_pid,
+						target,
+						tid,
+						A_remote_sec_level,
+						A_remote_mac_categories,
+						TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_READ_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-read with setting attributes */
+			result = auto_read(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_check);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (!i_attr_val1.mac_check)
+				return 0;
+			/* and perform auto-read with setting attributes */
+			result = auto_read(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_READ_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-read-write without setting attributes */
+			result = auto_read_write(caller_pid,
+						 target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_check);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (!i_attr_val1.mac_check)
+				return 0;
+			/* and perform auto-read-write with setting of attributes */
+			result = auto_read_write(caller_pid,
+						 target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_SEARCH:
+		switch (target) {
+		case T_DIR:
+		case T_SYMLINK:
+			/* and perform auto-read with setting of attributes */
+			result = auto_read(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_TRACE:
+		switch (target) {
+		case T_PROCESS:
+			/* and perform auto-read-write with setting attributes */
+			result = auto_read_write_attr(caller_pid,
+						      target,
+						      tid,
+						      A_current_sec_level,
+						      A_mac_curr_categories,
+						      TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_WRITE:
+	case R_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_IPC:
+			/* and perform auto-write with setting attributes */
+			result = auto_write(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+		case T_DEV:
+			/* Only check for devices with mac_check set */
+			if (rsbac_get_attr(SW_MAC,
+					   T_DEV,
+					   tid,
+					   A_mac_check,
+					   &i_attr_val1, FALSE)) {
+				rsbac_ds_get_error
+				    ("rsbac_adf_set_attr_mac", A_mac_check);
+				return (-RSBAC_EREADFAILED);
+			}
+			if (!i_attr_val1.mac_check)
+				return 0;
+			/* and perform auto-write with setting attributes */
+			result = auto_write(caller_pid, target, tid, TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+		case T_NETOBJ:
+			/* and perform auto-write with setting attributes */
+			result = auto_write_attr(caller_pid,
+						 target,
+						 tid,
+						 A_remote_sec_level,
+						 A_remote_mac_categories,
+						 TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+#ifdef CONFIG_RSBAC_MAC_NET_OBJ_PROT
+	case R_BIND:
+	case R_LISTEN:
+		switch (target) {
+		case T_NETOBJ:
+			/* and perform auto-write with setting attributes */
+			result = auto_write_attr(caller_pid,
+						 target,
+						 tid,
+						 A_local_sec_level,
+						 A_local_mac_categories,
+						 TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_ACCEPT:
+	case R_CONNECT:
+	case R_SEND:
+	case R_RECEIVE:
+		switch (target) {
+		case T_NETOBJ:
+			/* and perform auto-write with setting attributes */
+			result = auto_write_attr(caller_pid,
+						 target,
+						 tid,
+						 A_remote_sec_level,
+						 A_remote_mac_categories,
+						 TRUE);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return (-RSBAC_EDECISIONMISMATCH);
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+#endif
+	default:
+		return 0;
+	}
+
+	return 0;
+}
diff --git a/rsbac/adf/mac/mac_syscalls.c b/rsbac/adf/mac/mac_syscalls.c
new file mode 100644
index 0000000..ffd97b8
--- /dev/null
+++ b/rsbac/adf/mac/mac_syscalls.c
@@ -0,0 +1,693 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Mandatory Access Control         */
+/* File: rsbac/adf/mac/syscalls.c                    */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/mac.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+#include <rsbac/rkmem.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+static int
+  mac_sys_check_role(enum rsbac_system_role_t role)
+  {
+    union rsbac_target_id_t i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    i_tid.user = __kuid_val(current_uid());
+    if (rsbac_get_attr(SW_MAC,
+                       T_USER,
+                       i_tid,
+                       A_mac_role,
+                       &i_attr_val1,
+                       FALSE))
+      {
+        rsbac_ds_get_error("mac_sys_check_role", A_mac_role);
+        return -EPERM;
+      }
+    /* if correct role, then grant */
+    if (i_attr_val1.system_role == role)
+      return 0;
+    else
+      return -EPERM;
+  }
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+/*****************************************************************************/
+/* This function allows processes to set their own current security level    */
+/* via sys_rsbac_mac_set_curr_seclevel() system call.                        */
+/* The level must keep within the min_write_open/max_read_open-boundary and  */
+/* must not be greater than owner_sec_level. Setting current_sec_level by    */
+/* this function also turns off auto-levelling via mac_auto.                 */
+
+int  rsbac_mac_set_curr_level(rsbac_security_level_t level,
+                              rsbac_mac_category_vector_t categories)
+  {
+    union rsbac_target_id_t       tid;
+    union rsbac_attribute_value_t attr_val1;
+    rsbac_mac_process_flags_t     flags;
+
+    if(   (level > SL_max)
+       && (level != SL_none)
+      )
+      return -RSBAC_EINVALIDVALUE;
+    
+    tid.process = task_pid(current);
+
+    /* check flags */
+    if (rsbac_get_attr(SW_MAC,
+                       T_PROCESS,
+                       tid,
+                       A_mac_process_flags,
+                       &attr_val1,
+                       FALSE))
+      { /* failed! */
+        rsbac_ds_get_error("rsbac_mac_set_curr_level", A_mac_process_flags);
+        return(-RSBAC_EREADFAILED);
+      }
+    flags = attr_val1.mac_process_flags;
+    if(   !(flags & MAC_auto)
+       && !(flags & MAC_trusted)
+       && !(flags & MAC_override)
+      )
+      {
+        rsbac_printk(KERN_INFO
+                     "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): no auto, trusted or override -> not granted \n",
+                     __kuid_val(current_uid()),
+                     current->pid,
+                     current->comm);
+        #ifdef CONFIG_RSBAC_SOFTMODE
+        if(   !rsbac_softmode
+        #ifdef CONFIG_RSBAC_SOFTMODE_IND
+           && !rsbac_ind_softmode[SW_MAC]
+        #endif
+          )
+        #endif
+          return -EPERM;
+      }
+
+    /* override allows full range */
+    if(!(flags & MAC_override))
+      {
+        if(level != SL_none)
+          {
+            /* get maximum security level */
+            tid.process = task_pid(current);
+            if (rsbac_get_attr(SW_MAC,
+                               T_PROCESS,
+                               tid,
+                               A_security_level,
+                               &attr_val1,
+                               FALSE))
+              { /* failed! */
+                rsbac_ds_get_error("rsbac_mac_set_curr_level", A_security_level);
+                return(-RSBAC_EREADFAILED);
+              }
+            /* if level is too high -> error */
+            if (level > attr_val1.security_level)
+              {
+                rsbac_printk(KERN_INFO
+                             "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested level %u over max level %u, no override -> not granted \n",
+                             __kuid_val(current_uid()),
+                             current->pid,
+                             current->comm,
+                             level,
+                             attr_val1.security_level);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_MAC]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+            /* get minimum security level */
+            tid.process = task_pid(current);
+            if (rsbac_get_attr(SW_MAC,
+                               T_PROCESS,
+                               tid,
+                               A_min_security_level,
+                               &attr_val1,
+                               FALSE))
+              { /* failed! */
+                rsbac_ds_get_error("rsbac_mac_set_curr_level", A_min_security_level);
+                return(-RSBAC_EREADFAILED);
+              }
+            /* if level is too low -> error */
+            if (level < attr_val1.security_level)
+              {
+                rsbac_printk(KERN_INFO
+                             "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested level %u under min level %u, no override -> not granted \n",
+                             __kuid_val(current_uid()),
+                             current->pid,
+                             current->comm,
+                             level,
+                             attr_val1.security_level);
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_MAC]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+
+            /* auto needed? -> stay inside boundaries */
+            if(!(flags & MAC_trusted))
+              {
+                /* check against upper/write boundary */ 
+                if (rsbac_get_attr(SW_MAC,
+                                   T_PROCESS,
+                                   tid,
+                                   A_min_write_open,
+                                   &attr_val1,
+                                   FALSE))
+                  { /* failed! */
+                    rsbac_ds_get_error("rsbac_mac_set_curr_level", A_min_write_open);
+                    return(-RSBAC_EREADFAILED);
+                  }
+                if (level > attr_val1.min_write_open)
+                  {
+                    rsbac_printk(KERN_INFO
+                                 "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested level %u over min_write_open %u, no override or trusted -> not granted \n",
+                                 __kuid_val(current_uid()),
+                                 current->pid,
+                                 current->comm,
+                                 level,
+                                 attr_val1.min_write_open);
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    if(   !rsbac_softmode
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                       && !rsbac_ind_softmode[SW_MAC]
+                    #endif
+                      )
+                    #endif
+                      return -EPERM;
+                  }
+
+                /* check against lower/read boundary */ 
+                if (rsbac_get_attr(SW_MAC,
+                                   T_PROCESS,
+                                   tid,
+                                   A_max_read_open,
+                                   &attr_val1,
+                                   FALSE))
+                  { /* failed! */
+                    rsbac_ds_get_error("rsbac_mac_set_curr_level", A_max_read_open);
+                    return(-RSBAC_EREADFAILED);
+                  }
+                if (level < attr_val1.max_read_open)
+                  return -EPERM;
+              }
+          }
+        if(categories != RSBAC_MAC_MIN_CAT_VECTOR)
+          {
+            /* get maximum categories */
+            tid.process = task_pid(current);
+            if (rsbac_get_attr(SW_MAC,
+                               T_PROCESS,
+                               tid,
+                               A_mac_categories,
+                               &attr_val1,
+                               FALSE))
+              { /* failed! */
+                rsbac_ds_get_error("rsbac_mac_set_curr_level", A_mac_categories);
+                return(-RSBAC_EREADFAILED);
+              }
+            /* if categories are no subset -> error */
+            if ((categories & attr_val1.mac_categories) != categories)
+              {
+                char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                if(tmp)
+                  {
+                    char * tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                    if(tmp2)
+                      {
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested categories %s over max categories %s, no override -> not granted \n",
+                                     __kuid_val(current_uid()),
+                                     current->pid,
+                                     current->comm,
+                                     u64tostrmac(tmp, categories),
+                                     u64tostrmac(tmp2, attr_val1.mac_categories));
+                        rsbac_kfree(tmp2);
+                      }
+                    rsbac_kfree(tmp);
+                  }
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_MAC]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+            /* get minimum categories */
+            tid.process = task_pid(current);
+            if (rsbac_get_attr(SW_MAC,
+                               T_PROCESS,
+                               tid,
+                               A_mac_min_categories,
+                               &attr_val1,
+                               FALSE))
+              { /* failed! */
+                rsbac_ds_get_error("rsbac_mac_set_curr_level", A_mac_min_categories);
+                return(-RSBAC_EREADFAILED);
+              }
+            /* if level is too low -> error */
+            if ((categories & attr_val1.mac_categories) != attr_val1.mac_categories)
+              {
+                char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                if(tmp)
+                  {
+                    char * tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                    if(tmp2)
+                      {
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested categories %s under min categories %s, no override -> not granted \n",
+                                     __kuid_val(current_uid()),
+                                     current->pid,
+                                     current->comm,
+                                     u64tostrmac(tmp, categories),
+                                     u64tostrmac(tmp2, attr_val1.mac_categories));
+                        rsbac_kfree(tmp2);
+                      }
+                    rsbac_kfree(tmp);
+                  }
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_MAC]
+                #endif
+                  )
+                #endif
+                  return -EPERM;
+              }
+
+            /* auto needed? -> stay inside boundaries */
+            if(!(flags & MAC_trusted))
+              {
+                /* check against upper/write boundary */ 
+                if (rsbac_get_attr(SW_MAC,
+                                   T_PROCESS,
+                                   tid,
+                                   A_min_write_categories,
+                                   &attr_val1,
+                                   FALSE))
+                  { /* failed! */
+                    rsbac_ds_get_error("rsbac_mac_set_curr_level", A_min_write_categories);
+                    return(-RSBAC_EREADFAILED);
+                  }
+                if ((categories & attr_val1.mac_categories) != categories)
+                  {
+                    char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                    if(tmp)
+                      {
+                        char * tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                        if(tmp2)
+                          {
+                            rsbac_printk(KERN_INFO
+                                         "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested categories %s over min_write categories %s, no override or trusted -> not granted \n",
+                                         __kuid_val(current_uid()),
+                                         current->pid,
+                                         current->comm,
+                                         u64tostrmac(tmp, categories),
+                                         u64tostrmac(tmp2, attr_val1.mac_categories));
+                            rsbac_kfree(tmp2);
+                          }
+                        rsbac_kfree(tmp);
+                      }
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    if(   !rsbac_softmode
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                       && !rsbac_ind_softmode[SW_MAC]
+                    #endif
+                      )
+                    #endif
+                      return -EPERM;
+                  }
+                /* check against lower/read boundary */ 
+                if (rsbac_get_attr(SW_MAC,
+                                   T_PROCESS,
+                                   tid,
+                                   A_max_read_categories,
+                                   &attr_val1,
+                                   FALSE))
+                  { /* failed! */
+                    rsbac_ds_get_error("rsbac_mac_set_curr_level", A_max_read_categories);
+                    return(-RSBAC_EREADFAILED);
+                  }
+                if ((categories & attr_val1.mac_categories) != attr_val1.mac_categories)
+                  {
+                    char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                    if(tmp)
+                      {
+                        char * tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                        if(tmp2)
+                          {
+                            rsbac_printk(KERN_INFO
+                                         "rsbac_mac_set_curr_level(): uid %u, pid %u(%s): requested categories %s under max_read categories %s, no override or trusted -> not granted \n",
+                                         __kuid_val(current_uid()),
+                                         current->pid,
+                                         current->comm,
+                                         u64tostrmac(tmp, categories),
+                                         u64tostrmac(tmp2, attr_val1.mac_categories));
+                            rsbac_kfree(tmp2);
+                          }
+                        rsbac_kfree(tmp);
+                      }
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    if(   !rsbac_softmode
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                       && !rsbac_ind_softmode[SW_MAC]
+                    #endif
+                      )
+                    #endif
+                      return -EPERM;
+                  }
+              }
+          }
+      }
+
+    /* OK, checks passed: set values */
+    if(level != SL_none)
+      {
+        attr_val1.current_sec_level = level;
+        if (rsbac_set_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_current_sec_level,
+                           attr_val1))
+          { /* failed! */
+            rsbac_ds_set_error("rsbac_mac_set_curr_level", A_none);
+            return(-RSBAC_EWRITEFAILED);
+          }
+      }
+    if(categories != RSBAC_MAC_MIN_CAT_VECTOR)
+      {
+        attr_val1.mac_categories = categories;
+        if (rsbac_set_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_mac_curr_categories,
+                           attr_val1))
+          { /* failed! */
+            rsbac_ds_set_error("rsbac_mac_set_curr_level", A_none);
+            return(-RSBAC_EWRITEFAILED);
+          }
+      }
+    return(0);
+  }
+
+/*  getting own levels as well - no restrictions */
+int  rsbac_mac_get_curr_level(rsbac_security_level_t * level_p,
+                              rsbac_mac_category_vector_t * categories_p)
+  {
+    union rsbac_target_id_t       tid;
+    union rsbac_attribute_value_t attr_val;
+
+    tid.process = task_pid(current);
+    if(level_p)
+      {
+        if (rsbac_get_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_current_sec_level,
+                           &attr_val,
+                           FALSE))
+          { /* failed! */
+            rsbac_ds_get_error("rsbac_mac_get_curr_level", A_current_sec_level);
+            return(-RSBAC_EREADFAILED);
+          }
+        *level_p = attr_val.current_sec_level;
+      }
+    if(categories_p)
+      {
+        if (rsbac_get_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_mac_curr_categories,
+                           &attr_val,
+                           FALSE))
+          { /* failed! */
+            rsbac_ds_get_error("rsbac_mac_get_curr_level", A_mac_curr_categories);
+            return(-RSBAC_EREADFAILED);
+          }
+        *categories_p = attr_val.mac_categories;
+      }
+    return 0;
+  }
+
+int  rsbac_mac_get_max_level(rsbac_security_level_t * level_p,
+                              rsbac_mac_category_vector_t * categories_p)
+  {
+    union rsbac_target_id_t       tid;
+    union rsbac_attribute_value_t attr_val;
+
+    tid.process = task_pid(current);
+    if(level_p)
+      {
+        if (rsbac_get_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_security_level,
+                           &attr_val,
+                           FALSE))
+          { /* failed! */
+            rsbac_ds_get_error("rsbac_mac_get_max_level", A_security_level);
+            return(-RSBAC_EREADFAILED);
+          }
+        *level_p = attr_val.security_level;
+      }
+    if(categories_p)
+      {
+        if (rsbac_get_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_mac_categories,
+                           &attr_val,
+                           FALSE))
+          { /* failed! */
+            rsbac_ds_get_error("rsbac_mac_get_max_level", A_mac_categories);
+            return(-RSBAC_EREADFAILED);
+          }
+        *categories_p = attr_val.mac_categories;
+      }
+    return 0;
+  }
+
+
+int  rsbac_mac_get_min_level(rsbac_security_level_t * level_p,
+                              rsbac_mac_category_vector_t * categories_p)
+  {
+    union rsbac_target_id_t       tid;
+    union rsbac_attribute_value_t attr_val;
+
+    tid.process = task_pid(current);
+    if(level_p)
+      {
+        if (rsbac_get_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_min_security_level,
+                           &attr_val,
+                           FALSE))
+          { /* failed! */
+            rsbac_ds_get_error("rsbac_mac_get_min_level", A_min_security_level);
+            return(-RSBAC_EREADFAILED);
+          }
+        *level_p = attr_val.security_level;
+      }
+    if(categories_p)
+      {
+        if (rsbac_get_attr(SW_MAC,
+                           T_PROCESS,
+                           tid,
+                           A_mac_min_categories,
+                           &attr_val,
+                           FALSE))
+          { /* failed! */
+            rsbac_ds_get_error("rsbac_mac_get_min_level", A_mac_min_categories);
+            return(-RSBAC_EREADFAILED);
+          }
+        *categories_p = attr_val.mac_categories;
+      }
+    return 0;
+  }
+
+int rsbac_mac_add_p_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t uid,
+  rsbac_time_t ttl)
+  {
+/* check only in non-maint mode */
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+    if(rsbac_switch_mac)
+#endif
+      {
+        if(mac_sys_check_role(SR_security_officer))
+          {
+            rsbac_printk(KERN_INFO
+                   "rsbac_mac_add_p_tru(): adding MAC trusted user %u to process %u denied for process %u!\n",
+                   uid,
+                   pid,
+                   current->pid);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_MAC]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    /* OK, check passed. Add the truability. */
+    if(rsbac_mac_add_to_p_truset(ta_number, pid, uid, ttl))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_mac_add_p_tru(): rsbac_mac_add_to_p_truset() returned error!\n");
+        return(-RSBAC_EWRITEFAILED);
+      }
+    return 0;
+  }
+
+int rsbac_mac_remove_p_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_pid_t pid,
+  rsbac_uid_t uid)
+  {
+/* check only in non-maint mode */
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+    if(rsbac_switch_mac)
+#endif
+      {
+        if(mac_sys_check_role(SR_security_officer))
+          {
+            rsbac_printk(KERN_INFO
+                   "rsbac_mac_remove_p_tru(): removing MAC trusted user %u from process %u denied for process %u!\n",
+                   uid,
+                   pid,
+                   current->pid);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_MAC]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+    /* OK, check passed. Try to remove the trusted user */
+    return(rsbac_mac_remove_from_p_truset(ta_number, pid, uid));
+  }
+
+int rsbac_mac_add_f_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t uid,
+  rsbac_time_t ttl)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+    if(rsbac_switch_mac)
+#endif
+      {
+        if(mac_sys_check_role(SR_security_officer))
+          {
+            rsbac_printk(KERN_INFO
+                   "rsbac_mac_add_f_tru(): adding MAC trusted user %u to file %u on device %02u:%02u denied for process %u!\n",
+                   uid,
+                   file.inode,
+                   MAJOR(file.device),
+                   MINOR(file.device),
+                   current->pid);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_MAC]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    if(rsbac_mac_add_to_f_truset(ta_number, file, uid, ttl))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_mac_add_f_tru(): rsbac_mac_add_to_f_truset() returned error!\n");
+        return(-RSBAC_EWRITEFAILED);
+      }
+    return 0;
+  }
+
+int rsbac_mac_remove_f_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_mac_file_t file,
+  rsbac_uid_t uid)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+    if(rsbac_switch_mac)
+#endif
+      {
+        if(mac_sys_check_role(SR_security_officer))
+          {
+            rsbac_printk(KERN_INFO
+                   "rsbac_mac_remove_f_tru(): removing MAC trusted user %u from file %u on device %02u:%02u denied for process %u!\n",
+                   uid,
+                   file.inode,
+                   MAJOR(file.device),
+                   MINOR(file.device),
+                   current->pid);
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_MAC]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    return(rsbac_mac_remove_from_f_truset(ta_number, file, uid));
+  }
+
+
+/* end of rsbac/adf/mac/syscalls.c */
diff --git a/rsbac/adf/pax/Makefile b/rsbac/adf/pax/Makefile
new file mode 100644
index 0000000..14181cf
--- /dev/null
+++ b/rsbac/adf/pax/Makefile
@@ -0,0 +1,9 @@
+#
+# File: rsbac/adf/pax/Makefile
+#
+# Makefile for the Linux rsbac pax decision module.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := pax_main.o
diff --git a/rsbac/adf/pax/pax_main.c b/rsbac/adf/pax/pax_main.c
new file mode 100644
index 0000000..3821b97
--- /dev/null
+++ b/rsbac/adf/pax/pax_main.c
@@ -0,0 +1,241 @@
+/**************************************************** */
+/* Rule Set Based Access Control                      */
+/* Implementation of the Access Control Decision      */
+/* Facility (ADF) - PAX                               */
+/* File: rsbac/adf/pax/pax_main.c                     */
+/*                                                    */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org>  */
+/*                                                    */
+/* Last modified: 04/Apr/2016                         */
+/**************************************************** */
+
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/pax_getname.h>
+#include <rsbac/debug.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+/**** PaX set flags func ****/
+#if defined(CONFIG_RSBAC_PAX) && (defined(CONFIG_PAX_HAVE_ACL_FLAGS) || defined(CONFIG_PAX_HOOK_ACL_FLAGS))
+
+#include <linux/binfmts.h>
+
+#if defined(CONFIG_PAX_HAVE_ACL_FLAGS)
+void pax_set_initial_flags(struct linux_binprm * bprm)
+#else
+void rsbac_pax_set_flags_func(struct linux_binprm * bprm)
+#endif
+  {
+    int err;
+    union rsbac_target_id_t tid;
+    union rsbac_attribute_value_t attr_val;
+
+    if(!rsbac_is_initialized())
+      return;
+    tid.file.device = bprm->file->f_path.dentry->d_sb->s_dev;
+    tid.file.inode = bprm->file->f_path.dentry->d_inode->i_ino;
+    tid.file.dentry_p = bprm->file->f_path.dentry;
+    err = rsbac_get_attr(SW_PAX,
+                         T_FILE,
+                         tid,
+                         A_pax_flags,
+                         &attr_val,
+                         FALSE);
+    if(!err)
+      {
+        pax_check_flags(&attr_val.pax_flags);
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_adf_pax)
+          {
+            rsbac_printk(KERN_DEBUG
+                   "rsbac_pax_set_flags_func(): changing flags for process %u from %lx to %lx from device %02u:%02u inode %lu\n",
+                   current->pid,
+                   current->flags & RSBAC_PAX_ALL_FLAGS,
+                   attr_val.pax_flags,
+                   MAJOR(tid.file.device),MINOR(tid.file.device),
+                   tid.file.inode);
+          }
+#endif
+        /* Set flags for process */
+        current->mm->pax_flags = (current->mm->pax_flags & ~RSBAC_PAX_ALL_FLAGS) | attr_val.pax_flags;
+      }
+    else
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_pax_set_flags_func(): get_data for device %02u:%02u, inode %lu returned error %i!\n",
+               MAJOR(tid.file.device),
+               MINOR(tid.file.device),
+               tid.file.inode,
+               err);
+      }
+  }
+#endif
+
+
+inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request_pax (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)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    switch (request)
+      {
+        case R_MODIFY_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_system_role:
+                case A_pax_role:
+                case A_pax_flags:
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_PAX,
+                                     T_USER,
+                                     i_tid,
+                                     A_pax_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_pax()", A_pax_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_READ_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_system_role:
+                case A_pax_role:
+                case A_pax_flags:
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer or Admin? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_PAX,
+                                     T_USER,
+                                     i_tid,
+                                     A_pax_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_pax()", A_pax_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if(   (i_attr_val1.system_role == SR_security_officer)
+                     || (i_attr_val1.system_role == SR_administrator)
+                    )
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_LOG:
+            switch(target)
+              {
+                case T_NONE:
+                  /* test owner's pax_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_PAX,
+                                     T_USER,
+                                     i_tid,
+                                     A_pax_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_pax()", A_pax_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are unknown */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_MODULE:
+            switch(target)
+              {
+                case T_NONE:
+                  /* we need the switch_target */
+                  if(attr != A_switch_target)
+                    return NOT_GRANTED;
+                  /* do not care for other modules */
+                  if(   (attr_val.switch_target != SW_PAX)
+                     #ifdef CONFIG_RSBAC_SOFTMODE
+                     && (attr_val.switch_target != SW_SOFTMODE)
+                     #endif
+                     #ifdef CONFIG_RSBAC_FREEZE
+                     && (attr_val.switch_target != SW_FREEZE)
+                     #endif
+                    )
+                    return(DO_NOT_CARE);
+                  /* test owner's pax_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_PAX,
+                                     T_USER,
+                                     i_tid,
+                                     A_pax_role,
+                                     &i_attr_val1,
+                                     FALSE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_pax()", A_pax_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are unknown */
+                default: return(DO_NOT_CARE);
+              }
+
+/*********************/
+        default: return DO_NOT_CARE;
+      }
+
+    return DO_NOT_CARE;
+  } /* end of rsbac_adf_request_pax() */
+
+
+/* end of rsbac/adf/pax/pax_main.c */
diff --git a/rsbac/adf/rc/Makefile b/rsbac/adf/rc/Makefile
new file mode 100644
index 0000000..445ecad
--- /dev/null
+++ b/rsbac/adf/rc/Makefile
@@ -0,0 +1,9 @@
+#
+# File: rsbac/adf/rc/Makefile
+#
+# Makefile for the Linux rsbac rc decision module.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+obj-y    := rc_syscalls.o rc_main.o
diff --git a/rsbac/adf/rc/rc_main.c b/rsbac/adf/rc/rc_main.c
new file mode 100644
index 0000000..6fa9725
--- /dev/null
+++ b/rsbac/adf/rc/rc_main.c
@@ -0,0 +1,3285 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Role Compatibility               */
+/* File: rsbac/adf/rc/main.c                         */
+/*                                                   */
+/* Author and (c) 1999-2017: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 04/Jan/2017                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/rc.h>
+#include <rsbac/error.h>
+#include <rsbac/debug.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/rc_getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/network.h>
+#include <rsbac/rc_types.h>
+#include <rsbac/lists.h>
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+#ifdef CONFIG_RSBAC_RC_LEARN_TA
+rsbac_list_ta_number_t rc_learn_ta = CONFIG_RSBAC_RC_LEARN_TA;
+#else
+rsbac_list_ta_number_t rc_learn_ta = 0;
+#endif
+#endif
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+static enum rsbac_adf_req_ret_t
+check_comp_rc(enum rsbac_target_t target,
+	      union rsbac_target_id_t tid,
+	      enum rsbac_adf_request_t request, rsbac_pid_t caller_pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	enum rsbac_attribute_t i_attr;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_attribute_value_t i_attr_val2;
+
+	union rsbac_rc_target_id_t i_rc_subtid;
+	enum rsbac_rc_item_t i_rc_item;
+
+	/* get rc_role from process */
+	i_tid.process = caller_pid;
+	if ((err = rsbac_get_attr(SW_RC,
+				  T_PROCESS,
+				  i_tid,
+				  A_rc_role, &i_attr_val1, FALSE))) {
+		rsbac_pr_get_error(A_rc_role);
+		return NOT_GRANTED;
+	}
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		i_rc_item = RI_type_comp_fd;
+		i_attr = A_rc_type_fd;
+		break;
+	case T_DEV:
+		i_rc_item = RI_type_comp_dev;
+		i_attr = A_rc_type;
+		break;
+	case T_USER:
+		i_rc_item = RI_type_comp_user;
+		i_attr = A_rc_type;
+		break;
+	case T_PROCESS:
+		i_rc_item = RI_type_comp_process;
+		i_attr = A_rc_type;
+		break;
+	case T_IPC:
+		i_rc_item = RI_type_comp_ipc;
+		i_attr = A_rc_type;
+		break;
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	case T_GROUP:
+		i_rc_item = RI_type_comp_group;
+		i_attr = A_rc_type;
+		break;
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_DEV_PROT)
+	case T_NETDEV:
+		i_rc_item = RI_type_comp_netdev;
+		i_attr = A_rc_type;
+		break;
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+	case T_NETTEMP:
+		i_rc_item = RI_type_comp_nettemp;
+		i_attr = A_rc_type_nt;
+		break;
+	case T_NETOBJ:
+		i_rc_item = RI_type_comp_netobj;
+		if (rsbac_net_remote_request(request))
+			i_attr = A_remote_rc_type;
+		else
+			i_attr = A_local_rc_type;
+		break;
+#endif
+	default:
+		rsbac_printk(KERN_WARNING "check_comp_rc(): invalid target %i!\n",
+			     target);
+		return NOT_GRANTED;
+	}
+
+	/* get rc_type[_fd|_nt] from target */
+	if ((err = rsbac_get_attr(SW_RC,
+				  target,
+				  tid, i_attr, &i_attr_val2, TRUE))) {
+		rsbac_pr_get_error(i_attr);
+		return NOT_GRANTED;
+	}
+
+	/* get type_comp_xxx of role */
+	i_rc_subtid.type = i_attr_val2.rc_type;
+	if (rsbac_rc_check_comp(i_attr_val1.rc_role,
+				i_rc_subtid, i_rc_item, request)) {
+#ifdef CONFIG_RSBAC_DEBUG
+		if (rsbac_debug_adf_rc && (request <= R_NONE) && (rsbac_log_levels[request][target] == LL_full)) {
+			char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+			if (tmp) {
+				char *tmp2 =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+				if (tmp2) {
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+					u_int pseudo = 0;
+					union rsbac_attribute_value_t i_attr_val3;
+
+					/* Get owner's logging pseudo */
+					i_tid.user = __kuid_val(current_uid());
+					if (!rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val3,FALSE)) {
+						pseudo = i_attr_val3.pseudo;
+					}
+					if (pseudo)
+						rsbac_pr_debug(adf_rc, "pid %u(%s), pseudo %u, rc_role %u, %s rc_type %u, request %s -> GRANTED!\n",
+							     pid_nr(caller_pid),
+							     current->comm,
+							     pseudo,
+							     i_attr_val1.rc_role,
+							     get_target_name_only
+							     (tmp, target),
+							     i_attr_val2.rc_type,
+							     get_rc_special_right_name
+								     (tmp2, request));
+					else
+#endif
+						rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, %s rc_type %u, request %s -> GRANTED!\n",
+							     pid_nr(caller_pid),
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     i_attr_val1.rc_role,
+							     get_target_name_only
+								     (tmp, target),
+							     i_attr_val2.rc_type,
+							     get_rc_special_right_name
+								     (tmp2, request));
+					rsbac_kfree(tmp2);
+				}
+				rsbac_kfree(tmp);
+			}
+		}
+#endif
+		return GRANTED;
+	} else {
+#ifdef CONFIG_RSBAC_DEBUG
+		if (rsbac_debug_adf_rc && ( (request > R_NONE) || (rsbac_log_levels[request][target] != LL_none) ) ) {
+			char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+			if (tmp) {
+				char *tmp2 =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+				if (tmp2) {
+#if defined(CONFIG_RSBAC_RC_LEARN)
+					if (rsbac_rc_learn) {
+						union rsbac_rc_target_id_t i_rc_tid;
+						union rsbac_rc_item_value_t i_rc_value;
+
+						i_rc_tid.role = i_attr_val1.rc_role;
+#ifdef CONFIG_RSBAC_RC_LEARN_TA
+						if (!rsbac_list_ta_exist(rc_learn_ta))
+							rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+									&rc_learn_ta,
+									RSBAC_ALL_USERS,
+									RSBAC_RC_LEARN_TA_NAME,
+									NULL);
+#endif
+						err = rsbac_rc_get_item (rc_learn_ta,
+									RT_ROLE,
+									i_rc_tid,
+									i_rc_subtid,
+									i_rc_item,
+									&i_rc_value,
+									NULL);
+						if (!err) {
+							i_rc_value.rights |= RSBAC_RC_RIGHTS_VECTOR(request);
+							err = rsbac_rc_set_item (rc_learn_ta,
+										RT_ROLE,
+										i_rc_tid,
+										i_rc_subtid,
+										i_rc_item,
+										i_rc_value,
+										RSBAC_LIST_TTL_KEEP);
+							if (!err) {
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+								u_int pseudo = 0;
+								union rsbac_attribute_value_t i_attr_val3;
+
+				          /* Get owner's logging pseudo */
+						        	i_tid.user = __kuid_val(current_uid());
+				        			if (!rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val3,FALSE)) {
+					        			pseudo = i_attr_val3.pseudo;
+								}
+								if (pseudo) {
+									rsbac_printk(KERN_INFO "check_comp_rc(): learning mode: pid %u(%s), pseudo %u, rc_role %u, %s rc_type %u, right %s added to transaction %u!\n",
+										     pid_nr(caller_pid),
+										     current->comm,
+										     pseudo,
+										     i_attr_val1.rc_role,
+										     get_target_name_only
+										     (tmp, target),
+										     i_attr_val2.rc_type,
+										     get_rc_special_right_name
+											     (tmp2, request),
+										     rc_learn_ta);
+								} else
+#endif
+								rsbac_printk(KERN_INFO "check_comp_rc(): learning mode: pid %u(%s), owner %u, rc_role %u, %s rc_type %u, right %s added to transaction %u!\n",
+									     pid_nr(caller_pid),
+									     current->comm,
+									     __kuid_val(current_uid()),
+									     i_attr_val1.rc_role,
+									     get_target_name_only
+										     (tmp, target),
+									     i_attr_val2.rc_type,
+									     get_rc_special_right_name
+										     (tmp2, request),
+									     rc_learn_ta);
+								rsbac_kfree(tmp2);
+								rsbac_kfree(tmp);
+								return GRANTED;
+							}
+						}
+					}
+#endif
+					{
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+						u_int pseudo = 0;
+						union rsbac_attribute_value_t i_attr_val3;
+
+				          /* Get owner's logging pseudo */
+				        	i_tid.user = __kuid_val(current_uid());
+				        	if (!rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val3,FALSE)) {
+					        	pseudo = i_attr_val3.pseudo;
+						}
+						if (pseudo) {
+							rsbac_pr_debug(adf_rc, "pid %u(%s), pseudo %u, rc_role %u, %s rc_type %u, request %s -> NOT_GRANTED!\n",
+								     pid_nr(caller_pid),
+								     current->comm,
+								     pseudo,
+								     i_attr_val1.rc_role,
+								     get_target_name_only
+								     (tmp, target),
+								     i_attr_val2.rc_type,
+								     get_rc_special_right_name
+									     (tmp2, request));
+						} else
+#endif
+						rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, %s rc_type %u, request %s -> NOT_GRANTED!\n",
+							     pid_nr(caller_pid),
+							     current->comm,
+							     __kuid_val(current_uid()),
+							     i_attr_val1.rc_role,
+							     get_target_name_only
+								     (tmp, target),
+							     i_attr_val2.rc_type,
+							     get_rc_special_right_name
+								     (tmp2, request));
+					}
+					rsbac_kfree(tmp2);
+				}
+				rsbac_kfree(tmp);
+			}
+		}
+#endif
+		return NOT_GRANTED;
+	}
+}
+
+static enum rsbac_adf_req_ret_t
+check_comp_rc_scd(enum rsbac_rc_scd_type_t scd_type,
+		  enum rsbac_adf_request_t request, rsbac_pid_t caller_pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	union rsbac_rc_target_id_t i_rc_subtid;
+
+	/* get rc_role from process */
+	i_tid.process = caller_pid;
+	if ((err = rsbac_get_attr(SW_RC,
+				  T_PROCESS,
+				  i_tid,
+				  A_rc_role, &i_attr_val1, FALSE))) {
+		rsbac_pr_get_error(A_rc_role);
+		return NOT_GRANTED;
+	}
+	/* get type_comp_scd of role */
+	i_rc_subtid.type = scd_type;
+	if (rsbac_rc_check_comp(i_attr_val1.rc_role,
+				i_rc_subtid, RI_type_comp_scd, request)) {
+		return GRANTED;
+	} else {
+#if defined(CONFIG_RSBAC_RC_LEARN) || defined(CONFIG_RSBAC_DEBUG)
+		char tmp[RSBAC_MAXNAMELEN];
+#endif
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+		if (rsbac_rc_learn) {
+			union rsbac_rc_target_id_t i_rc_tid;
+			union rsbac_rc_item_value_t i_rc_value;
+
+			i_rc_tid.role = i_attr_val1.rc_role;
+#ifdef CONFIG_RSBAC_RC_LEARN_TA
+			if (!rsbac_list_ta_exist(rc_learn_ta))
+				rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+						&rc_learn_ta,
+						RSBAC_ALL_USERS,
+						RSBAC_RC_LEARN_TA_NAME,
+						NULL);
+#endif
+			err = rsbac_rc_get_item (rc_learn_ta,
+						RT_ROLE,
+						i_rc_tid,
+						i_rc_subtid,
+						RI_type_comp_scd,
+						&i_rc_value,
+						NULL);
+			if (!err) {
+				i_rc_value.rights |= RSBAC_RC_RIGHTS_VECTOR(request);
+				err = rsbac_rc_set_item (rc_learn_ta,
+							RT_ROLE,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_scd,
+							i_rc_value,
+							RSBAC_LIST_TTL_KEEP);
+				if (!err) {
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+					u_int pseudo = 0;
+					union rsbac_attribute_value_t i_attr_val3;
+
+	        /* Get owner's logging pseudo */
+				        i_tid.user = __kuid_val(current_uid());
+				        if (!rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val3,FALSE)) {
+					        pseudo = i_attr_val3.pseudo;
+					}
+					if (pseudo) {
+						rsbac_printk(KERN_INFO "check_comp_rc_scd(): learning mode: pid %u(%s), pseudo %u, rc_role %i, scd_type %i, right %s added to transaction %u!\n",
+							       pid_nr(caller_pid), current->comm, pseudo,
+							       i_attr_val1.rc_role, scd_type,
+							       get_request_name(tmp, request),
+							       rc_learn_ta);
+					} else
+#endif
+					rsbac_printk(KERN_INFO "check_comp_rc_scd(): learning mode: pid %u(%s), owner %u, rc_role %i, scd_type %i, right %s added to transaction %u!\n",
+						       pid_nr(caller_pid), current->comm, __kuid_val(current_uid()),
+						       i_attr_val1.rc_role, scd_type,
+						       get_request_name(tmp, request),
+						       rc_learn_ta);
+					return GRANTED;
+				}
+			}
+		}
+#endif
+		if (rsbac_debug_adf_rc && ( (request > R_NONE) || (rsbac_log_levels[request][T_SCD] != LL_none) ) ) {
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+			u_int pseudo = 0;
+			union rsbac_attribute_value_t i_attr_val3;
+
+		        /* Get owner's logging pseudo */
+		        i_tid.user = __kuid_val(current_uid());
+		        if (!rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val3,FALSE)) {
+			        pseudo = i_attr_val3.pseudo;
+			}
+			if (pseudo) {
+				rsbac_pr_debug(adf_rc, "pid %u(%s), pseudo %u, rc_role %i, scd_type %i, request %s -> NOT_GRANTED!\n",
+					       pid_nr(caller_pid), current->comm, pseudo,
+					       i_attr_val1.rc_role, scd_type,
+					       get_request_name(tmp, request));
+			} else
+#endif
+			rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %i, scd_type %i, request %s -> NOT_GRANTED!\n",
+				       pid_nr(caller_pid), current->comm, __kuid_val(current_uid()),
+				       i_attr_val1.rc_role, scd_type,
+				       get_request_name(tmp, request));
+		}
+		return NOT_GRANTED;
+	}
+}
+
+static enum rsbac_adf_req_ret_t
+rc_check_create(
+	rsbac_pid_t caller_pid,
+	enum rsbac_target_t target,
+	union rsbac_rc_target_id_t tid,
+	union rsbac_rc_target_id_t subtid,
+	enum rsbac_rc_item_t item)
+{
+	if (rsbac_rc_check_comp(tid.role, subtid, item, R_CREATE))
+		return GRANTED;
+	else {
+		char tmp[RSBAC_MAXNAMELEN];
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+		if (rsbac_rc_learn) {
+			union rsbac_rc_item_value_t i_rc_value;
+			int err;
+
+#ifdef CONFIG_RSBAC_RC_LEARN_TA
+			if (!rsbac_list_ta_exist(rc_learn_ta))
+				rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+						&rc_learn_ta,
+						RSBAC_ALL_USERS,
+						RSBAC_RC_LEARN_TA_NAME,
+						NULL);
+#endif
+			err = rsbac_rc_get_item (rc_learn_ta,
+						RT_ROLE,
+						tid,
+						subtid,
+						item,
+						&i_rc_value,
+						NULL);
+			if (!err) {
+				i_rc_value.rights |= RSBAC_RC_RIGHTS_VECTOR(R_CREATE);
+				err = rsbac_rc_set_item (rc_learn_ta,
+							RT_ROLE,
+							tid,
+							subtid,
+							item,
+							i_rc_value,
+							RSBAC_LIST_TTL_KEEP);
+				if (!err) {
+#ifdef CONFIG_RSBAC_LOG_PSEUDO
+					u_int pseudo = 0;
+					union rsbac_target_id_t i_tid;
+					union rsbac_attribute_value_t i_attr_val3;
+
+				          /* Get owner's logging pseudo */
+			        	i_tid.user = __kuid_val(current_uid());
+	        			if (!rsbac_get_attr(SW_GEN,T_USER,i_tid,A_pseudo,&i_attr_val3,FALSE)) {
+		        			pseudo = i_attr_val3.pseudo;
+					}
+					if (pseudo) {
+						rsbac_printk(KERN_INFO "rc_check_create(): learning mode: pid %u(%s), pseudo %u, rc_role %u, %s rc_type %u, right CREATE added to transaction %u!\n",
+							     pid_nr(caller_pid),
+							     current->comm,
+							     pseudo,
+							     tid.role,
+							     get_target_name_only
+							     (tmp, target),
+							     subtid.type,
+							     rc_learn_ta);
+					} else
+#endif
+					rsbac_printk(KERN_INFO "rc_check_create(): learning mode: pid %u(%s), owner %u, rc_role %u, %s rc_type %u, right CREATE added to transaction %u!\n",
+						     pid_nr(caller_pid),
+						     current->comm,
+						     __kuid_val(current_uid()),
+						     tid.role,
+						     get_target_name_only
+							     (tmp, target),
+						     subtid.type,
+						     rc_learn_ta);
+					return GRANTED;
+				}
+			}
+		}
+#endif
+		rsbac_printk(KERN_WARNING "rc_check_create(): rc_role %i has no CREATE right on its %s def_create_type %i -> NOT_GRANTED!\n",
+			     tid.role,
+			     get_target_name_only (tmp, target),
+			     subtid.type);
+		return NOT_GRANTED;
+	}
+}
+
+/* exported for rc_syscalls.c */
+int rsbac_rc_test_admin_roles(rsbac_rc_role_id_t t_role,
+			      rsbac_boolean_t modify)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_rc_target_id_t i_rc_subtid;
+
+	if (t_role > RC_role_max_value)
+		return -RSBAC_EINVALIDVALUE;
+	/* get rc_role of process */
+	i_tid.process = task_pid(current);
+	if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+				  i_tid, A_rc_role, &i_attr_val1, FALSE))) {
+		rsbac_pr_get_error(A_rc_role);
+		return -RSBAC_EREADFAILED;
+	}
+
+	i_rc_subtid.role = t_role;
+	/* read_only? -> assign_roles membership is enough */
+	if (!modify) {
+		if (rsbac_rc_check_comp(i_attr_val1.rc_role,
+					i_rc_subtid,
+					RI_assign_roles, R_NONE))
+			return 0;
+		/* fall through */
+	}
+	/* check admin_roles of role */
+	if (rsbac_rc_check_comp(i_attr_val1.rc_role,
+				i_rc_subtid, RI_admin_roles, R_NONE))
+		return 0;
+
+        if (t_role <= RC_role_max_value)
+	        rsbac_pr_debug(adf_rc,
+			"rsbac_rc_test_admin_roles(): role %u not in admin roles of role %u, pid %u, user %u!\n",
+			t_role,
+			i_attr_val1.rc_role,
+			current->pid,
+			__kuid_val(current_uid()));
+	return -EPERM;
+}
+
+/* exported for rc_syscalls.c */
+int rsbac_rc_test_assign_roles(enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_attribute_t attr,
+			       rsbac_rc_role_id_t t_role)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_attribute_value_t i_attr_val2;
+	union rsbac_rc_target_id_t i_rc_subtid;
+
+	if (target >= T_NONE)
+		return -RSBAC_EINVALIDVALUE;
+	/* get rc_role of process */
+	i_tid.process = task_pid(current);
+	if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+				  i_tid, A_rc_role, &i_attr_val1, FALSE))) {
+		rsbac_pr_get_error(A_rc_role);
+		return -RSBAC_EREADFAILED;
+	}
+	/* get old role of target */
+	if ((err = rsbac_get_attr(SW_RC,
+				  target,
+				  tid, attr, &i_attr_val2, TRUE))) {
+		rsbac_pr_get_error(attr);
+		return -RSBAC_EREADFAILED;
+	}
+
+	i_rc_subtid.role = i_attr_val2.rc_role;
+	if (!rsbac_rc_check_comp(i_attr_val1.rc_role,
+				 i_rc_subtid, RI_assign_roles, R_NONE)) {
+                if (i_attr_val2.rc_role <= RC_role_max_value)
+                        rsbac_pr_debug(adf_rc,
+                               "rsbac_rc_test_assign_roles(): old role %u not in assign roles of role %u, pid %u, user %u!\n",
+                               i_attr_val2.rc_role,
+                               i_attr_val1.rc_role,
+                               current->pid,
+                               __kuid_val(current_uid()));
+		return -EPERM;
+	}
+	i_rc_subtid.role = t_role;
+	if (!rsbac_rc_check_comp(i_attr_val1.rc_role,
+				 i_rc_subtid,
+				 RI_assign_roles, R_NONE)) {
+                if (t_role <= RC_role_max_value)
+                        rsbac_pr_debug(adf_rc,
+       	                       "rsbac_rc_test_assign_roles(): new role %u not in assign roles of role %u, pid %u, user %u!\n",
+               	               t_role,
+                       	       i_attr_val1.rc_role,
+                               current->pid,
+       	                       __kuid_val(current_uid()));
+		return -EPERM;
+	}
+	return 0;
+}
+
+enum rsbac_adf_req_ret_t
+rsbac_rc_check_type_comp(enum rsbac_target_t target,
+			 rsbac_rc_type_id_t type,
+			 enum rsbac_rc_special_rights_t request,
+			 rsbac_pid_t caller_pid)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	union rsbac_rc_target_id_t i_rc_subtid;
+	enum rsbac_rc_item_t i_rc_item;
+
+	if (!caller_pid)
+		caller_pid = task_pid(current);
+	/*
+	 * we don't care about tried assignments of special type values,
+	 * but deny other accesses to those
+	 */
+	if (type > RC_type_max_value) {
+		if (request == RCR_ASSIGN)
+			return GRANTED;
+		else
+			return NOT_GRANTED;
+	}
+
+	/* get rc_role from process */
+	i_tid.process = caller_pid;
+	if ((err = rsbac_get_attr(SW_RC,
+				  T_PROCESS,
+				  i_tid,
+				  A_rc_role, &i_attr_val1, FALSE))) {
+		rsbac_pr_get_error(A_rc_role);
+		return NOT_GRANTED;
+	}
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	case T_FD:
+		i_rc_item = RI_type_comp_fd;
+		break;
+	case T_DEV:
+		i_rc_item = RI_type_comp_dev;
+		break;
+	case T_USER:
+		i_rc_item = RI_type_comp_user;
+		break;
+	case T_PROCESS:
+		i_rc_item = RI_type_comp_process;
+		break;
+	case T_IPC:
+		i_rc_item = RI_type_comp_ipc;
+		break;
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	case T_GROUP:
+		i_rc_item = RI_type_comp_group;
+		break;
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_DEV_PROT)
+	case T_NETDEV:
+		i_rc_item = RI_type_comp_netdev;
+		break;
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+	case T_NETTEMP:
+		i_rc_item = RI_type_comp_nettemp;
+		break;
+	case T_NETOBJ:
+		i_rc_item = RI_type_comp_netobj;
+		break;
+#endif
+
+	default:
+		rsbac_printk(KERN_WARNING "rsbac_rc_check_type_comp(): invalid target %i!\n",
+			     target);
+		return NOT_GRANTED;
+	}
+	/* check type_comp_xxx of role */
+	i_rc_subtid.type = type;
+	if (rsbac_rc_check_comp(i_attr_val1.rc_role,
+				i_rc_subtid, i_rc_item, request))
+		return GRANTED;
+	else {
+#ifdef CONFIG_RSBAC_DEBUG
+		if (rsbac_debug_adf_rc && ( (request > (enum rsbac_rc_special_rights_t) R_NONE) || (rsbac_log_levels[request][target] != LL_none) ) ) {
+			char tmp[50];
+			char tmp2[RSBAC_MAXNAMELEN];
+
+			rsbac_pr_debug(adf_rc, "rc_role is %i, %s rc_type is %i, request is %s -> NOT_GRANTED!\n",
+				       i_attr_val1.rc_role,
+				       get_target_name_only(tmp, target),
+				       type,
+				       get_rc_special_right_name(tmp2, request));
+		}
+#endif
+		return NOT_GRANTED;
+	}
+}
+
+/* exported for rc_syscalls.c */
+int rsbac_rc_test_role_admin(rsbac_boolean_t modify)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_rc_target_id_t i_rc_tid;
+	union rsbac_rc_item_value_t i_rc_item_val1;
+
+	/* get rc_role of process */
+	i_tid.process = task_pid(current);
+	if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+				  i_tid, A_rc_role, &i_attr_val1, FALSE))) {
+		rsbac_pr_get_error(A_rc_role);
+		return -RSBAC_EREADFAILED;
+	}
+
+	/* get admin_type of role */
+	i_rc_tid.role = i_attr_val1.rc_role;
+	if ((err = rsbac_rc_get_item(0, RT_ROLE, i_rc_tid, i_rc_tid,	/* dummy */
+				     RI_admin_type,
+				     &i_rc_item_val1, NULL))) {
+		rsbac_rc_pr_get_error(RI_admin_type);
+		return -RSBAC_EREADFAILED;
+	}
+
+	/* allow, if RC_role_admin or (read_only and RC_system_admin) */
+	if ((i_rc_item_val1.admin_type == RC_role_admin)
+	    || (!modify && (i_rc_item_val1.admin_type == RC_system_admin)
+	    )
+	    )
+		return 0;
+	else
+		return -EPERM;
+}
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+inline enum rsbac_adf_req_ret_t
+rsbac_adf_request_rc(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)
+{
+	int err;
+	enum rsbac_adf_req_ret_t result = DO_NOT_CARE;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_rc_target_id_t i_rc_tid;
+	union rsbac_rc_target_id_t i_rc_subtid;
+	union rsbac_rc_item_value_t i_rc_item_val1;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val2;
+
+	switch (request) {
+	case R_SEARCH:
+		switch (target) {
+		case T_DIR:
+		case T_FILE:
+		case T_SYMLINK:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CLOSE:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_GET_STATUS_DATA:
+		switch (target) {
+		case T_SCD:
+			return check_comp_rc_scd
+				(tid.scd, request, caller_pid);
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+		case T_IPC:
+		case T_PROCESS:
+		case T_DEV:
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+#if defined(CONFIG_RSBAC_RC_NET_DEV_PROT)
+		case T_NETDEV:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SEND:
+		switch (target) {
+		case T_DEV:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+                case T_UNIXSOCK:
+                case T_IPC:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_UNIX_PROCESS)
+			if (attr == A_process) {
+				enum rsbac_adf_req_ret_t tmp_result;
+
+				i_tid.process = attr_val.process;
+				tmp_result = check_comp_rc(T_PROCESS, i_tid,
+							R_SEND,
+							caller_pid);
+				if ((tmp_result == NOT_GRANTED)
+				    || (tmp_result == UNDEFINED)
+				    )
+					return tmp_result;
+			}
+#endif				/* UNIX_PROCESS */
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+
+			/* all other cases are undefined */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_LISTEN:
+	case R_NET_SHUTDOWN:
+		switch (target) {
+                case T_UNIXSOCK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are undefined */
+		default:
+			return DO_NOT_CARE;
+		}
+	case R_ACCEPT:
+	case R_CONNECT:
+	case R_RECEIVE:
+		switch (target) {
+                case T_UNIXSOCK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_UNIX_PROCESS)
+			if (attr == A_process) {
+				enum rsbac_adf_req_ret_t tmp_result;
+
+				i_tid.process = attr_val.process;
+				tmp_result = check_comp_rc(T_PROCESS, i_tid,
+							  request,
+							  caller_pid);
+				if ((tmp_result == NOT_GRANTED)
+				    || (tmp_result == UNDEFINED)
+				    )
+					return tmp_result;
+			}
+#endif				/* UNIX_PROCESS */
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif
+
+			/* all other cases are undefined */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_READ:
+	case R_WRITE:
+		switch (target) {
+		case T_DIR:
+#ifdef CONFIG_RSBAC_RW
+		case T_FILE:
+		case T_FIFO:
+		case T_DEV:
+#endif
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+#if defined(CONFIG_RSBAC_NET_OBJ_RW)
+		case T_NETTEMP:
+#endif
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+#ifdef CONFIG_RSBAC_RW
+		case T_IPC:
+                case T_UNIXSOCK:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_UNIX_PROCESS)
+			if (attr == A_process) {
+				enum rsbac_adf_req_ret_t tmp_result;
+
+				i_tid.process = attr_val.process;
+				if (request == R_READ)
+					tmp_result =
+					    check_comp_rc(T_PROCESS, i_tid,
+							  R_RECEIVE,
+							  caller_pid);
+				else
+					tmp_result =
+					    check_comp_rc(T_PROCESS, i_tid,
+							  R_SEND,
+							  caller_pid);
+				if ((tmp_result == NOT_GRANTED)
+				    || (tmp_result == UNDEFINED)
+				    )
+					return tmp_result;
+			}
+#endif				/* UNIX_PROCESS */
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif				/* RW */
+
+		case T_SCD:
+			return check_comp_rc_scd
+				(tid.scd, request, caller_pid);
+
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+#if defined(CONFIG_RSBAC_NET_OBJ_RW)
+		case T_NETOBJ:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MOVETO:
+		switch (target) {
+		case T_DIR:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_APPEND_OPEN:
+	case R_READ_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_DEV:
+		case T_FIFO:
+		case T_IPC:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MAP_EXEC:
+		switch (target) {
+		case T_FILE:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+		case T_NONE:
+			/* anonymous mapping */
+			return check_comp_rc_scd
+				(ST_other, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CHANGE_GROUP:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CHANGE_OWNER:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_IPC:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+#ifdef CONFIG_RSBAC_USER_CHOWN
+		case T_USER:
+#if defined(CONFIG_RSBAC_AUTH)
+			result = check_comp_rc(target, tid, request, caller_pid);
+			if((result == GRANTED) || (result == DO_NOT_CARE))
+				return result;
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_AUTH, T_PROCESS,
+						  i_tid,
+						  A_auth_last_auth,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_auth_last_auth);
+				return NOT_GRANTED;
+			}
+			if(i_attr_val1.auth_last_auth != tid.user)
+				return NOT_GRANTED;
+			else
+				return check_comp_rc(target, tid, RCR_CHANGE_AUTHED_OWNER, caller_pid);
+#else
+			return check_comp_rc(target, tid, request, caller_pid);
+#endif
+#endif
+
+		case T_PROCESS:
+			/* get rc_role from process */
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_process_chown_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0, RT_ROLE, i_rc_tid, i_rc_tid,	/* dummy */
+						     RI_def_process_chown_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_process_chown_type);
+				return NOT_GRANTED;
+			}
+			if ((i_rc_item_val1.type_id == RC_type_no_chown)
+			    || (i_rc_item_val1.type_id ==
+				RC_type_no_create)
+			    )
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CHDIR:
+		switch (target) {
+		case T_DIR:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_CLONE:
+		if (target == T_PROCESS) {
+			/* check, whether we may create process of def_process_create_type */
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_process_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_process_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_process_create_type);
+				return NOT_GRANTED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_process_create_type no_create, request CLONE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return NOT_GRANTED;
+
+			case RC_type_use_new_role_def_create:
+			case RC_type_use_fd:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type use_new_role_def_create in def_process_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				return GRANTED;
+
+			default:
+				/* check, whether role has CREATE right to new type */
+				/* check type_comp_process of role */
+				i_rc_subtid.type = i_rc_item_val1.type_id;
+				return rc_check_create(caller_pid,
+							target,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_process);
+			}
+		} else
+			return DO_NOT_CARE;
+
+		/* Creating dir or (pseudo) file IN target dir! */
+	case R_CREATE:
+		switch (target) {
+		case T_DIR:
+			/* check, whether we may create files/dirs in this dir */
+			result =
+			    check_comp_rc(target, tid, request,
+					  caller_pid);
+			if ((result != GRANTED) && (result != DO_NOT_CARE))
+				return result;
+
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* Check, whether this process has a preselected type */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_select_type,
+						  &i_attr_val2, FALSE))) {
+				rsbac_pr_get_error(A_rc_select_type);
+				return NOT_GRANTED;
+			}
+			if (i_attr_val2.rc_select_type == RC_type_use_fd) {
+				/* get def_fd_create_type of role */
+				/* First get target dir's efftype */
+				if ((err = rsbac_get_attr(SW_RC,
+						  target,
+						  tid,
+						  A_rc_type_fd,
+						  &i_attr_val2, TRUE))) {
+					rsbac_pr_get_error(A_rc_type_fd);
+					return NOT_GRANTED;
+				}
+				i_rc_tid.role = i_attr_val1.rc_role;
+				i_rc_subtid.type = i_attr_val2.rc_type;
+				if ((err = rsbac_rc_get_item(0, RT_ROLE, i_rc_tid, i_rc_subtid, RI_def_fd_ind_create_type, &i_rc_item_val1, NULL))) {	/* No individual create type -> try global */
+					if ((err = rsbac_rc_get_item(0,
+							     RT_ROLE,
+							     i_rc_tid,
+							     i_rc_subtid,
+							     RI_def_fd_create_type,
+							     &i_rc_item_val1,
+							     NULL))) {
+						rsbac_rc_pr_get_error
+						    (RI_def_fd_create_type);
+						return NOT_GRANTED;
+					}
+				}
+			} else
+				i_rc_item_val1.type_id = i_attr_val2.rc_select_type;
+			
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_inherit_parent:
+				return GRANTED;
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_fd_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return NOT_GRANTED;
+
+			case RC_type_use_new_role_def_create:
+			case RC_type_inherit_process:
+			case RC_type_use_fd:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type use_new_role_def_create in def_fd_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			default:
+				/* check, whether role has CREATE right to new type */
+				/* get type_comp_fd of role */
+				i_rc_tid.role = i_attr_val1.rc_role;
+				i_rc_subtid.type = i_rc_item_val1.type_id;
+				return rc_check_create(caller_pid,
+							target,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_fd);
+			}
+
+		case T_IPC:
+			/* check, whether we may create IPC of def_ipc_create_type */
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_ipc_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_ipc_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_ipc_create_type);
+				return NOT_GRANTED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_ipc_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return NOT_GRANTED;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type use_new_role_def_create in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+			case RC_type_use_fd:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type inherit_parent in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			default:
+				/* check, whether role has CREATE right to new type */
+				/* get type_comp_ipc of role */
+				i_rc_subtid.type = i_rc_item_val1.type_id;
+				return rc_check_create(caller_pid,
+							target,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_ipc);
+			}
+
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+			/* check, whether we may create USER of def_user_create_type */
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_user_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_user_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_user_create_type);
+				return NOT_GRANTED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_user_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return NOT_GRANTED;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type use_new_role_def_create in def_user_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+			case RC_type_use_fd:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type inherit_parent in def_user_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			default:
+				/* check, whether role has CREATE right to new type */
+				/* get type_comp_ipc of role */
+				i_rc_subtid.type = i_rc_item_val1.type_id;
+				return rc_check_create(caller_pid,
+							target,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_user);
+			}
+
+		case T_GROUP:
+			/* check, whether we may create GROUP of def_group_create_type */
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_group_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_group_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_group_create_type);
+				return NOT_GRANTED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_group_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return NOT_GRANTED;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type use_new_role_def_create in def_group_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+			case RC_type_use_fd:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type inherit_parent in def_group_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			default:
+				/* check, whether role has CREATE right to new type */
+				/* get type_comp_ipc of role */
+				i_rc_subtid.type = i_rc_item_val1.type_id;
+				return rc_check_create(caller_pid,
+							target,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_group);
+			}
+#endif				/* RSBAC_RC_UM_PROT */
+
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETTEMP:
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC,
+						  T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get type_comp_xxx of role - we always use type GENERAL for CREATE */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			i_rc_subtid.type = RSBAC_RC_GENERAL_TYPE;
+			return rc_check_create(caller_pid,
+						target,
+						i_rc_tid,
+						i_rc_subtid,
+						RI_type_comp_nettemp);
+
+		case T_NETOBJ:
+			/* check, whether we may create NETOBJ of this type */
+			return(check_comp_rc(target, tid, request, caller_pid));
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_DELETE:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+	        case T_UNIXSOCK:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETTEMP:
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_EXECUTE:
+		switch (target) {
+		case T_FILE:
+			/* get rc_role from process */
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_process_execute_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_process_execute_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_process_execute_type);
+				return NOT_GRANTED;
+			}
+			if (i_rc_item_val1.type_id == RC_type_no_execute)
+				return NOT_GRANTED;
+			else
+				return check_comp_rc
+					(target, tid, request,
+					 caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_GET_PERMISSIONS_DATA:
+		switch (target) {
+		case T_SCD:
+			return check_comp_rc_scd
+				(tid.scd, request, caller_pid);
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+	        case T_UNIXSOCK:
+		case T_IPC:
+		case T_DEV:
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+		default:
+			return DO_NOT_CARE;
+		};
+
+	case R_LINK_HARD:
+		switch (target) {
+		case T_FILE:
+		case T_UNIXSOCK:
+		case T_FIFO:
+		case T_SYMLINK:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_ACCESS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+		case T_UNIXSOCK:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_AUTHENTICATE:
+		switch (target) {
+		case T_USER:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_ATTRIBUTE:
+		switch (attr) {	/* owner must be changed by other request to prevent inconsistency */
+		case A_owner:
+			return NOT_GRANTED;
+		case A_rc_type:
+		case A_local_rc_type:
+		case A_remote_rc_type:
+		case A_rc_type_fd:
+		case A_rc_type_nt:
+		case A_rc_select_type:
+			/* Granted on target? */
+			result =
+			    check_comp_rc(target, tid, request,
+					  caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    ) {
+				/* Granted on type? */
+				if (   (target == T_NETTEMP)
+				    && (attr == A_rc_type)
+				   )
+				   target = T_NETOBJ;
+				result =
+				    rsbac_rc_check_type_comp(target,
+							     attr_val.
+							     rc_type,
+							     RCR_ASSIGN,
+ 							     caller_pid);
+				if ((result == GRANTED)
+				    || (result == DO_NOT_CARE)
+				    )
+					return result;
+			}
+			/* Classical admin_type check */
+			if ((err = rsbac_rc_test_role_admin(TRUE)))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+
+		case A_rc_force_role:
+		case A_rc_initial_role:
+		case A_rc_role:
+		case A_rc_def_role:
+			/* Granted on target? */
+			result =
+			    check_comp_rc(target, tid, request,
+					  caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    ) {
+				/* test assign_roles of process / modify */
+				if (!
+				    (err =
+				     rsbac_rc_test_assign_roles(target,
+								tid, attr,
+								attr_val.
+								rc_role)))
+					return GRANTED;
+			}
+			/* Classical admin_type check */
+			if (rsbac_rc_test_role_admin(TRUE))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+
+			/* you may only change a user's pseudo, if you also may assign her role */
+		case A_pseudo:
+			if (target != T_USER)
+				return NOT_GRANTED;
+			/* test assign_roles of process for user's role only */
+			if (rsbac_rc_test_assign_roles
+			    (target, tid, A_rc_def_role,
+			     RC_role_inherit_user))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+
+#ifdef CONFIG_RSBAC_RC_GEN_PROT
+		case A_log_array_low:
+		case A_log_array_high:
+		case A_log_program_based:
+		case A_log_user_based:
+		case A_symlink_add_remote_ip:
+		case A_symlink_add_uid:
+		case A_symlink_add_rc_role:
+		case A_linux_dac_disable:
+		case A_fake_root_uid:
+		case A_audit_uid:
+		case A_auid_exempt:
+		case A_remote_ip:
+		case A_vset:
+		case A_program_file:
+			/* Explicitely granted? */
+			result =
+			    check_comp_rc(target, tid, request,
+					  caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    )
+				return result;
+			/* Failed -> Classical admin_type check / modify */
+			if (rsbac_rc_test_role_admin(TRUE))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+
+			/* All attributes (remove target!) */
+		case A_none:
+			switch (target) {
+			case T_USER:
+				/* test assign_roles of process for user's role */
+				if ((err =
+				     rsbac_rc_test_assign_roles(target,
+								tid,
+								A_rc_def_role,
+								RC_role_inherit_user)))
+					return NOT_GRANTED;
+				else
+					return GRANTED;
+
+			default:
+				/* Explicitely granted? */
+				return check_comp_rc
+					(target, tid, request,
+					 caller_pid);
+			}
+
+#ifdef CONFIG_RSBAC_RC_AUTH_PROT
+		case A_auth_may_setuid:
+		case A_auth_may_set_cap:
+		case A_auth_start_uid:
+		case A_auth_start_euid:
+		case A_auth_start_gid:
+		case A_auth_start_egid:
+		case A_auth_learn:
+		case A_auth_add_f_cap:
+		case A_auth_remove_f_cap:
+		case A_auth_last_auth:
+			/* may manipulate auth capabilities, if allowed in general... */
+			result =
+			    check_comp_rc_scd(RST_auth_administration,
+					      request, caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    ) {
+				/* ...and for this target */
+				result =
+				    check_comp_rc(target, tid,
+						  RCR_MODIFY_AUTH,
+						  caller_pid);
+				if ((result == GRANTED)
+				    || (result == DO_NOT_CARE)
+				    )
+					return result;
+			}
+			/* Last chance: classical admin_type check */
+			if ((err = rsbac_rc_test_role_admin(TRUE)))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+#ifdef CONFIG_RSBAC_RC_UDF_PROT
+		case A_udf_role:
+		case A_udf_checker:
+		case A_udf_checked:
+		case A_udf_do_check:
+			/* may manipulate udf attributes, if general...  */
+			result =
+			    check_comp_rc_scd(RST_udf_administration,
+					      request, caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    ) {
+				/* ...and for this target */
+				result =
+				    check_comp_rc(target, tid,
+						  RCR_MODIFY_UDF,
+						  caller_pid);
+				if ((result == GRANTED)
+				    || (result == DO_NOT_CARE)
+				    )
+					return result;
+			}
+			/* Last chance: classical admin_type check */
+			if ((err = rsbac_rc_test_role_admin(TRUE)))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+#if defined(CONFIG_RSBAC_RC_LEARN)
+		case A_rc_learn:
+			/* Only role admin */
+			if ((err = rsbac_rc_test_role_admin(TRUE)))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_PERMISSIONS_DATA:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+		case T_IPC:
+		case T_DEV:
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+		case T_SCD:
+			return check_comp_rc_scd
+				(tid.scd, request, caller_pid);
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+		case T_NONE:
+			/* may turn off Linux DAC, if compatible */
+			return check_comp_rc_scd
+				(ST_other, request, caller_pid);
+#endif
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MODIFY_SYSTEM_DATA:
+		switch (target) {
+		case T_SCD:
+			return check_comp_rc_scd
+				(tid.scd, request, caller_pid);
+
+		case T_DEV:
+		case T_PROCESS:
+		case T_IPC:
+#if defined(CONFIG_RSBAC_RC_NET_DEV_PROT)
+		case T_NETDEV:
+#endif
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_MOUNT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_DEV:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_READ_ATTRIBUTE:
+		switch (attr) {
+		case A_rc_type:
+		case A_rc_type_fd:
+		case A_rc_type_nt:
+		case A_rc_force_role:
+		case A_rc_initial_role:
+		case A_rc_role:
+		case A_rc_def_role:
+		case A_rc_select_type:
+		case A_pseudo:
+#ifdef CONFIG_RSBAC_RC_GEN_PROT
+		case A_owner:
+		case A_log_array_low:
+		case A_log_array_high:
+		case A_log_program_based:
+		case A_log_user_based:
+		case A_symlink_add_remote_ip:
+		case A_symlink_add_uid:
+		case A_symlink_add_rc_role:
+		case A_linux_dac_disable:
+		case A_fake_root_uid:
+		case A_audit_uid:
+		case A_auid_exempt:
+		case A_remote_ip:
+		case A_vset:
+		case A_program_file:
+#endif
+			/* Explicitely granted? */
+			result =
+			    check_comp_rc(target, tid, request,
+					  caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    )
+				return result;
+			/* Failed -> Classical admin_type check / modify */
+			if (rsbac_rc_test_role_admin(FALSE))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+
+#ifdef CONFIG_RSBAC_RC_AUTH_PROT
+		case A_auth_may_setuid:
+		case A_auth_may_set_cap:
+		case A_auth_start_uid:
+		case A_auth_start_euid:
+		case A_auth_start_gid:
+		case A_auth_start_egid:
+		case A_auth_learn:
+		case A_auth_add_f_cap:
+		case A_auth_remove_f_cap:
+		case A_auth_last_auth:
+			/* may read auth capabilities, if compatible */
+			result =
+			    check_comp_rc_scd(RST_auth_administration,
+					      request, caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    )
+				return result;
+			/* Failed -> Classical admin_type check / modify */
+			if (rsbac_rc_test_role_admin(FALSE))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+#ifdef CONFIG_RSBAC_RC_UDF_PROT
+		case A_udf_role:
+		case A_udf_checker:
+		case A_udf_checked:
+		case A_udf_do_check:
+			/* may read UDF attributes, if compatible */
+			result =
+			    check_comp_rc_scd(RST_udf_administration,
+					      request, caller_pid);
+			if ((result == GRANTED)
+			    || (result == DO_NOT_CARE)
+			    )
+				return result;
+			/* Failed -> Classical admin_type check / modify */
+			if (rsbac_rc_test_role_admin(FALSE))
+				return NOT_GRANTED;
+			else
+				return GRANTED;
+#endif
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_READ_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_DEV:
+		case T_IPC:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_ADD_TO_KERNEL:
+		switch (target) {
+		case T_NONE:
+			/* may add to kernel, if compatible */
+			return check_comp_rc_scd
+				(ST_other, request, caller_pid);
+
+		case T_FILE:
+		case T_DEV:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+
+	case R_ALTER:
+		/* only for IPC */
+		switch (target) {
+		case T_IPC:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_REMOVE_FROM_KERNEL:
+		switch (target) {
+		case T_NONE:
+			return check_comp_rc_scd
+				(ST_other, request, caller_pid);
+
+		case T_FILE:
+		case T_DEV:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_RENAME:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		case T_USER:
+		case T_GROUP:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SEND_SIGNAL:
+	case R_TRACE:
+		if (target == T_PROCESS)
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+		else
+			return DO_NOT_CARE;
+
+	case R_SHUTDOWN:
+		switch (target) {
+		case T_NONE:
+			return check_comp_rc_scd
+				(ST_other, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SWITCH_LOG:
+		switch (target) {
+		case T_NONE:
+			return check_comp_rc_scd
+				(ST_other, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_SWITCH_MODULE:
+		switch (target) {
+		case T_NONE:
+			/* we need the switch_target */
+			if (attr != A_switch_target)
+				return NOT_GRANTED;
+                        switch(attr_val.switch_target) {
+				case SW_RC:
+#ifdef CONFIG_RSBAC_SOFTMODE
+				case SW_SOFTMODE:
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+				case SW_FREEZE:
+#endif
+					return check_comp_rc_scd (ST_other, request, caller_pid);
+#ifdef CONFIG_RSBAC_RC_AUTH_PROT
+				case SW_AUTH:
+					if (check_comp_rc_scd (ST_other, request, caller_pid) == GRANTED)
+						return GRANTED;
+					return check_comp_rc_scd (RST_auth_administration, request, caller_pid);
+#endif
+#ifdef CONFIG_RSBAC_RC_UDF_PROT
+				case SW_UDF:
+					return check_comp_rc_scd (RST_udf_administration, request, caller_pid);
+#endif
+
+				default:
+					return DO_NOT_CARE;
+			}
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_TERMINATE:
+		return DO_NOT_CARE;
+
+	case R_TRUNCATE:
+		switch (target) {
+		case T_FILE:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_WRITE_OPEN:
+		switch (target) {
+		case T_FILE:
+		case T_DEV:
+		case T_FIFO:
+                case T_UNIXSOCK:
+		case T_IPC:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_UMOUNT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_DEV:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+			/* all other cases are unknown */
+		default:
+			return DO_NOT_CARE;
+		}
+
+
+	case R_BIND:
+		switch (target) {
+		case T_IPC:
+			/* check, whether we may create IPC of def_ipc_create_type */
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return NOT_GRANTED;
+			}
+			/* get def_ipc_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_ipc_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_ipc_create_type);
+				return NOT_GRANTED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_ipc_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return NOT_GRANTED;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type use_new_role_def_create in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+			case RC_type_use_fd:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_request_rc(): invalid type inherit_parent in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return NOT_GRANTED;
+
+			default:
+				/* check, whether role has CREATE right to new type */
+				/* get type_comp_ipc of role */
+				i_rc_subtid.type = i_rc_item_val1.type_id;
+				return rc_check_create(caller_pid,
+							target,
+							i_rc_tid,
+							i_rc_subtid,
+							RI_type_comp_ipc);
+			}
+#if defined(CONFIG_RSBAC_RC_NET_DEV_PROT)
+		case T_NETDEV:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif
+
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#endif
+
+			/* all other cases are undefined */
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_IOCTL:
+		switch (target) {
+		case T_DEV:
+                case T_UNIXSOCK:
+		case T_IPC:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+#if defined(CONFIG_RSBAC_RC_NET_OBJ_PROT)
+		case T_NETOBJ:
+#endif
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+		default:
+			return DO_NOT_CARE;
+		}
+
+	case R_LOCK:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+
+		default:
+			return DO_NOT_CARE;
+		}
+	case RCR_SELECT:
+		switch (target) {
+		case T_FILE:
+		case T_DIR:
+		case T_FIFO:
+		case T_SYMLINK:
+                case T_UNIXSOCK:
+			return check_comp_rc
+				(target, tid, request, caller_pid);
+		default:
+			return DO_NOT_CARE;
+		}
+	default:
+		return DO_NOT_CARE;
+	}
+
+	return result;
+}
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up. Because of this, the write boundary is not adjusted - there  */
+/* is no user-level writing anyway...                                        */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+inline int rsbac_adf_set_attr_rc(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)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_attribute_value_t i_attr_val2;
+	union rsbac_rc_target_id_t i_rc_tid;
+	union rsbac_rc_target_id_t i_rc_subtid;
+	union rsbac_rc_item_value_t i_rc_item_val1;
+
+	switch (request) {
+	case R_CLOSE:
+	case R_ACCEPT:
+	case R_READ:
+		return 0;
+	case R_CHANGE_OWNER:
+		switch (target) {
+		case T_PROCESS:
+			/* setting owner for process is done in main dispatcher */
+			/* Here we have to adjust the rc_type and set the rc_role */
+			/* to the new owner's rc_def_role */
+			if (attr != A_owner)
+				return -RSBAC_EINVALIDATTR;
+
+			/* get old rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_process_chown_type of old role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_process_chown_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_process_chown_type);
+				return -RSBAC_EREADFAILED;
+			}
+
+			/* get rc_force_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_force_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_force_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* only set to user's rc_def_role, if indicated by force_role, otherwise keep */
+			if ((i_attr_val1.rc_force_role ==
+			     RC_role_inherit_user)
+			    || (i_attr_val1.rc_force_role ==
+				RC_role_inherit_up_mixed)
+			    ) {
+				/* get rc_def_role from new owner */
+				i_tid.user = attr_val.owner;
+				if ((err = rsbac_get_attr(SW_RC, T_USER,
+							  i_tid,
+							  A_rc_def_role,
+							  &i_attr_val1,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_def_role);
+					return -RSBAC_EREADFAILED;
+				}
+				/* check rc_def_role, warn, if unusable */
+				if (i_attr_val1.rc_def_role >
+				    RC_role_max_value) {
+					rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): rc_def_role %u of user %u is higher than MAX_ROLE %u, setting role of process %u to GENERAL_ROLE %u!\n",
+						     i_attr_val1.
+						     rc_def_role,
+						     attr_val.owner,
+						     RC_role_max_value,
+						     pid_nr(caller_pid),
+						     RSBAC_RC_GENERAL_ROLE);
+					i_attr_val1.rc_def_role =
+					    RSBAC_RC_GENERAL_ROLE;
+				}
+				/* set new rc_role for process */
+				i_tid.process = caller_pid;
+				if ((err = rsbac_set_attr(SW_RC, T_PROCESS,
+							  i_tid,
+							  A_rc_role,
+							  i_attr_val1))) {
+					rsbac_pr_set_error(A_rc_role);
+					return -RSBAC_EWRITEFAILED;
+				}
+			} else
+			    /* set it to the force_role, if real role) */
+			if ((i_attr_val1.rc_force_role <= RC_role_max_value)
+			    ) {
+				/* set new rc_role for process */
+				i_tid.process = caller_pid;
+				if ((err = rsbac_set_attr(SW_RC, T_PROCESS,
+							  i_tid,
+							  A_rc_role,
+							  i_attr_val1))) {
+					rsbac_pr_set_error(A_rc_role);
+					return -RSBAC_EWRITEFAILED;
+				}
+			}
+
+			/* adjust type: switch on def_process_chown_type of old role */
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				/* keep old type */
+				break;
+			case RC_type_use_new_role_def_create:
+				/* get new rc_role from process */
+				i_tid.process = caller_pid;
+				if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+							  i_tid,
+							  A_rc_role,
+							  &i_attr_val1, FALSE))) {
+					rsbac_pr_get_error(A_rc_role);
+					return -RSBAC_EREADFAILED;
+				}
+				/* Cannot adjust, if new role is no real role */
+				if (i_attr_val1.rc_role >
+				    RC_role_max_value)
+					break;
+				/* get def_process_create_type of new role */
+				i_rc_tid.role = i_attr_val1.rc_role;
+				if ((err = rsbac_rc_get_item(0,
+							     RT_ROLE,
+							     i_rc_tid,
+							     i_rc_tid,
+							     RI_def_process_create_type,
+							     &i_rc_item_val1,
+							     NULL))) {
+					rsbac_rc_pr_get_error
+					    (RI_def_process_create_type);
+					return -RSBAC_EREADFAILED;
+				}
+				switch (i_rc_item_val1.type_id) {
+				case RC_type_inherit_parent:
+				case RC_type_inherit_process:
+					/* keep old type */
+					break;
+				case RC_type_use_new_role_def_create:
+					/* error - complain, but keep type (inherit) */
+					rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type use_new_role_def_create in def_process_create_type of role %i!\n",
+						     i_attr_val1.rc_role);
+					break;
+				case RC_type_no_create:
+					/* set rc_type for process to general */
+					i_rc_item_val1.type_id =
+					    RSBAC_RC_GENERAL_TYPE;
+					/* fall through */
+				default:
+					/* set rc_type for process */
+					i_attr_val1.rc_type =
+					    i_rc_item_val1.type_id;
+					if ((err =
+					     rsbac_set_attr(SW_RC, T_PROCESS,
+							    i_tid,
+							    A_rc_type,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error(A_rc_type);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+				break;
+			case RC_type_no_create:
+			case RC_type_no_chown:
+				/* set rc_type for process to general */
+				i_rc_item_val1.type_id =
+				    RSBAC_RC_GENERAL_TYPE;
+				/* fall through */
+			default:
+				/* set rc_type for process */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				if ((err =
+				     rsbac_set_attr(SW_RC, T_PROCESS, i_tid,
+						    A_rc_type,
+						    i_attr_val1))) {
+					rsbac_pr_set_error(A_rc_type);
+					return -RSBAC_EWRITEFAILED;
+				}
+			}
+
+			return 0;
+
+			/* all other cases */
+		default:
+			return 0;
+		}
+
+	case R_CLONE:
+		if (target == T_PROCESS) {
+			/* get rc_role from process */
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+
+			/* get rc_force_role from process */
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  tid,
+						  A_rc_force_role,
+						  &i_attr_val2, FALSE))) {
+				rsbac_pr_get_error(A_rc_force_role);
+				return -RSBAC_EREADFAILED;
+			}
+
+			/* set rc_role for new process */
+			if ((i_attr_val1.rc_role != RSBAC_RC_GENERAL_ROLE) && (err = rsbac_set_attr(SW_RC, T_PROCESS,
+						  new_tid,
+						  A_rc_role,
+						  i_attr_val1))) {
+				rsbac_pr_set_error(A_rc_role);
+				return -RSBAC_EWRITEFAILED;
+			}
+
+			/* set rc_force_role for new process */
+			if ((i_attr_val2.rc_force_role != RC_default_force_role) && (err = rsbac_set_attr(SW_RC, T_PROCESS,
+						  new_tid,
+						  A_rc_force_role,
+						  i_attr_val2))) {
+				rsbac_pr_set_error(A_rc_force_role);
+				return -RSBAC_EWRITEFAILED;
+			}
+
+			/* get def_process_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_process_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_process_create_type);
+				return -RSBAC_EREADFAILED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				/* copy old type */
+				/* get rc_type from old process */
+				if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+							  tid,
+							  A_rc_type,
+							  &i_attr_val1,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_type);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set rc_type for new process */
+				if ((i_attr_val1.rc_type != RSBAC_RC_GENERAL_TYPE) && (err = rsbac_set_attr(SW_RC, T_PROCESS,
+							  new_tid,
+							  A_rc_type,
+							  i_attr_val1))) {
+					rsbac_pr_set_error(A_rc_type);
+					return -RSBAC_EWRITEFAILED;
+				}
+				break;
+			case RC_type_no_create:
+				return -RSBAC_EDECISIONMISMATCH;
+			case RC_type_use_new_role_def_create:
+				/* error - complain, but keep type (inherit) */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type use_new_role_def_create in def_process_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+			default:
+				/* set rc_type for new process */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				if ((i_attr_val1.rc_type != RSBAC_RC_GENERAL_TYPE) && (err =
+				     rsbac_set_attr(SW_RC, T_PROCESS, new_tid,
+						    A_rc_type,
+						    i_attr_val1))) {
+					rsbac_pr_set_error(A_rc_type);
+					return -RSBAC_EWRITEFAILED;
+				}
+			}
+			return 0;
+		} else
+			return 0;
+
+	case R_CREATE:
+		switch (target) {
+			/* Creating dir or (pseudo) file IN target dir! */
+		case T_DIR:
+			/* Mode of created item is ignored! */
+			/* check for select_fd_type being set for calling
+			 * process and enforce it if set. */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_select_type,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_select_type);
+				return -RSBAC_EREADFAILED;
+			}
+			if (i_attr_val1.rc_select_type != RC_type_use_fd) {
+				i_attr_val2.rc_type_fd = i_attr_val1.rc_select_type;
+				/* rc_select_type is one use only so we reset it
+				 * to default value first.
+				 * value to be set already backup'ed. */
+				i_attr_val1.rc_select_type = RC_type_use_fd;
+				if ((err = rsbac_set_attr(SW_RC, T_PROCESS,
+						         i_tid, A_rc_select_type,
+						         i_attr_val1)))
+				{
+					rsbac_printk("rsbac_adf_set_attr_rc(): unable to reset rc_select_type to default value!\n");
+				}
+				if ((err = rsbac_set_attr(SW_RC, new_target,
+							  new_tid, A_rc_type_fd,
+							  i_attr_val2)))
+				{
+					rsbac_pr_set_error(A_rc_type_fd);
+					return -RSBAC_EWRITEFAILED;
+				}
+				return 0;
+								
+			}
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_fd_create_type of role */
+			/* First get target dir's efftype */
+			if ((err = rsbac_get_attr(SW_RC,
+						  target,
+						  tid,
+						  A_rc_type_fd,
+						  &i_attr_val2, TRUE))) {
+				rsbac_pr_get_error(A_rc_type_fd);
+				return -RSBAC_EREADFAILED;
+			}
+			i_rc_tid.role = i_attr_val1.rc_role;
+			switch(new_target) {
+				case T_UNIXSOCK:
+					i_rc_subtid.type = i_attr_val2.rc_type;
+					if ((err = rsbac_rc_get_item(0,
+								     RT_ROLE,
+								     i_rc_tid,
+								     i_rc_subtid,
+								     RI_def_unixsock_create_type,
+								     &i_rc_item_val1,
+								     NULL))) {
+						rsbac_rc_pr_get_error
+						    (RI_def_unixsock_create_type);
+						return -RSBAC_EREADFAILED;
+					}
+					if(i_rc_item_val1.type_id != RC_type_use_fd)
+						break;
+					/* fall through */
+				default:
+					i_rc_subtid.type = i_attr_val2.rc_type;
+					if ((err = rsbac_rc_get_item(0, RT_ROLE, i_rc_tid, i_rc_subtid, RI_def_fd_ind_create_type, &i_rc_item_val1, NULL))) {	/* No individual create type -> try global */
+						if ((err = rsbac_rc_get_item(0,
+									     RT_ROLE,
+									     i_rc_tid,
+									     i_rc_subtid,
+									     RI_def_fd_create_type,
+									     &i_rc_item_val1,
+									     NULL))) {
+							rsbac_rc_pr_get_error
+							    (RI_def_fd_create_type);
+							return -RSBAC_EREADFAILED;
+						}
+					}
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				return -RSBAC_EDECISIONMISMATCH;
+				break;
+
+			case RC_type_use_new_role_def_create:
+			case RC_type_inherit_process:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type inherit_process or use_new_role_def_create in def_fd_create_type or def_unixsock_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			case RC_type_inherit_parent:
+			default:
+				/* get type from new target */
+				if ((err = rsbac_get_attr(SW_RC, new_target,
+							  new_tid,
+							  A_rc_type_fd,
+							  &i_attr_val1,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_type_fd);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set it for new target, if different */
+				if (i_attr_val1.rc_type_fd !=
+				    i_rc_item_val1.type_id) {
+					i_attr_val1.rc_type_fd =
+					    i_rc_item_val1.type_id;
+					if ((err =
+					     rsbac_set_attr(SW_RC, new_target,
+							    new_tid,
+							    A_rc_type_fd,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error(A_rc_type_fd);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			}
+			return 0;
+
+		case T_IPC:
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_ipc_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_ipc_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_ipc_create_type);
+				return -RSBAC_EREADFAILED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				return -RSBAC_EDECISIONMISMATCH;
+				break;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type use_new_role_def_create in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type inherit_parent in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			default:
+				/* set rc_type for ipc target */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				/* get type from target */
+				if ((err = rsbac_get_attr(SW_RC,
+							  target,
+							  tid,
+							  A_rc_type,
+							  &i_attr_val2,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_type);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set it for new target, if different */
+				if (i_attr_val1.rc_type !=
+				    i_attr_val2.rc_type) {
+					if ((err =
+					     rsbac_set_attr(SW_RC, target,
+							    tid, A_rc_type,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error
+						    (A_rc_type);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			}
+			return 0;
+
+		case T_USER:
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_user_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_user_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_user_create_type);
+				return -RSBAC_EREADFAILED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_user_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return -RSBAC_EDECISIONMISMATCH;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type use_new_role_def_create in def_user_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type inherit_parent in def_user_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			default:
+				/* set rc_type for user target */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				/* get type from target */
+				if ((err = rsbac_get_attr(SW_RC,
+							  target,
+							  tid,
+							  A_rc_type,
+							  &i_attr_val2,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_type);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set it for new target, if different */
+				if (i_attr_val1.rc_type !=
+				    i_attr_val2.rc_type) {
+					if ((err =
+					     rsbac_set_attr(SW_RC, target,
+							    tid, A_rc_type,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error
+						    (A_rc_type);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			}
+			return 0;
+
+		case T_GROUP:
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_group_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_group_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_group_create_type);
+				return -RSBAC_EREADFAILED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				if ((request > R_NONE) || (rsbac_log_levels[request][target] != LL_none)) {
+					rsbac_pr_debug(adf_rc, "pid %u(%s), owner %u, rc_role %u, def_group_create_type no_create, request CREATE -> NOT_GRANTED!\n",
+						       pid_nr(caller_pid), current->comm,
+						       __kuid_val(current_uid()),
+						       i_attr_val1.rc_role);
+				}
+				return -RSBAC_EDECISIONMISMATCH;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type use_new_role_def_create in def_group_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type inherit_parent in def_group_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			default:
+				/* set rc_type for group target */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				/* get type from target */
+				if ((err = rsbac_get_attr(SW_RC,
+							  target,
+							  tid,
+							  A_rc_type,
+							  &i_attr_val2,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_type);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set it for new target, if different */
+				if (i_attr_val1.rc_type !=
+				    i_attr_val2.rc_type) {
+					if ((err =
+					     rsbac_set_attr(SW_RC, target,
+							    tid, A_rc_type,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error
+						    (A_rc_type);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			}
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_EXECUTE:
+		switch (target) {
+		case T_FILE:
+			/* get rc_force_role from target file */
+			if ((err = rsbac_get_attr(SW_RC, T_FILE,
+						  tid,
+						  A_rc_force_role,
+						  &i_attr_val1, TRUE))) {
+				rsbac_pr_get_error(A_rc_force_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* check rc_force_role, warn, if unusable */
+			if ((i_attr_val1.rc_force_role > RC_role_max_value)
+			    && (i_attr_val1.rc_force_role <
+				RC_role_min_special)
+			    ) {
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): rc_force_role %u of file %u on device %02u:%02u is higher than MAX_ROLE %u, setting forced role of process %u to default value %u!\n",
+					     i_attr_val1.rc_force_role,
+					     tid.file.inode,
+					     MAJOR(tid.file.device),
+					     MINOR(tid.file.device),
+					     RC_role_max_value, pid_nr(caller_pid),
+					     RC_default_root_dir_force_role);
+				i_attr_val1.rc_force_role =
+				    RC_default_root_dir_force_role;
+			}
+			/* set rc_force_role for this process to keep track of it later */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_set_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_force_role,
+						  i_attr_val1))) {
+				rsbac_pr_set_error(A_rc_force_role);
+				return -RSBAC_EWRITEFAILED;
+			}
+			/* get rc_initial_role from target file */
+			if ((err = rsbac_get_attr(SW_RC, T_FILE,
+						  tid,
+						  A_rc_initial_role,
+						  &i_attr_val2, TRUE))) {
+				rsbac_pr_get_error(A_rc_initial_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* check rc_initial_role, warn, if unusable */
+			if ((i_attr_val2.rc_initial_role >
+			     RC_role_max_value)
+			    && (i_attr_val2.rc_initial_role !=
+				RC_role_use_force_role)
+			    ) {
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): rc_initial_role %u of file %u on device %02u:%02u is higher than MAX_ROLE %u, setting initial role of process %u to default value %u!\n",
+					     i_attr_val2.rc_initial_role,
+					     tid.file.inode,
+					     MAJOR(tid.file.device),
+					     MINOR(tid.file.device),
+					     RC_role_max_value, pid_nr(caller_pid),
+					     RC_default_root_dir_initial_role);
+				i_attr_val2.rc_initial_role =
+				    RC_default_root_dir_initial_role;
+			}
+			if (i_attr_val2.rc_initial_role ==
+			    RC_role_use_force_role) {
+				switch (i_attr_val1.rc_force_role) {
+				case RC_role_inherit_user:
+					/* get rc_def_role from process owner */
+					i_tid.user = owner;
+					if ((err =
+					     rsbac_get_attr(SW_RC, T_USER,
+							    i_tid,
+							    A_rc_def_role,
+							    &i_attr_val1,
+							    FALSE))) {
+						rsbac_pr_get_error
+						    (A_rc_def_role);
+						return -RSBAC_EREADFAILED;
+					}
+					/* set it for this process */
+					i_tid.process = caller_pid;
+					if ((err =
+					     rsbac_set_attr(SW_RC, T_PROCESS,
+							    i_tid,
+							    A_rc_role,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error
+						    (A_rc_role);
+						return -RSBAC_EWRITEFAILED;
+					}
+					break;
+
+				case RC_role_inherit_parent:
+				case RC_role_inherit_process:
+				case RC_role_inherit_up_mixed:
+					/* keep current role */
+					break;
+
+				default:
+					/* set forced role for this process */
+					i_tid.process = caller_pid;
+					if ((err =
+					     rsbac_set_attr(SW_RC, T_PROCESS,
+							    i_tid,
+							    A_rc_role,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error
+						    (A_rc_role);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			} else {	/* use initial_role */
+
+				/* set initial role for this process */
+				i_tid.process = caller_pid;
+				if ((err = rsbac_set_attr(SW_RC, T_PROCESS,
+							  i_tid,
+							  A_rc_role,
+							  i_attr_val2))) {
+					rsbac_pr_set_error
+					    (A_rc_role);
+					return -RSBAC_EWRITEFAILED;
+				}
+			}
+			/* Get role of process. */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_process_execute_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_process_execute_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_process_execute_type);
+				return -RSBAC_EREADFAILED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+			case RC_type_use_new_role_def_create:
+				/* Cannot reset, because of unusable default -> warn and keep */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type in def_process_execute_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				break;
+			case RC_type_no_execute:
+				return -RSBAC_EDECISIONMISMATCH;
+			default:
+				/* set rc_type for process */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				i_tid.process = caller_pid;
+				if ((err =
+				     rsbac_set_attr(SW_RC, T_PROCESS, i_tid,
+						    A_rc_type,
+						    i_attr_val1))) {
+					rsbac_pr_set_error(A_rc_type);
+					return -RSBAC_EWRITEFAILED;
+				}
+			}
+			/* type and role are set - ready. */
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+	case R_BIND:
+		switch (target) {
+		case T_IPC:
+			/* get rc_role from process */
+			i_tid.process = caller_pid;
+			if ((err = rsbac_get_attr(SW_RC, T_PROCESS,
+						  i_tid,
+						  A_rc_role,
+						  &i_attr_val1, FALSE))) {
+				rsbac_pr_get_error(A_rc_role);
+				return -RSBAC_EREADFAILED;
+			}
+			/* get def_ipc_create_type of role */
+			i_rc_tid.role = i_attr_val1.rc_role;
+			if ((err = rsbac_rc_get_item(0,
+						     RT_ROLE,
+						     i_rc_tid,
+						     i_rc_tid,
+						     RI_def_ipc_create_type,
+						     &i_rc_item_val1,
+						     NULL))) {
+				rsbac_rc_pr_get_error
+				    (RI_def_ipc_create_type);
+				return -RSBAC_EREADFAILED;
+			}
+			switch (i_rc_item_val1.type_id) {
+			case RC_type_no_create:
+				return -RSBAC_EDECISIONMISMATCH;
+				break;
+
+			case RC_type_use_new_role_def_create:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type use_new_role_def_create in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			case RC_type_inherit_parent:
+			case RC_type_inherit_process:
+				/* error - complain and return error */
+				rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_rc(): invalid type inherit_parent in def_ipc_create_type of role %i!\n",
+					     i_attr_val1.rc_role);
+				return -RSBAC_EINVALIDVALUE;
+
+			default:
+				/* set rc_type for ipc target */
+				i_attr_val1.rc_type =
+				    i_rc_item_val1.type_id;
+				/* get type from target */
+				if ((err = rsbac_get_attr(SW_RC,
+							  target,
+							  tid,
+							  A_rc_type,
+							  &i_attr_val2,
+							  FALSE))) {
+					rsbac_pr_get_error(A_rc_type);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set it for new target, if different */
+				if (i_attr_val1.rc_type !=
+				    i_attr_val2.rc_type) {
+					if ((err =
+					     rsbac_set_attr(SW_RC, target,
+							    tid, A_rc_type,
+							    i_attr_val1)))
+					{
+						rsbac_pr_set_error
+						    (A_rc_type);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			}
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	case R_CONNECT:
+		switch (target) {
+		case T_IPC:
+			if (new_target == T_IPC) {
+				/* get type from old target */
+				i_tid.process = caller_pid;
+				if ((err = rsbac_get_attr(SW_RC, T_IPC,
+							  tid,
+							  A_rc_type,
+							  &i_attr_val1, FALSE))) {
+					rsbac_pr_get_error(A_rc_role);
+					return -RSBAC_EREADFAILED;
+				}
+				/* set rc_type for new ipc target, if not 0 */
+				if (i_attr_val1.rc_type) {
+					if ((err = rsbac_set_attr(SW_RC, T_IPC,
+							    new_tid, A_rc_type,
+							    i_attr_val1))) {
+						rsbac_pr_set_error(A_rc_type);
+						return -RSBAC_EWRITEFAILED;
+					}
+				}
+			}
+			return 0;
+
+			/* all other cases are unknown */
+		default:
+			return 0;
+		}
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_SECDEL
+inline rsbac_boolean_t rsbac_need_overwrite_rc(struct dentry * dentry_p)
+{
+	int err = 0;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_rc_target_id_t i_rc_tid;
+	union rsbac_rc_item_value_t i_rc_item_val1;
+
+	if (!dentry_p || !dentry_p->d_inode)
+		return FALSE;
+
+	i_tid.file.device = dentry_p->d_sb->s_dev;
+	i_tid.file.inode = dentry_p->d_inode->i_ino;
+	i_tid.file.dentry_p = dentry_p;
+	/* get target's rc_type_fd */
+	if (rsbac_get_attr(SW_RC, T_FILE,
+			   i_tid, A_rc_type_fd, &i_attr_val1, TRUE)) {
+		rsbac_pr_get_error(A_rc_type_fd);
+		return FALSE;
+	}
+	/* get type_fd_need_secdel of target's rc_type_fd */
+	i_rc_tid.role = i_attr_val1.rc_role;
+	if ((err = rsbac_rc_get_item(0,
+				     RT_TYPE,
+				     i_rc_tid,
+				     i_rc_tid,
+				     RI_type_fd_need_secdel,
+				     &i_rc_item_val1, NULL))) {
+		rsbac_rc_pr_get_error(RI_type_fd_need_secdel);
+		return FALSE;
+	}
+
+	/* return need_overwrite */
+	return i_rc_item_val1.need_secdel;
+}
+#endif
diff --git a/rsbac/adf/rc/rc_syscalls.c b/rsbac/adf/rc/rc_syscalls.c
new file mode 100644
index 0000000..422392a
--- /dev/null
+++ b/rsbac/adf/rc/rc_syscalls.c
@@ -0,0 +1,1683 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - Role Compatibility               */
+/* File: rsbac/adf/rc/syscalls.c                     */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 26/Mar/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/rc.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/debug.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/rc_getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/um.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*           Declarations                          */
+/************************************************* */
+
+/* from rsbac/adf/rc/main.c */
+int rsbac_rc_test_role_admin(rsbac_boolean_t modify);
+
+int rsbac_rc_test_admin_roles(rsbac_rc_role_id_t t_role, rsbac_boolean_t modify);
+
+enum rsbac_adf_req_ret_t
+         rsbac_rc_check_type_comp(enum  rsbac_target_t          target,
+                                  rsbac_rc_type_id_t      type,
+                            enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             caller_pid);
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+/* Here we only check access rights and pass on to rc_data_structures */
+int rsbac_rc_sys_copy_role(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_rc_role_id_t from_role,
+  rsbac_rc_role_id_t to_role)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_RC
+    if(rsbac_switch_rc)
+#endif
+      {
+        int                           err;
+        /* source role must be in admin roles or caller must be role_admin */
+        if (   (err=rsbac_rc_test_admin_roles(from_role, TRUE))
+            && rsbac_rc_test_role_admin(TRUE)
+           )
+          {
+            if(err == -EPERM)
+              {
+                rsbac_uid_t user;
+
+                if(!rsbac_get_owner(&user))
+                  {
+                    rsbac_printk(KERN_INFO
+                                 "rsbac_rc_sys_copy_role(): copying of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                 from_role,
+                                 current->pid,
+                                 user);
+                  }
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_RC]
+                #endif
+                  )
+                #endif
+                  return err;
+              }
+            else
+              return err;
+          }
+        /* only role_admins may copy to existing targets */
+        if (   rsbac_rc_role_exists(ta_number, to_role)
+            && rsbac_rc_test_role_admin(TRUE)
+           )
+          {
+            rsbac_uid_t user;
+
+            if(!rsbac_get_owner(&user))
+              {
+                rsbac_printk(KERN_INFO
+                             "rsbac_rc_sys_copy_role(): overwriting of existing role %u denied for pid %u, user %u - no role_admin!\n",
+                             to_role,
+                             current->pid,
+                             user);
+              }
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_RC]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    /* pass on */
+    return(rsbac_rc_copy_role(ta_number, from_role, to_role));
+  }
+
+/* Here we only check access rights and pass on to rc_data_structures */
+int rsbac_rc_sys_copy_type (
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_target_t      target,
+        rsbac_rc_type_id_t     from_type,
+        rsbac_rc_type_id_t     to_type)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_RC
+    if(rsbac_switch_rc)
+#endif
+      {
+        int err;
+
+        switch(target)
+          {
+            case T_FILE:
+            case T_DIR:
+            case T_FIFO:
+            case T_SYMLINK:
+              target = T_FD;
+              break;
+            case T_FD:
+            case T_DEV:
+            case T_USER:
+            case T_PROCESS:
+            case T_IPC:
+            case T_GROUP:
+            case T_NETDEV:
+            case T_NETTEMP:
+            case T_NETOBJ:
+              break;
+
+            default:
+              return -RSBAC_EINVALIDTARGET;
+          }
+        /* need ADMIN right to source type or caller must be role_admin */
+        if(   (rsbac_rc_check_type_comp(target, from_type, RCR_ADMIN, 0) != GRANTED)
+           && (err=rsbac_rc_test_role_admin(FALSE))
+          )
+          {
+            if(err == -EPERM)
+              {
+                rsbac_uid_t user;
+
+                if(!rsbac_get_owner(&user))
+                  {
+                    char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                    if(tmp)
+                      {
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_rc_sys_copy_type(): copying of %s type %u denied for pid %u, user %u - not in admin_roles!\n",
+                                     get_target_name_only(tmp, target),
+                                     from_type,
+                                     current->pid,
+                                     user);
+                        rsbac_kfree(tmp);
+                      }
+                  }
+                #ifdef CONFIG_RSBAC_SOFTMODE
+                if(   !rsbac_softmode
+                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                   && !rsbac_ind_softmode[SW_RC]
+                #endif
+                  )
+                #endif
+                  return err;
+              }
+            else
+              return err;
+          }
+        /* only role_admins may copy to existing targets */
+        if (   rsbac_rc_type_exists(ta_number, target, to_type)
+            && rsbac_rc_test_role_admin(TRUE)
+           )
+          {
+            rsbac_uid_t user;
+
+            if(!rsbac_get_owner(&user))
+              {
+                char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+                if(tmp)
+                  {
+                    rsbac_printk(KERN_INFO
+                                 "rsbac_rc_sys_copy_type(): overwriting of existing %s type %u denied for pid %u, user %u - no role_admin!\n",
+                                 get_target_name_only(tmp, target),
+                                 to_type,
+                                 current->pid,
+                                 user);
+                    rsbac_kfree(tmp);
+                  }
+              }
+            #ifdef CONFIG_RSBAC_SOFTMODE
+            if(   !rsbac_softmode
+            #ifdef CONFIG_RSBAC_SOFTMODE_IND
+               && !rsbac_ind_softmode[SW_RC]
+            #endif
+              )
+            #endif
+              return -EPERM;
+          }
+      }
+
+    /* pass on */
+    return(rsbac_rc_copy_type(ta_number, target, from_type, to_type));
+  }
+
+/* Getting values */
+int rsbac_rc_sys_get_item(
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t       target,
+  union rsbac_rc_target_id_t    tid,
+  union rsbac_rc_target_id_t    subtid,
+  enum  rsbac_rc_item_t         item,
+  union rsbac_rc_item_value_t * value_p,
+        rsbac_time_t          * ttl_p)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_RC
+    if(rsbac_switch_rc)
+#endif
+      {
+        int                           err;
+
+        switch(item)
+          {
+            case RI_name:
+            case RI_type_fd_name:
+            case RI_type_dev_name:
+            case RI_type_ipc_name:
+            case RI_type_user_name:
+            case RI_type_process_name:
+            case RI_type_scd_name:
+            case RI_type_group_name:
+            case RI_type_netdev_name:
+            case RI_type_nettemp_name:
+            case RI_type_netobj_name:
+              /* getting names is always allowed */
+              break;
+
+            case RI_type_fd_need_secdel:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (err=rsbac_rc_check_type_comp(T_FILE, tid.type, RCR_ADMIN, 0))
+                 && (err=rsbac_rc_test_role_admin(FALSE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_get_item(): reading fd_need_secdel of type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return err;
+                    }
+                  else
+                    return err;
+                }
+              break;
+
+            default:
+              if(target != RT_ROLE)
+                return -RSBAC_EINVALIDATTR;
+              /* test admin_roles or admin_type of process' role / no modify */
+              if (   (err=rsbac_rc_test_admin_roles(tid.role, FALSE))
+                  && (err=rsbac_rc_test_role_admin(FALSE))
+                 )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_get_item(): getting item of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return err;
+                    }
+                  else
+                    return err;
+                }
+          }
+      }
+
+    /* pass on */
+    return(rsbac_rc_get_item(ta_number,target, tid, subtid, item, value_p, ttl_p));
+  }
+
+/* Setting values */
+int rsbac_rc_sys_set_item(
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t       target,
+  union rsbac_rc_target_id_t    tid,
+  union rsbac_rc_target_id_t    subtid,
+  enum  rsbac_rc_item_t         item,
+  union rsbac_rc_item_value_t   value,
+        rsbac_time_t            ttl)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_RC
+    if(rsbac_switch_rc)
+#endif
+      {
+        int                           err;
+
+        switch(item)
+          {
+          /* type targets */
+            case RI_type_fd_name:
+            case RI_type_fd_need_secdel:
+            case RI_type_fd_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_FILE, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+                      char tmp[80];
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing %s of FD type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       get_rc_item_name(tmp, item),
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_dev_name:
+            case RI_type_dev_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_DEV, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of DEV type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_ipc_name:
+            case RI_type_ipc_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_IPC, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of IPC type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_user_name:
+            case RI_type_user_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_USER, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of USER type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_process_name:
+            case RI_type_process_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_PROCESS, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of process type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_scd_name:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_SCD, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of SCD type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_group_name:
+            case RI_type_group_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_GROUP, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of GROUP type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_netdev_name:
+            case RI_type_netdev_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_NETDEV, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of NETDEV type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_nettemp_name:
+            case RI_type_nettemp_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_NETTEMP, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of NETTEMP type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_type_netobj_name:
+            case RI_type_netobj_remove:
+              if(target != RT_TYPE)
+                return -RSBAC_EINVALIDTARGET;
+              if(   (rsbac_rc_check_type_comp(T_NETOBJ, tid.type, RCR_ADMIN, 0) == NOT_GRANTED)
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name or removing of NETOBJ type %u denied for pid %u, user %u - no ADMIN right!\n",
+                                       tid.type,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+
+          /* roles only from here */
+            case RI_role_comp:
+              /* need admin for this role, assign for changed compatible roles */
+              {
+                union rsbac_target_id_t       i_tid;
+                union rsbac_attribute_value_t i_attr_val1;
+
+                if(target != RT_ROLE)
+                  return -RSBAC_EINVALIDATTR;
+                if(!rsbac_rc_test_role_admin(TRUE))
+                  break;
+                /* test admin_role of process / modify */
+                if((err=rsbac_rc_test_admin_roles(tid.role, TRUE)))
+                  {
+                    if(err == -EPERM)
+                      {
+                        rsbac_uid_t user;
+
+                        if(!rsbac_get_owner(&user))
+                          {
+                            rsbac_printk(KERN_INFO
+                                         "rsbac_rc_sys_set_item(): changing role_comp of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                         tid.role,
+                                         current->pid,
+                                         user);
+                          }
+                      }
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    if(   !rsbac_softmode
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                       && !rsbac_ind_softmode[SW_RC]
+                    #endif
+                      )
+                    #endif
+                      return err;
+                  }
+                /* now check assign for changed comp role. */
+                /* get rc_role of process */
+                i_tid.process = task_pid(current);
+                if ((err=rsbac_get_attr(SW_RC, T_PROCESS,
+                                        i_tid,
+                                        A_rc_role,
+                                        &i_attr_val1,
+                                        FALSE)))
+                  {
+                    rsbac_pr_get_error(A_rc_role);
+                    return -RSBAC_EREADFAILED;
+                  }
+                /* check assign_roles of role */
+                if (!rsbac_rc_check_comp(i_attr_val1.rc_role,
+                                         tid,
+                                         RI_assign_roles,
+                                         R_NONE))
+                  {
+                    rsbac_uid_t user;
+                    if(!rsbac_get_owner(&user))
+                      {
+                        rsbac_printk(KERN_INFO
+                                     "rsbac_rc_sys_set_item(): changing role_comp for role %u denied for user %u, role %u - not in assign_roles!\n",
+                                     tid.role,
+                                     user,
+                                     i_attr_val1.rc_role);
+                      }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                      return -EPERM;
+                  }
+              }
+              break;
+
+            case RI_admin_type:
+            case RI_admin_roles:
+            case RI_assign_roles:
+            case RI_boot_role:
+	    case RI_req_reauth:
+              /* admin_type role_admin */
+              if((err=rsbac_rc_test_role_admin(TRUE)))
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+                      char tmp[80];
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing %s of role %u denied for pid %u, user %u - no Role Admin!\n",
+                                       get_rc_item_name(tmp, item),
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+            case RI_name:
+              /* admin for this role */
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing name of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+
+            case RI_remove_role:
+              /* test admin_role of process role / modify */
+              if((err=rsbac_rc_test_role_admin(TRUE)))
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): removing of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+
+            case RI_def_fd_create_type:
+            case RI_def_fd_ind_create_type:
+              /* admin for this role and assign for target type */
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_fd_[ind_]create_type of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              else
+                {
+                  enum rsbac_adf_req_ret_t result;
+
+                  result = rsbac_rc_check_type_comp(T_FILE, value.type_id, RCR_ASSIGN, 0);
+                  if(   (   (result == NOT_GRANTED)
+                         || (result == UNDEFINED)
+                        )
+                     && (err=rsbac_rc_test_role_admin(TRUE))
+                    )
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_fd_[ind_]create_type for role %u to %u denied for user %u - no ASSIGN right for type!\n",
+                                       tid.role,
+                                       value.type_id,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return -EPERM;
+                    }
+                }
+              break;
+
+            case RI_def_fd_ind_create_type_remove:
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_fd_[ind_]create_type of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              break;
+
+            case RI_def_user_create_type:
+              /* admin for this role and assign for target type */
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_user_create_type of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              else
+                {
+                  enum rsbac_adf_req_ret_t result;
+
+                  result = rsbac_rc_check_type_comp(T_USER, value.type_id, RCR_ASSIGN, 0);
+                  if(   (   (result == NOT_GRANTED)
+                         || (result == UNDEFINED)
+                        )
+                     && (err=rsbac_rc_test_role_admin(TRUE))
+                    )
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_user_create_type for role %u to %u denied for user %u - no ASSIGN right for type!\n",
+                                       tid.role,
+                                       value.type_id,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return -EPERM;
+                    }
+                }
+              break;
+
+            case RI_def_process_create_type:
+            case RI_def_process_chown_type:
+            case RI_def_process_execute_type:
+              /* admin for this role and assign for target type */
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+                      char tmp[80];
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing %s of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       get_rc_item_name(tmp, item),
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              else
+                {
+                  enum rsbac_adf_req_ret_t result;
+
+                  result = rsbac_rc_check_type_comp(T_PROCESS, value.type_id, RCR_ASSIGN, 0);
+                  if(   (   (result == NOT_GRANTED)
+                         || (result == UNDEFINED)
+                        )
+                     && (err=rsbac_rc_test_role_admin(TRUE))
+                    )
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_process_*_type for role %u to %u denied for user %u - no ASSIGN right for type!\n",
+                                       tid.role,
+                                       value.type_id,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return -EPERM;
+                    }
+                }
+              break;
+            case RI_def_ipc_create_type:
+              /* admin for this role and assign for target type */
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_ipc_create_type of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              else
+                {
+                  enum rsbac_adf_req_ret_t result;
+
+                  result = rsbac_rc_check_type_comp(T_IPC, value.type_id, RCR_ASSIGN, 0);
+                  if(   (   (result == NOT_GRANTED)
+                         || (result == UNDEFINED)
+                        )
+                     && (err=rsbac_rc_test_role_admin(TRUE))
+                    )
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_ipc_create_type for role %u to %u denied for user %u - no ASSIGN right for type!\n",
+                                       tid.role,
+                                       value.type_id,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return -EPERM;
+                    }
+                }
+              break;
+            case RI_def_group_create_type:
+              /* admin for this role and assign for target type */
+              /* test admin_role of process / modify */
+              if(   (err=rsbac_rc_test_admin_roles(tid.role, TRUE))
+                 && (err=rsbac_rc_test_role_admin(TRUE))
+                )
+                {
+                  if(err == -EPERM)
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_group_create_type of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                       tid.role,
+                                       current->pid,
+                                       user);
+                        }
+                    }
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+              else
+                {
+                  enum rsbac_adf_req_ret_t result;
+
+                  result = rsbac_rc_check_type_comp(T_GROUP, value.type_id, RCR_ASSIGN, 0);
+                  if(   (   (result == NOT_GRANTED)
+                         || (result == UNDEFINED)
+                        )
+                     && (err=rsbac_rc_test_role_admin(TRUE))
+                    )
+                    {
+                      rsbac_uid_t user;
+
+                      if(!rsbac_get_owner(&user))
+                        {
+                          rsbac_printk(KERN_INFO
+                                       "rsbac_rc_sys_set_item(): changing def_group_create_type for role %u to %u denied for user %u - no ASSIGN right for type!\n",
+                                       tid.role,
+                                       value.type_id,
+                                       user);
+                        }
+                      #ifdef CONFIG_RSBAC_SOFTMODE
+                      if(   !rsbac_softmode
+                      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                         && !rsbac_ind_softmode[SW_RC]
+                      #endif
+                        )
+                      #endif
+                        return -EPERM;
+                    }
+                }
+              break;
+            case RI_def_unixsock_create_type:
+			/* admin for this role and assign for target type */
+			/* test admin_role of process / modify */
+			if ((err =
+			     rsbac_rc_test_admin_roles(tid.role, TRUE))
+			    && (err = rsbac_rc_test_role_admin(TRUE))
+			    ) {
+				if (err == -EPERM) {
+					rsbac_uid_t user;
+
+					if (!rsbac_get_owner(&user)) {
+						rsbac_printk(KERN_INFO "rsbac_rc_sys_set_item(): changing def_unixsock_create_type of role %u denied for pid %u, user %u - not in admin_roles\n",
+							     tid.role,
+							     current->pid,
+							     user);
+					}
+                                }
+                                #ifdef CONFIG_RSBAC_SOFTMODE
+                                if(   !rsbac_softmode
+                                #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                                   && !rsbac_ind_softmode[SW_RC]
+                                #endif
+                                  )
+                                #endif
+                                  return err;
+			} else {
+				enum rsbac_adf_req_ret_t result;
+
+				result =
+				    rsbac_rc_check_type_comp(T_UNIXSOCK,
+							     value.type_id,
+							     RCR_ASSIGN,
+							     0);
+				if (((result == NOT_GRANTED)
+				     || (result == UNDEFINED)
+				    )
+				    && (err =
+					rsbac_rc_test_role_admin(TRUE))
+				    ) {
+					rsbac_uid_t user;
+
+					if (!rsbac_get_owner(&user)) {
+						rsbac_printk(KERN_INFO "rsbac_rc_sys_set_item(): changing def_unixsock_create_type for role %u to %u denied for user %u - no ASSIGN right for type\n",
+							     tid.role,
+							     value.type_id,
+							     user);
+					}
+#ifdef CONFIG_RSBAC_SOFTMODE
+					if (!rsbac_softmode
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+					    && !rsbac_ind_softmode[SW_RC]
+#endif
+					    )
+#endif
+						return -EPERM;
+				}
+			}
+			break;
+
+
+            case RI_type_comp_fd:
+            case RI_type_comp_dev:
+            case RI_type_comp_user:
+            case RI_type_comp_process:
+            case RI_type_comp_ipc:
+            case RI_type_comp_scd:
+            case RI_type_comp_group:
+            case RI_type_comp_netdev:
+            case RI_type_comp_nettemp:
+            case RI_type_comp_netobj:
+              {
+                union rsbac_rc_item_value_t old_value, my_value;
+                union rsbac_target_id_t       i_tid;
+                union rsbac_attribute_value_t i_attr_val1;
+                union rsbac_rc_target_id_t    i_rc_tid;
+
+                if(target != RT_ROLE)
+                  return -RSBAC_EINVALIDATTR;
+                if(!rsbac_rc_test_role_admin(TRUE))
+                  break;
+                /* test admin_role of process / modify */
+                if((err=rsbac_rc_test_admin_roles(tid.role, TRUE)))
+                  {
+                    if(err == -EPERM)
+                      {
+                        rsbac_uid_t user;
+                        char tmp[80];
+
+                        if(!rsbac_get_owner(&user))
+                          {
+                            rsbac_printk(KERN_INFO
+                                         "rsbac_rc_sys_set_item(): changing %s of role %u denied for pid %u, user %u - not in admin_roles!\n",
+                                         get_rc_item_name(tmp, item),
+                                         tid.role,
+                                         current->pid,
+                                         user);
+                          }
+                      }
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    if(   !rsbac_softmode
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                       && !rsbac_ind_softmode[SW_RC]
+                    #endif
+                      )
+                    #endif
+                      return err;
+                  }
+                /* test caller's RCR_ACCESS_CONTROL for the type, if we change normal access */
+                /* and caller's RCR_SUPERVISOR for the type, if we change special rights */
+                /* first get old setting */
+                err = rsbac_rc_get_item(ta_number, target, tid, subtid, item, &old_value, NULL);
+                if(err) {
+                  #ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+                  #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RC]
+                  #endif
+                    )
+                  #endif
+                    return err;
+                }
+
+                /* get rc_role of process */
+                i_tid.process = task_pid(current);
+                if ((err=rsbac_get_attr(SW_RC, T_PROCESS,
+                                        i_tid,
+                                        A_rc_role,
+                                        &i_attr_val1,
+                                        FALSE)))
+                  {
+                    rsbac_pr_get_error(A_rc_role);
+                    return err;
+                  }
+                /* get item of process role */
+                i_rc_tid.role = i_attr_val1.rc_role;
+                if ((err=rsbac_rc_get_item(ta_number,
+                                           RT_ROLE,
+                                           i_rc_tid,
+                                           subtid,
+                                           item,
+                                           &my_value,
+                                           NULL)))
+                  {
+                    rsbac_rc_pr_get_error(item);
+                    #ifdef CONFIG_RSBAC_SOFTMODE
+                    if(   !rsbac_softmode
+                    #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                       && !rsbac_ind_softmode[SW_RC]
+                    #endif
+                      )
+                    #endif
+                      return err;
+                  }
+
+                /* check planned changes for type */
+                if(   /* Want to change normal rights to this type? Need RCR_ACCESS_CONTROL. */
+                      (   (   (old_value.rights & RSBAC_ALL_REQUEST_VECTOR)
+                           != (value.rights & RSBAC_ALL_REQUEST_VECTOR)
+                          )
+                       && (!(my_value.rights & RSBAC_RC_RIGHTS_VECTOR(RCR_ACCESS_CONTROL)))
+                      )
+                   ||    
+                      /* Want to change special rights to this type? Need RCR_SUPERVISOR. */
+                      (   (   (old_value.rights & RSBAC_RC_SPECIAL_RIGHTS_VECTOR)
+                           != (value.rights & RSBAC_RC_SPECIAL_RIGHTS_VECTOR)
+                          )
+                       && (!(my_value.rights & RSBAC_RC_RIGHTS_VECTOR(RCR_SUPERVISOR)))
+                      )
+                  )
+                  {
+                    /* check failed. Last resort: Classical admin_type. */
+                    if((err=rsbac_rc_test_role_admin(TRUE)))
+                      {
+                        if(err == -EPERM)
+                          {
+                            rsbac_uid_t user;
+                            char tmp[80];
+
+                            if(!rsbac_get_owner(&user))
+                              {
+                                rsbac_printk(KERN_INFO
+                                             "rsbac_rc_sys_set_item(): changing %s of role %u denied for pid %u, user %u, role %u - insufficent rights!\n",
+                                             get_rc_item_name(tmp, item),
+                                             tid.role,
+                                             current->pid,
+                                             user,
+                                             i_attr_val1.rc_role);
+                              }
+                          }
+                        #ifdef CONFIG_RSBAC_SOFTMODE
+                        if(   !rsbac_softmode
+                        #ifdef CONFIG_RSBAC_SOFTMODE_IND
+                           && !rsbac_ind_softmode[SW_RC]
+                        #endif
+                          )
+                        #endif
+                          return err;
+                      }
+                  }
+              }
+              break;
+
+            default:
+              return -RSBAC_EINVALIDATTR;
+          }
+      }
+
+    /* pass on */
+    return(rsbac_rc_set_item(ta_number, target, tid, subtid, item, value, ttl));
+  }
+
+/* Set own role, if allowed ( = in role_comp vector of current role) */
+int rsbac_rc_sys_change_role(rsbac_rc_role_id_t role, char __user * pass)
+{
+	int err;
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+#ifdef CONFIG_RSBAC_UM
+	union rsbac_rc_item_value_t i_rc_item_val1;
+	char *k_pass;
+#endif
+
+#ifdef CONFIG_RSBAC_SWITCH_RC
+	if (rsbac_switch_rc)
+#endif
+	{
+		union rsbac_rc_target_id_t i_rc_subtid;
+
+		i_tid.process = task_pid(current);
+		/* get rc_role of process */
+		if ((err = rsbac_get_attr(SW_RC,
+					  T_PROCESS,
+					  i_tid,
+					  A_rc_role,
+					  &i_attr_val1, FALSE))) {
+			rsbac_printk(KERN_WARNING "rsbac_rc_sys_change_role(): rsbac_get_attr() returned error %i\n",
+				     err);
+			goto out;
+		}
+
+		/* check role_comp of role */
+		i_rc_subtid.role = role;
+		if (!rsbac_rc_check_comp(i_attr_val1.rc_role,
+					 i_rc_subtid, RI_role_comp, 0)) {
+			rsbac_uid_t user;
+
+			if (!rsbac_get_owner(&user)) {
+				rsbac_printk(KERN_INFO "rsbac_rc_sys_change_role(): changing from role %u to %u denied for pid %u, user %u, role %u - roles not compatible\n",
+					     i_attr_val1.rc_role,
+					     role,
+					     pid_nr(i_tid.process),
+					     user, i_attr_val1.rc_role);
+			}
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+			    && !rsbac_ind_softmode[SW_RC]
+#endif
+			    )
+#endif
+			{
+				err = -EPERM;
+				goto out;
+			}
+		}
+#ifdef CONFIG_RSBAC_UM
+		/* need to make sure UM is compilled in and active
+		* XXX what to do about softmode here
+		*/
+		if ((err = rsbac_rc_get_item(0, RT_ROLE, i_rc_subtid, i_rc_subtid,	
+					     RI_req_reauth,
+					     &i_rc_item_val1, NULL))) {
+			rsbac_printk(KERN_WARNING "rsbac_rc_sys_change_role(): rsbac_rc_get_item() returned error %i\n",
+				     err);
+			err = -EPERM;
+			goto out;
+		}
+		if (i_rc_item_val1.req_reauth) {
+			rsbac_uid_t user;
+
+			if (!pass) {
+				rsbac_printk(KERN_WARNING "rsbac_rc_sys_change_role(): password required for switching to role %u\n",
+					     role);
+				err = -EPERM;
+				goto out;
+			}
+			k_pass = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (!k_pass) {
+				err = -RSBAC_ENOMEM;
+				goto out;
+			}
+			err = strncpy_from_user(k_pass, pass, RSBAC_MAXNAMELEN);
+			if(unlikely(err < 0))
+				goto out_free;
+			k_pass[RSBAC_MAXNAMELEN - 1] = 0;
+			err = rsbac_get_owner(&user);
+			if (err) {
+				rsbac_printk(KERN_WARNING "rsbac_rc_sys_change_role(): rsbac_rc_get_item() returned error %i\n",
+					     err);
+				goto out_free;
+			}
+			err = rsbac_um_check_pass(user, k_pass);
+			if (err) {
+				goto out_free;
+			}
+		}
+#endif
+
+	}
+
+	/* OK, check passed. Set role. */
+	i_tid.process = task_pid(current);
+	i_attr_val1.rc_role = role;
+	if (rsbac_set_attr(SW_RC, T_PROCESS, i_tid, A_rc_role, i_attr_val1)) {	/* failed! */
+		rsbac_printk(KERN_WARNING "rsbac_rc_sys_change_role(): rsbac_set_attr() returned error\n");
+		err = -RSBAC_EWRITEFAILED;
+	}
+	else
+		err = 0;
+
+out:
+	return err;
+
+#ifdef CONFIG_RSBAC_UM
+out_free:
+	memset(k_pass, 0, RSBAC_MAXNAMELEN);
+	rsbac_kfree(k_pass);
+	goto out;
+#endif
+}
+
+/* Getting own effective rights */
+int rsbac_rc_sys_get_eff_rights(
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_target_t       target,
+  union rsbac_target_id_t    tid,
+        rsbac_rc_request_vector_t * request_vector,
+        rsbac_time_t       * ttl_p)
+  {
+    union rsbac_target_id_t       i_tid;
+    enum  rsbac_attribute_t       i_attr = A_none;
+    union rsbac_attribute_value_t i_attr_val1;
+    union rsbac_attribute_value_t i_attr_val2;
+    int                           err;
+    enum  rsbac_rc_item_t         i_rc_item;
+    union rsbac_rc_target_id_t    i_rc_tid;
+    union rsbac_rc_target_id_t    i_rc_subtid;
+    union rsbac_rc_item_value_t   i_rc_item_val1;
+
+    i_tid.process = task_pid(current);
+    /* get rc_role of process */
+    if ((err=rsbac_get_attr(SW_RC, T_PROCESS,
+                       i_tid,
+                       A_rc_role,
+                       &i_attr_val1,
+                       FALSE)))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_rc_sys_get_eff_rights(): rsbac_get_attr() returned error %i!\n",err);
+        return -RSBAC_EREADFAILED;
+      }
+
+    switch(target)
+      {
+        case T_FILE:
+        case T_DIR:
+        case T_FIFO:
+        case T_SYMLINK:
+          i_attr = A_rc_type_fd;
+          i_rc_item = RI_type_comp_fd;
+          break;
+        case T_DEV:
+          i_attr = A_rc_type;
+          i_rc_item = RI_type_comp_dev;
+          break;
+        case T_IPC:
+          i_attr = A_rc_type;
+          i_rc_item = RI_type_comp_ipc;
+          break;
+        case T_PROCESS:
+          i_attr = A_rc_type;
+          i_rc_item = RI_type_comp_process;
+          break;
+        case T_SCD: /* special case! */
+          if(tid.scd >= RST_none)
+            return -RSBAC_EINVALIDTARGET;
+          i_rc_item = RI_type_comp_scd;
+          break;
+        case T_GROUP:
+          i_attr = A_rc_type;
+          i_rc_item = RI_type_comp_group;
+          break;
+        case T_NETDEV:
+          i_attr = A_rc_type;
+          i_rc_item = RI_type_comp_netdev;
+          break;
+        case T_NETTEMP:
+          i_attr = A_rc_type_nt;
+          i_rc_item = RI_type_comp_nettemp;
+          break;
+        case T_NETOBJ:
+          i_attr = A_rc_type;
+          i_rc_item = RI_type_comp_netobj;
+          break;
+        default:
+          return -RSBAC_EINVALIDTARGET;
+      }
+    /* get rc_type of target */
+    if(target == T_SCD)
+      {
+        i_attr_val2.rc_type = tid.scd;
+      }
+    else
+      {
+        if ((err=rsbac_get_attr(SW_RC,
+                                target,
+                                tid,
+                                i_attr,
+                                &i_attr_val2,
+                                TRUE)))
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbac_rc_sys_get_eff_rights(): rsbac_get_attr() returned error %i!\n",err);
+            return -RSBAC_EREADFAILED;
+          }
+      }
+    /* get type_comp_xxx of role for type and target */
+    i_rc_tid.role = i_attr_val1.rc_role;
+    i_rc_subtid.type = i_attr_val2.rc_type;
+    if ((err=rsbac_rc_get_item(ta_number,
+                                RT_ROLE,
+                                i_rc_tid,
+                                i_rc_subtid,
+                                i_rc_item,
+                                &i_rc_item_val1,
+                                ttl_p)))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_rc_sys_get_eff_rights(): rsbac_rc_get_item() returned error %i!\n",err);
+        return -RSBAC_EREADFAILED;
+      }
+    /* extract value */
+    *request_vector = i_rc_item_val1.rights;
+    /* Ready. */
+    return 0;
+  }
+
+int rsbac_rc_sys_get_current_role(rsbac_rc_role_id_t * role_p)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+    int err;
+
+    /* get rc_role of process */
+    i_tid.process = task_pid(current);
+    if ((err=rsbac_get_attr(SW_RC, T_PROCESS,
+                       i_tid,
+                       A_rc_role,
+                       &i_attr_val1,
+                       FALSE)))
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbac_rc_sys_get_current_role(): rsbac_get_attr() returned error %i!\n",err);
+        return -RSBAC_EREADFAILED;
+      }
+    *role_p = i_attr_val1.rc_role;
+    /* Ready. */
+    return 0;
+  }
+
+int rsbac_rc_select_fd_create_type(rsbac_rc_type_id_t type)
+{
+
+	int res;
+
+	union rsbac_target_id_t tid;
+	union rsbac_attribute_value_t attr_val;
+
+	/* sanity checks */
+	if (type != RC_type_use_fd) {
+		if (!rsbac_rc_type_exists(0, T_FILE, type))
+			return -RSBAC_EINVALIDVALUE;
+		if (!rsbac_rc_check_type_comp(T_FILE, type, RCR_SELECT, task_pid(current))) {
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if(   !rsbac_softmode
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+			   && !rsbac_ind_softmode[SW_RC]
+#endif
+			)
+#endif
+				return -EPERM;
+		}
+	}
+
+	tid.process = task_pid(current);
+	attr_val.rc_select_type = type;
+	if ((res = rsbac_set_attr(SW_RC,
+				  T_PROCESS,
+				  tid,
+				  A_rc_select_type,
+				  attr_val))) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_select_fd_create_type(): rsbac_set_attr() returned error %i\n", res);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+/* end of rsbac/adf/rc/syscalls.c */
diff --git a/rsbac/adf/reg/Makefile b/rsbac/adf/reg/Makefile
new file mode 100644
index 0000000..2e6fac0
--- /dev/null
+++ b/rsbac/adf/reg/Makefile
@@ -0,0 +1,13 @@
+#
+# File: rsbac/adf/reg/Makefile
+#
+# Makefile for the Linux rsbac REG / registration of decision modules
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+obj-y  := reg_main.o
+ifeq ($(CONFIG_RSBAC_REG_SAMPLES),y)
+obj-m    += reg_sample1.o reg_sample3.o kproc_hide.o modules_off.o
+endif
+
diff --git a/rsbac/adf/reg/kproc_hide.c b/rsbac/adf/reg/kproc_hide.c
new file mode 100644
index 0000000..93d0328
--- /dev/null
+++ b/rsbac/adf/reg/kproc_hide.c
@@ -0,0 +1,121 @@
+/*
+ * RSBAC REG decision module kproc_hide. Hiding kernel processes.
+ *
+ * Author and (c) 2004 Michal Purzynski <albeiro@rsbac.org>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/getname.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+
+MODULE_AUTHOR("Michal Purzynski");
+MODULE_DESCRIPTION("RSBAC REG kproc_hide decision module");
+MODULE_LICENSE("GPL");
+
+static long handle = 9999992;
+
+/**** Helper Functions ****/
+
+/**********************************************************************
+Description:  Checks if process is a kernel process.
+Parameters:   Pid of checking process.
+Return value: 1 if is, 0 otherwise.
+**********************************************************************/
+
+int is_kproc(struct pid *pid)
+{
+	struct task_struct *tid_task;
+
+	tid_task = pid_task(pid, PIDTYPE_PID);
+
+	if (tid_task->mm == NULL)
+		return 1;
+	else
+		return 0;
+}
+
+/**** Decision Functions ****/
+
+static int request_func(enum rsbac_adf_request_t	request,
+			rsbac_pid_t			owner_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)
+{  
+
+	switch (request) {
+		case R_GET_STATUS_DATA:
+			switch (target) {
+				case T_PROCESS:
+					if (is_kproc(tid.process))
+					return NOT_GRANTED;
+				default:
+					return DO_NOT_CARE;
+			}
+		default:
+			return DO_NOT_CARE;
+	}
+	
+/*
+	if (request == R_GET_STATUS_DATA && target == T_PROCESS && is_kproc(tid.process))
+		return NOT_GRANTED;
+	else
+		return GRANTED;
+*/
+}
+
+/**** Init ****/
+
+int init_module(void)
+{
+	struct rsbac_reg_entry_t entry;
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module kproc_hide: Initializing.\n");
+
+	/* clearing registration entries */
+	memset(&entry, 0, sizeof(entry));
+
+	strcpy(entry.name, "RSBAC REG kproc_hide ADF module");
+	rsbac_printk(KERN_INFO "RSBAC REG decision module kproc_hide: REG Version: %u, Name: %s, Handle: %li\n",
+								RSBAC_REG_VERSION, entry.name, handle);
+
+	entry.handle = handle;
+	entry.request_func = request_func;
+	entry.switch_on = TRUE;
+	rsbac_printk(KERN_INFO "RSBAC REG decision module kproc_hide: Registering to ADF.\n");
+	
+	if(rsbac_reg_register(RSBAC_REG_VERSION, entry) < 0) {
+		rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 1: Registering failed. Unloading.\n");
+		return -ENOEXEC;
+	}
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module kproc_hide: Loaded.\n");
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	rsbac_printk(KERN_INFO "RSBAC REG decision module kproc_hide: Unregistering.\n");
+	
+	if(rsbac_reg_unregister(handle))
+	{
+		rsbac_printk(KERN_ERR "RSBAC REG decision module kproc_hide: Unregistering failed - beware of possible system failure!\n");
+	}
+	
+	rsbac_printk(KERN_INFO "RSBAC REG decision module kproc_hide: Unloaded.\n");
+}
+
diff --git a/rsbac/adf/reg/modules_off.c b/rsbac/adf/reg/modules_off.c
new file mode 100644
index 0000000..e19a488
--- /dev/null
+++ b/rsbac/adf/reg/modules_off.c
@@ -0,0 +1,90 @@
+/*
+ *   RSBAC REG decision module kproc_hide. Disabling kernel modules support.
+ *   
+ *   Author and (c) 2004 Michal Purzynski <michal@rsbac.org>
+ *   Adjusted 2011 Amon Ott <ao@rsbac.org>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/getname.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+#include <linux/namei.h>
+
+MODULE_AUTHOR("Michal Purzynski");
+MODULE_DESCRIPTION("RSBAC REG modules_off decision module");
+MODULE_LICENSE("GPL");
+
+static long handle = 9999991;
+
+/**** Decision Functions ****/
+
+static int request_func (enum rsbac_adf_request_t	request,
+			rsbac_pid_t			owner_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)
+{
+	switch (request) {
+		case R_ADD_TO_KERNEL:
+		case R_REMOVE_FROM_KERNEL:
+			return NOT_GRANTED;
+		default:
+			return DO_NOT_CARE;
+	}
+}
+
+/**** Init ****/
+
+int init_module(void)
+{
+
+	struct rsbac_reg_entry_t entry;
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module modules_off: Initializing.\n");
+
+	/* clearing registration entries */
+	memset(&entry, 0, sizeof(entry));
+
+	strcpy(entry.name, "RSBAC REG modules_off ADF module");
+	rsbac_printk(KERN_INFO "RSBAC REG decision module modules_off: REG Version: %u, Name: %s, Handle: %li\n",RSBAC_REG_VERSION, entry.name, handle);
+
+	entry.handle = handle;
+	entry.request_func = request_func;
+	entry.switch_on = TRUE;
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module modules_off: Registering to ADF.\n");
+
+	if(rsbac_reg_register(RSBAC_REG_VERSION, entry) < 0)
+	{
+		rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 1: Registering failed. Unloading.\n");
+		return -ENOEXEC;
+	}
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module modules_off: Loaded.\n");
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	rsbac_printk(KERN_INFO "RSBAC REG decision module modules_off: Unregistering.\n");
+
+	if(rsbac_reg_unregister(handle))
+	{
+		rsbac_printk(KERN_ERR "RSBAC REG decision module modules_off: Unregistering failed - beware of possible system failure!\n");
+	}
+	
+	rsbac_printk(KERN_INFO "RSBAC REG decision module modules_off: Unloaded.\n");
+}
+
diff --git a/rsbac/adf/reg/reg_main.c b/rsbac/adf/reg/reg_main.c
new file mode 100644
index 0000000..de803a4
--- /dev/null
+++ b/rsbac/adf/reg/reg_main.c
@@ -0,0 +1,928 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - REG / Decision Module Registration */
+/* File: rsbac/adf/reg/main.c                        */
+/*                                                   */
+/* Author and (c) 1999-2011: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 12/Jul/2011                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <linux/seq_file.h>
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/reg_main.h>
+#include <rsbac/aci.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/adf.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/rkmem.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+static struct rsbac_reg_list_head_t     list_head;
+static struct rsbac_reg_sc_list_head_t  sc_list_head;
+
+/************************************************* */
+/*           Internal functions                    */
+/************************************************* */
+
+static void reg_read_lock(void)
+  {
+    spin_lock(&list_head.lock);
+    while(list_head.readers < 0)
+      {
+        spin_unlock(&list_head.lock);
+        spin_lock(&list_head.lock);
+      }
+    list_head.readers++;
+    spin_unlock(&list_head.lock);
+  }
+
+static void reg_read_unlock(void)
+  {
+    spin_lock(&list_head.lock);
+    list_head.readers--;
+    spin_unlock(&list_head.lock);
+  }
+
+static void reg_write_lock(void)
+  {
+    spin_lock(&list_head.lock);
+    while(list_head.readers != 0)
+      {
+        spin_unlock(&list_head.lock);
+        spin_lock(&list_head.lock);
+      }
+    list_head.readers = -1;
+    spin_unlock(&list_head.lock);
+  }
+
+static void reg_write_unlock(void)
+  {
+    spin_lock(&list_head.lock);
+    list_head.readers = 0;
+    spin_unlock(&list_head.lock);
+  }
+
+static void reg_sc_read_lock(void)
+  {
+    spin_lock(&sc_list_head.lock);
+    while(sc_list_head.readers < 0)
+      {
+        spin_unlock(&sc_list_head.lock);
+        spin_lock(&sc_list_head.lock);
+      }
+    sc_list_head.readers++;
+    spin_unlock(&sc_list_head.lock);
+  }
+
+static void reg_sc_read_unlock(void)
+  {
+    spin_lock(&sc_list_head.lock);
+    sc_list_head.readers--;
+    spin_unlock(&sc_list_head.lock);
+  }
+
+static void reg_sc_write_lock(void)
+  {
+    spin_lock(&sc_list_head.lock);
+    while(sc_list_head.readers != 0)
+      {
+        spin_unlock(&sc_list_head.lock);
+        spin_lock(&sc_list_head.lock);
+      }
+    sc_list_head.readers = -1;
+    spin_unlock(&sc_list_head.lock);
+  }
+
+static void reg_sc_write_unlock(void)
+  {
+    spin_lock(&sc_list_head.lock);
+    sc_list_head.readers = 0;
+    spin_unlock(&sc_list_head.lock);
+  }
+
+/* lookup_item() */
+static struct rsbac_reg_list_item_t * lookup_item(rsbac_reg_handle_t handle)
+  {
+    struct rsbac_reg_list_item_t  * curr = list_head.curr;
+
+    /* is the current item the one we look for? yes -> return, else search */
+    if (curr && (curr->entry.handle == handle))
+      return (curr);
+
+    curr = list_head.head;
+    while (curr && (curr->entry.handle != handle))
+      curr = curr->next;
+    if (curr)
+      list_head.curr=curr;
+    return (curr);
+  };
+
+/* lookup_sc_item_reg() */
+static struct rsbac_reg_sc_list_item_t * lookup_sc_item_reg(rsbac_reg_handle_t handle)
+  {
+    struct rsbac_reg_sc_list_item_t  * curr = sc_list_head.curr;
+
+    /* is the current item the one we look for? yes -> return, else search */
+    if (curr && (curr->entry.registration_handle == handle))
+      return (curr);
+
+    curr = sc_list_head.head;
+    while (curr && (curr->entry.registration_handle != handle))
+      curr = curr->next;
+    if (curr)
+      sc_list_head.curr=curr;
+    return (curr);
+  };
+
+/* lookup_sc_item_dis() */
+static struct rsbac_reg_sc_list_item_t * lookup_sc_item_dis(rsbac_reg_handle_t handle)
+  {
+    struct rsbac_reg_sc_list_item_t  * curr = sc_list_head.curr;
+
+    /* is the current item the one we look for? yes -> return, else search */
+    if (curr && (curr->entry.dispatcher_handle == handle))
+      return (curr);
+
+    curr = sc_list_head.head;
+    while (curr && (curr->entry.dispatcher_handle != handle))
+      curr = curr->next;
+    if (curr)
+      sc_list_head.curr=curr;
+    return (curr);
+  };
+
+static struct rsbac_reg_list_item_t* 
+         add_item(struct rsbac_reg_entry_t entry)
+    {
+      struct rsbac_reg_list_item_t * new_item_p = NULL;
+
+      if ( !(new_item_p = (struct rsbac_reg_list_item_t *)
+                 rsbac_kmalloc(sizeof(*new_item_p))) )
+        return(NULL);
+      new_item_p->entry.handle = entry.handle;
+      strncpy(new_item_p->entry.name, entry.name, RSBAC_REG_NAME_LEN);
+      new_item_p->entry.name[RSBAC_REG_NAME_LEN] = 0;
+      new_item_p->entry.request_func = entry.request_func;
+      new_item_p->entry.set_attr_func = entry.set_attr_func;
+      new_item_p->entry.need_overwrite_func = entry.need_overwrite_func;
+      new_item_p->entry.write_func = entry.write_func;
+      new_item_p->entry.mount_func = entry.mount_func;
+      new_item_p->entry.umount_func = entry.umount_func;
+      new_item_p->entry.check_func = entry.check_func;
+      new_item_p->entry.switch_on = entry.switch_on;
+      
+      if (!list_head.head)
+        {
+          list_head.head=new_item_p;
+          list_head.tail=new_item_p;
+          list_head.curr=new_item_p;
+          list_head.count = 1;
+          new_item_p->prev=NULL;
+          new_item_p->next=NULL;          
+        }  
+      else
+        {
+          new_item_p->prev=list_head.tail;
+          new_item_p->next=NULL;
+          list_head.tail->next=new_item_p;
+          list_head.tail=new_item_p;
+          list_head.curr=new_item_p;
+          list_head.count++;
+        };
+      return(new_item_p);
+    };
+
+static struct rsbac_reg_sc_list_item_t* 
+         add_sc_item(struct rsbac_reg_syscall_entry_t entry)
+    {
+      struct rsbac_reg_sc_list_item_t * new_item_p = NULL;
+
+      if ( !(new_item_p = (struct rsbac_reg_sc_list_item_t *)
+                 rsbac_kmalloc(sizeof(*new_item_p))) )
+        return(NULL);
+      new_item_p->entry.registration_handle = entry.registration_handle;
+      new_item_p->entry.dispatcher_handle = entry.dispatcher_handle;
+      strncpy(new_item_p->entry.name, entry.name, RSBAC_REG_NAME_LEN);
+      new_item_p->entry.name[RSBAC_REG_NAME_LEN] = 0;
+      new_item_p->entry.syscall_func = entry.syscall_func;
+      
+      if (!sc_list_head.head)
+        {
+          sc_list_head.head=new_item_p;
+          sc_list_head.tail=new_item_p;
+          sc_list_head.curr=new_item_p;
+          sc_list_head.count = 1;
+          new_item_p->prev=NULL;
+          new_item_p->next=NULL;          
+        }  
+      else
+        {
+          new_item_p->prev=sc_list_head.tail;
+          new_item_p->next=NULL;
+          sc_list_head.tail->next=new_item_p;
+          sc_list_head.tail=new_item_p;
+          sc_list_head.curr=new_item_p;
+          sc_list_head.count++;
+        };
+      return(new_item_p);
+    };
+
+static void remove_item(rsbac_reg_handle_t handle)
+    {
+      struct rsbac_reg_list_item_t * item_p;
+    
+      /* first we must locate the item. */
+      if ( (item_p = lookup_item(handle)) )
+        { /* ok, item was found */
+          if ( (list_head.head == item_p) )
+             { /* item is head */
+               if ( (list_head.tail == item_p) )
+                 { /* item is head and tail = only item -> list will be empty*/
+                   list_head.head = NULL;
+                   list_head.tail = NULL;
+                 }
+               else
+                 { /* item is head, but not tail -> next item becomes head */
+                   item_p->next->prev = NULL;
+                   list_head.head = item_p->next;
+                 };
+             }
+          else
+             { /* item is not head */
+               if ( (list_head.tail == item_p) )
+                 { /*item is not head, but tail -> previous item becomes tail*/
+                   item_p->prev->next = NULL;
+                   list_head.tail = item_p->prev;
+                 }
+               else
+                 { /* item is neither head nor tail -> item is cut out */
+                   item_p->prev->next = item_p->next;
+                   item_p->next->prev = item_p->prev;
+                 };
+             };
+             
+          /* curr is no longer valid -> reset */
+          list_head.curr=NULL;
+          /* adjust counter */
+          list_head.count--;
+          /* now we can remove the item from memory */
+          rsbac_kfree(item_p);    
+        };  /* end of if: item was found */
+    }; /* end of remove_item() */
+
+static void remove_sc_item(rsbac_reg_handle_t handle)
+    {
+      struct rsbac_reg_sc_list_item_t * item_p;
+    
+      /* first we must locate the item. */
+      if ( (item_p = lookup_sc_item_reg(handle)) )
+        { /* ok, item was found */
+          if ( (sc_list_head.head == item_p) )
+             { /* item is head */
+               if ( (sc_list_head.tail == item_p) )
+                 { /* item is head and tail = only item -> sc_list will be empty*/
+                   sc_list_head.head = NULL;
+                   sc_list_head.tail = NULL;
+                 }
+               else
+                 { /* item is head, but not tail -> next item becomes head */
+                   item_p->next->prev = NULL;
+                   sc_list_head.head = item_p->next;
+                 };
+             }
+          else
+             { /* item is not head */
+               if ( (sc_list_head.tail == item_p) )
+                 { /*item is not head, but tail -> previous item becomes tail*/
+                   item_p->prev->next = NULL;
+                   sc_list_head.tail = item_p->prev;
+                 }
+               else
+                 { /* item is neither head nor tail -> item is cut out */
+                   item_p->prev->next = item_p->next;
+                   item_p->next->prev = item_p->prev;
+                 };
+             };
+             
+          /* curr is no longer valid -> reset */
+          sc_list_head.curr=NULL;
+          /* adjust counter */
+          sc_list_head.count--;
+          /* now we can remove the item from memory */
+          rsbac_kfree(item_p);    
+        };  /* end of if: item was found */
+    }; /* end of remove_item() */
+
+
+/************************************************* */
+/*           PROC support                          */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+static int
+reg_modules_proc_show(struct seq_file *m, void *v)
+{
+  union rsbac_target_id_t           rsbac_target_id;
+  union rsbac_attribute_value_t     rsbac_attribute_value;
+  struct rsbac_reg_list_item_t    * item_p;
+  struct rsbac_reg_sc_list_item_t * sc_item_p;
+
+  if (!rsbac_is_initialized())
+    return (-ENOSYS);
+
+#ifdef CONFIG_RSBAC_DEBUG
+  if (rsbac_debug_aef)
+    {
+      rsbac_printk(KERN_DEBUG "reg_modules_proc_info(): calling ADF\n");
+    }
+#endif
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                         task_pid(current),
+                         T_SCD,
+                         rsbac_target_id,
+                         A_none,
+                         rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+
+  seq_printf(m, "RSBAC REG registered decision modules\n-------------------------------------\n");
+
+  reg_read_lock();
+  item_p=list_head.head;
+  while(item_p)
+    {
+      if(item_p->entry.name[0] == 0)
+        seq_printf(m, "(no name)\n");
+      else
+        seq_printf(m, "%s\n",
+                       item_p->entry.name);
+      item_p = item_p->next;
+    }
+  reg_read_unlock();
+
+  seq_printf(m, "\n %i module entries used.\n",
+                 list_head.count);
+  seq_printf(m, "\nRSBAC REG registered system calls\n---------------------------------\n");
+
+  reg_sc_read_lock();
+  sc_item_p=sc_list_head.head;
+  while(sc_item_p)
+    {
+      if(sc_item_p->entry.name[0] == 0)
+        seq_printf(m, "%u: (no name)\n",
+                       sc_item_p->entry.dispatcher_handle);
+      else
+        seq_printf(m, "%u: %s\n",
+                       sc_item_p->entry.dispatcher_handle,
+                       sc_item_p->entry.name);
+      sc_item_p = sc_item_p->next;
+    }
+  reg_sc_read_unlock();
+
+  seq_printf(m, "\n %i syscall entries used.\n",
+                 sc_list_head.count);
+  return 0;
+}
+
+static int reg_modules_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, reg_modules_proc_show, NULL);
+}
+
+static const struct file_operations reg_modules_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= reg_modules_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct proc_dir_entry *reg_modules;
+
+#endif /* PROC */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+void rsbac_reg_init(void)
+#else
+void __init rsbac_reg_init(void)
+#endif
+  {
+    if (rsbac_is_initialized())
+      {
+        rsbac_printk(KERN_WARNING "rsbac_reg_init(): RSBAC already initialized\n");
+        return;
+      }
+    /* init data structures */
+    rsbac_printk(KERN_INFO "rsbac_reg_init(): Initializing RSBAC: REG module and syscall registration\n");
+
+    spin_lock_init(&list_head.lock);
+    list_head.readers = 0;
+    list_head.head = NULL;
+    list_head.tail = NULL;
+    list_head.curr = NULL;
+    list_head.count = 0;
+    spin_lock_init(&sc_list_head.lock);
+    sc_list_head.readers = 0;
+    sc_list_head.head = NULL;
+    sc_list_head.tail = NULL;
+    sc_list_head.curr = NULL;
+    sc_list_head.count = 0;
+
+    /* init proc entry */
+    #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+    {
+      reg_modules = proc_create(RSBAC_REG_PROC_NAME,
+                                      S_IFREG | S_IRUGO,
+                                      proc_rsbac_root_p, &reg_modules_proc_fops);
+    }
+    #endif
+  }
+
+
+inline enum rsbac_adf_req_ret_t
+   rsbac_adf_request_reg (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)
+  {
+    enum   rsbac_adf_req_ret_t        result = DO_NOT_CARE;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(   item_p->entry.request_func
+        #ifdef CONFIG_RSBAC_SWITCH_REG
+           && item_p->entry.switch_on
+        #endif
+          )
+          result = adf_and_plus(result,
+                                item_p->entry.request_func (request,
+                                                            caller_pid,
+                                                            target,
+                                                            tid,
+                                                            attr,
+                                                            attr_val,
+                                                            owner) );
+        item_p=item_p->next;
+      }
+    reg_read_unlock();
+    return result;
+  }
+
+inline int rsbac_adf_set_attr_reg(
+                      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)
+  {
+    int error = 0;
+    int suberror;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(   item_p->entry.set_attr_func
+        #ifdef CONFIG_RSBAC_SWITCH_REG
+           && item_p->entry.switch_on
+        #endif
+          )
+          {
+            suberror = item_p->entry.set_attr_func (request,
+                                                    caller_pid,
+                                                    target,
+                                                    tid,
+                                                    new_target,
+                                                    new_tid,
+                                                    attr,
+                                                    attr_val,
+                                                    owner);
+            if(suberror)
+              error = suberror;
+          }
+        item_p = item_p->next;
+      }
+    reg_read_unlock();
+    return error;
+  }
+
+
+#ifdef CONFIG_RSBAC_SECDEL
+inline rsbac_boolean_t rsbac_need_overwrite_reg(struct dentry * dentry_p)
+  {
+    rsbac_boolean_t need_overwrite = FALSE;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(   item_p->entry.need_overwrite_func
+        #ifdef CONFIG_RSBAC_SWITCH_REG
+           && item_p->entry.switch_on
+        #endif
+          )
+          if(!need_overwrite)
+            need_overwrite = item_p->entry.need_overwrite_func(dentry_p);
+        item_p=item_p->next;
+      }
+    reg_read_unlock();
+    return need_overwrite;
+  }
+#endif
+
+/* mounting and umounting */
+inline int rsbac_mount_reg(kdev_t kdev)
+  {
+    int error = 0;
+    int suberror;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(   item_p->entry.mount_func
+          )
+          {
+            suberror = item_p->entry.mount_func(kdev);
+            if(suberror < 0)
+              error = suberror;
+          }
+        item_p=item_p->next;
+      }
+    reg_read_unlock();
+    return error;
+  }
+
+inline int rsbac_umount_reg(kdev_t kdev)
+  {
+    int error = 0;
+    int suberror;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(   item_p->entry.umount_func
+          )
+          {
+            suberror = item_p->entry.umount_func(kdev);
+            if(suberror < 0)
+              error = suberror;
+          }
+        item_p=item_p->next;
+      }
+    reg_read_unlock();
+    return error;
+  }
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+inline int rsbac_write_reg(void)
+  {
+    int count = 0;
+    int subcount = 0;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(item_p->entry.write_func)
+          {
+            subcount = item_p->entry.write_func(FALSE);
+            if(subcount > 0)
+              {
+                count += subcount;
+              }
+            else
+            if(subcount < 0)
+              {
+                if(subcount != -RSBAC_ENOTWRITABLE)
+                  {
+                    rsbac_printk(KERN_WARNING
+                           "rsbac_write_reg(): write_func() for REG module %s returned error %i\n",
+                           item_p->entry.name, subcount);
+                  }
+              }
+          }
+        item_p=item_p->next;
+      }
+    reg_read_unlock();
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_write)
+      {
+        rsbac_printk(KERN_DEBUG "rsbac_write_reg(): %u lists written.\n",
+               count);
+      }
+#endif
+    return count;
+  }
+#endif /* CONFIG_RSBAC_AUTO_WRITE */
+
+/* Status checking */
+inline int rsbac_check_reg(int correct, int check_inode)
+  {
+    int error = 0;
+    int suberror;
+    struct rsbac_reg_list_item_t    * item_p;
+
+    reg_read_lock();
+    item_p=list_head.head;
+    while(item_p)
+      {
+        if(   item_p->entry.check_func
+          )
+          {
+            suberror = item_p->entry.check_func(correct, check_inode);
+            if(suberror < 0)
+              error = suberror;
+          }
+        item_p=item_p->next;
+      }
+    reg_read_unlock();
+    return error;
+  }
+
+
+/*
+ * Register an ADF decision module
+ * Returns given positive handle or negative error code
+ */
+
+EXPORT_SYMBOL(rsbac_reg_register);
+
+rsbac_reg_handle_t rsbac_reg_register(        rsbac_version_t    version,
+                                       struct rsbac_reg_entry_t  entry)
+  {
+    if(version != RSBAC_REG_VERSION)
+      return(-RSBAC_EINVALIDVERSION);
+
+    /* check entry */
+    if(   (   !entry.request_func
+           && !entry.set_attr_func
+           && !entry.need_overwrite_func
+           && !entry.write_func
+           && !entry.mount_func
+           && !entry.umount_func
+          )
+       || (entry.handle <= 0)
+      )
+      return -RSBAC_EINVALIDVALUE;
+
+    reg_write_lock();
+    if(lookup_item(entry.handle))
+      {
+        rsbac_printk(KERN_INFO "rsbac_reg_register: Handle in use, registering failed: %s.\n",
+               entry.name);
+        entry.handle = -RSBAC_EEXISTS;
+      }
+    else
+      {
+        if(!add_item(entry))
+          {
+            entry.name[RSBAC_REG_NAME_LEN] = 0;
+            rsbac_printk(KERN_INFO "rsbac_reg_register: registering failed for %s.\n",
+                   entry.name);
+            entry.handle = -RSBAC_ECOULDNOTADDITEM;
+          }
+#ifdef CONFIG_RSBAC_DEBUG
+        else
+          if(rsbac_debug_reg)
+            {
+              rsbac_printk(KERN_DEBUG "rsbac_reg_register: module %s registered.\n",
+                     entry.name);
+            }
+#endif
+      }
+    reg_write_unlock();
+    return entry.handle;
+  }
+
+/*
+ * Switch module on or off - for 'normal' modules this is done by general
+ * function. This is a dummy, if module switching is disabled.
+ */
+
+EXPORT_SYMBOL(rsbac_reg_switch);
+
+int rsbac_reg_switch (rsbac_reg_handle_t handle, rsbac_boolean_t value)
+  {
+#ifdef CONFIG_RSBAC_SWITCH_REG
+    struct rsbac_reg_list_item_t    * item_p;
+           int err=0;
+
+    if((value != FALSE) && (value != TRUE))
+      return -RSBAC_EINVALIDVALUE;
+    reg_read_lock();
+    item_p = lookup_item(handle);
+    if(item_p)
+      {
+        item_p->entry.switch_on = value;
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_reg)
+          {
+            rsbac_printk(KERN_DEBUG "rsbac_reg_switch: module %s switched to %i.\n",
+                   item_p->entry.name,
+                   value);
+          }
+#endif
+      }
+    else
+      err = -RSBAC_EINVALIDTARGET;
+    reg_read_unlock();
+    return err;
+#else
+    return(-RSBAC_EINVALIDTARGET);
+#endif
+  };
+
+/*
+ * Unregister an ADF decision module
+ * Returns 0 on success or negative error code. Be careful not to unregister
+ * modules you did not register yourself.
+ */
+
+EXPORT_SYMBOL(rsbac_reg_unregister);
+
+int rsbac_reg_unregister(rsbac_reg_handle_t handle)
+  {
+    int    err=0;
+
+    if(handle <= 0)
+      return -RSBAC_EINVALIDVALUE;
+
+    reg_write_lock();
+    if(lookup_item(handle))
+      {
+        remove_item(handle);
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_reg)
+          {
+            rsbac_printk(KERN_DEBUG "rsbac_reg_unregister: module unregistered.\n");
+          }
+#endif
+      }
+    else
+      {
+        err = -RSBAC_EINVALIDTARGET;
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_reg)
+          {
+            rsbac_printk(KERN_DEBUG "rsbac_reg_unregister: module unregistering failed.\n");
+          }
+#endif
+      }
+    reg_write_unlock();
+    return err;
+  }
+
+
+/*
+ * Register a system call
+ * Returns given positive handle or negative error code
+ */
+
+EXPORT_SYMBOL(rsbac_reg_register_syscall);
+
+rsbac_reg_handle_t rsbac_reg_register_syscall(       rsbac_version_t            version,
+                                              struct rsbac_reg_syscall_entry_t  entry)
+  {
+    if(version != RSBAC_REG_VERSION)
+      return(-RSBAC_EINVALIDVERSION);
+
+    /* check entry */
+    if(   !entry.syscall_func
+       || (entry.registration_handle <= 0)
+       || (entry.dispatcher_handle <= 0)
+      )
+      return -RSBAC_EINVALIDVALUE;
+
+    reg_sc_write_lock();
+    if(lookup_sc_item_reg(entry.registration_handle))
+      {
+        rsbac_printk(KERN_INFO "rsbac_reg_register_syscall: Registration handle in use, registering failed: %s.\n",
+               entry.name);
+        entry.registration_handle = -RSBAC_EEXISTS;
+      }
+    else
+    if(lookup_sc_item_dis(entry.dispatcher_handle))
+      {
+        rsbac_printk(KERN_INFO "rsbac_reg_register_syscall: Dispatcher handle in use, registering failed: %s.\n",
+               entry.name);
+        entry.registration_handle = -RSBAC_EEXISTS;
+      }
+    else
+      {
+        entry.name[RSBAC_REG_NAME_LEN] = 0;
+        if(!add_sc_item(entry))
+          {
+            rsbac_printk(KERN_INFO "rsbac_reg_register_syscall: registering failed for %s.\n",
+                   entry.name);
+            entry.registration_handle = -RSBAC_ECOULDNOTADDITEM;
+          }
+#ifdef CONFIG_RSBAC_DEBUG
+        else
+          if(rsbac_debug_reg)
+            {
+              rsbac_printk(KERN_DEBUG "rsbac_reg_register_syscall: syscall %s registered.\n",
+                     entry.name);
+            }
+#endif
+      }
+    reg_sc_write_unlock();
+    return entry.registration_handle;
+  }
+
+/*
+ * Unregister a system call
+ * Returns 0 on success or negative error code. Be careful not to unregister
+ * syscalls you did not register yourself.
+ */
+
+EXPORT_SYMBOL(rsbac_reg_unregister_syscall);
+
+int rsbac_reg_unregister_syscall(rsbac_reg_handle_t handle)
+  {
+    int    err=0;
+
+    if(handle <= 0)
+      return -RSBAC_EINVALIDVALUE;
+
+    reg_sc_write_lock();
+    if(lookup_sc_item_reg(handle))
+      {
+        remove_sc_item(handle);
+#ifdef CONFIG_RSBAC_DEBUG
+        if(rsbac_debug_reg)
+          {
+            rsbac_printk(KERN_DEBUG "rsbac_reg_unregister_syscall: syscall unregistered.\n");
+          }
+#endif
+      }
+    else
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        rsbac_printk(KERN_INFO "rsbac_reg_unregister_syscall: syscall unregistering failed for invalid handle!\n");
+      }
+    reg_sc_write_unlock();
+    return err;
+  }
+
+int rsbac_reg_syscall(rsbac_reg_handle_t handle,
+                      void __user * arg)
+  {
+    int err = 0;
+    struct rsbac_reg_sc_list_item_t    * item_p;
+
+    reg_sc_read_lock();
+    item_p=lookup_sc_item_dis(handle);
+    if(item_p && item_p->entry.syscall_func)
+      {
+        err = item_p->entry.syscall_func(arg);
+      }
+    else
+      {
+        err = -RSBAC_EINVALIDTARGET;
+      }
+    reg_sc_read_unlock();
+    return err;
+  }
+  
+/* end of rsbac/adf/reg/reg_main.c */
diff --git a/rsbac/adf/reg/reg_sample1.c b/rsbac/adf/reg/reg_sample1.c
new file mode 100644
index 0000000..e005603
--- /dev/null
+++ b/rsbac/adf/reg/reg_sample1.c
@@ -0,0 +1,254 @@
+/*
+ * RSBAC REG decision module sample 1
+ *
+ * Author and (c) 1999-2009 Amon Ott <ao@rsbac.org>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/getname.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+
+static u_long nr_request_calls = 0;
+static u_long nr_set_attr_calls = 0;
+static u_long nr_need_overwrite_calls = 0;
+static u_long nr_system_calls = 0;
+static void * system_call_arg = NULL;
+
+MODULE_AUTHOR("Amon Ott");
+MODULE_DESCRIPTION("RSBAC REG sample decision module 1");
+MODULE_LICENSE("GPL");
+
+static char * name = NULL;
+static char * syscall_name = NULL;
+static long handle = 123456;
+static long syscall_registration_handle = 654321;
+static long syscall_dispatcher_handle = 1;
+
+module_param(name, charp, 0000);
+MODULE_PARM_DESC(name, "Name");
+module_param(syscall_name, charp, 0000);
+MODULE_PARM_DESC(syscall_name, "Syscall name");
+module_param(handle, long, S_IRUSR);
+MODULE_PARM_DESC(handle, "Handle");
+module_param(syscall_registration_handle, long, S_IRUSR);
+MODULE_PARM_DESC(syscall_registration_handle, "Syscall registration handle");
+module_param(syscall_dispatcher_handle, long, S_IRUSR);
+MODULE_PARM_DESC(syscall_dispatcher_handle, "Syscall dispatcher");
+
+
+/* PROC functions */
+
+#if defined(CONFIG_RSBAC_PROC)
+#define PROC_NAME "reg_sample1"
+
+static struct proc_dir_entry * reg_sample_proc_p;
+
+static int
+reg_sample_proc_show(struct seq_file *m, void *v)
+{
+  union rsbac_target_id_t       rsbac_target_id;
+  union rsbac_attribute_value_t rsbac_attribute_value;
+
+  if (!rsbac_is_initialized())
+    return -ENOSYS;
+
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                         task_pid(current),
+                         T_SCD,
+                         rsbac_target_id,
+                         A_none,
+                         rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+  seq_puts(m, "RSBAC REG decision module sample 1\n----------------------------------\n");
+  seq_printf(m, "%lu calls to request function.\n",
+                 nr_request_calls);
+  seq_printf(m, "%lu calls to set_attr function.\n",
+                 nr_set_attr_calls);
+  seq_printf(m, "%lu calls to need_overwrite function.\n",
+                 nr_need_overwrite_calls);
+  seq_printf(m, "%lu calls to system_call function %lu, last arg was %p.\n",
+                 nr_system_calls,
+                 syscall_dispatcher_handle,
+                 system_call_arg);
+  return 0;
+}
+
+static int reg_sample_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, reg_sample_proc_show, NULL);
+}
+
+static const struct file_operations reg_sample_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = reg_sample_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+#endif /* CONFIG_RSBAC_PROC */
+
+/**** Decision Functions ****/
+
+static  int request_func  ( enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             owner_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)
+  {
+    /* count call, but not for SEARCH request */
+    if(request != R_SEARCH)
+      nr_request_calls++;
+    return GRANTED;
+  }
+
+static  int set_attr_func ( enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             owner_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)
+  {
+    /* count call, but not for SEARCH request */
+    if(request != R_SEARCH)
+      nr_set_attr_calls++;
+    return 0;
+  }
+
+static rsbac_boolean_t need_overwrite_func (struct dentry * dentry_p)
+  {
+    nr_need_overwrite_calls++;
+    return FALSE;
+  }
+
+static int syscall_func (void * arg)
+  {
+    nr_system_calls++;
+    system_call_arg = arg;
+    return nr_system_calls;
+  }
+
+/**** Init ****/
+
+int init_module(void)
+{
+  struct rsbac_reg_entry_t entry;
+  struct rsbac_reg_syscall_entry_t syscall_entry;
+
+  if(!handle)
+    handle = 123456;
+  if(!syscall_registration_handle)
+    syscall_registration_handle = 654321;
+  if(!syscall_dispatcher_handle)
+    syscall_dispatcher_handle = 1;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: Initializing.\n");
+
+  /* clearing registration entries */
+  memset(&entry, 0, sizeof(entry));
+  memset(&syscall_entry, 0, sizeof(syscall_entry));
+
+  if(name)
+    {
+      strncpy(entry.name, name, RSBAC_REG_NAME_LEN);
+      entry.name[RSBAC_REG_NAME_LEN] = 0;
+    }
+  else
+    strcpy(entry.name, "RSBAC REG sample 1 ADF module");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: REG Version: %u, Name: %s, Handle: %li\n",
+         RSBAC_REG_VERSION, entry.name, handle);
+
+  entry.handle = handle;
+  entry.request_func = request_func;
+  entry.set_attr_func = set_attr_func;
+  entry.need_overwrite_func = need_overwrite_func;
+  entry.switch_on = TRUE;
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: Registering to ADF.\n");
+  if(rsbac_reg_register(RSBAC_REG_VERSION, entry) < 0)
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 1: Registering failed. Unloading.\n");
+      return -ENOEXEC;
+    }
+
+  if(syscall_name)
+    {
+      strncpy(syscall_entry.name, syscall_name, RSBAC_REG_NAME_LEN);
+      syscall_entry.name[RSBAC_REG_NAME_LEN] = 0;
+    }
+  else
+    strcpy(syscall_entry.name, "RSBAC REG sample 1 syscall");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: REG Version: %u, Name: %s, Dispatcher Handle: %li\n",
+         RSBAC_REG_VERSION, syscall_entry.name, syscall_dispatcher_handle);
+
+  syscall_entry.registration_handle = syscall_registration_handle;
+  syscall_entry.dispatcher_handle = syscall_dispatcher_handle;
+  syscall_entry.syscall_func = syscall_func;
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: Registering syscall.\n");
+  syscall_registration_handle = rsbac_reg_register_syscall(RSBAC_REG_VERSION, syscall_entry);
+  if(syscall_registration_handle < 0)
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 1: Registering syscall failed. Unloading.\n");
+      if(rsbac_reg_unregister(handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 1: Unregistering failed - beware of possible system failure!\n");
+        }
+      return -ENOEXEC;
+    }
+
+  #if defined(CONFIG_RSBAC_PROC)
+  reg_sample_proc_p = proc_create(PROC_NAME,  S_IFREG | S_IRUGO, proc_rsbac_root_p, &reg_sample_proc_fops);
+  if(!reg_sample_proc_p)
+    {
+      rsbac_printk(KERN_WARNING "%s: Not loaded due to failed proc entry registering.\n", name);
+      if(rsbac_reg_unregister(handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 1: Unregistering failed - beware of possible system failure!\n");
+        }
+      if(rsbac_reg_unregister_syscall(syscall_registration_handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 1: Unregistering syscall failed - beware of possible system failure!\n");
+        }
+      return -ENOEXEC;
+    }
+  #endif 
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: Loaded.\n");
+
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: Unregistering.\n");
+  #if defined(CONFIG_RSBAC_PROC)
+  remove_proc_entry(PROC_NAME, proc_rsbac_root_p);
+  #endif 
+  if(rsbac_reg_unregister_syscall(syscall_registration_handle))
+    {
+      rsbac_printk(KERN_ERR "RSBAC REG decision module sample 1: Unregistering syscall failed - beware of possible system failure!\n");
+    }
+  if(rsbac_reg_unregister(handle))
+    {
+      rsbac_printk(KERN_ERR "RSBAC REG decision module sample 1: Unregistering failed - beware of possible system failure!\n");
+    }
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 1: Unloaded.\n");
+}
diff --git a/rsbac/adf/reg/reg_sample2.c b/rsbac/adf/reg/reg_sample2.c
new file mode 100644
index 0000000..c350e70
--- /dev/null
+++ b/rsbac/adf/reg/reg_sample2.c
@@ -0,0 +1,548 @@
+/*
+ * RSBAC REG decision module sample2
+ * (not working any more, kept for reference)
+ *
+ * Author and (c) 1999-2015 Amon Ott <ao@rsbac.org>
+ */
+
+/* general stuff */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+/* for file access */
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+/* rsbac */
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/getname.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+
+static u_long nr_request_calls = 0;
+static u_long nr_set_attr_calls = 0;
+static u_long nr_need_overwrite_calls = 0;
+static rsbac_boolean_t no_write = FALSE;
+static u_long nr_system_calls = 0;
+static void * system_call_arg = 0;
+
+MODULE_AUTHOR("Amon Ott");
+MODULE_DESCRIPTION("RSBAC REG sample decision module 2");
+
+MODULE_PARM(name, "s");
+static char * name = NULL;
+static char dummy_buf[70]="To protect against wrong insmod params";
+
+MODULE_PARM(syscall_name, "s");
+static char * syscall_name = NULL;
+static char dummy_buf2[70]="To protect against wrong insmod params";
+
+MODULE_PARM(handle, "l");
+static long handle = 123457;
+
+MODULE_PARM(syscall_registration_handle, "l");
+static long syscall_registration_handle = 754321;
+MODULE_PARM(syscall_dispatcher_handle, "l");
+static long syscall_dispatcher_handle = 2;
+
+/* Filename for persistent data in /rsbac dir of ROOT_DEV (max 7 chars) */
+#define FILENAME "regsmp2"
+
+/* Version number for on disk data structures */
+#define FILE_VERSION 1
+
+/* PROC functions */
+
+#if defined(CONFIG_RSBAC_PROC)
+#define PROC_NAME "reg_sample2"
+static struct proc_dir_entry * proc_reg_sample_p;
+
+static int
+adf_sample_proc_info(char *buffer, char **start, off_t offset, int length)
+{
+  int len = 0;
+  off_t pos   = 0;
+  off_t begin = 0;
+
+  union rsbac_target_id_t       rsbac_target_id;
+  union rsbac_attribute_value_t rsbac_attribute_value;
+
+  if (!rsbac_is_initialized())
+    return (-ENOSYS);
+
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                         task_pid(current),
+                         T_SCD,
+                         rsbac_target_id,
+                         A_none,
+                         rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+  len += sprintf(buffer, "RSBAC REG decision module sample 2\n----------------------------------\n");
+  pos = begin + len;
+  if (pos < offset)
+    {
+      len = 0;
+      begin = pos;
+    }
+  if (pos > offset+length)
+    goto out;
+
+  len += sprintf(buffer + len, "%lu calls to request function.\n",
+                 nr_request_calls);
+  pos = begin + len;
+  if (pos < offset)
+    {
+      len = 0;
+      begin = pos;
+    }
+  if (pos > offset+length)
+    goto out;
+
+  len += sprintf(buffer + len, "%lu calls to set_attr function.\n",
+                 nr_set_attr_calls);
+  pos = begin + len;
+  if (pos < offset)
+    {
+      len = 0;
+      begin = pos;
+    }
+  if (pos > offset+length)
+    goto out;
+
+  len += sprintf(buffer + len, "%lu calls to need_overwrite function.\n",
+                 nr_need_overwrite_calls);
+  pos = begin + len;
+  if (pos < offset)
+    {
+      len = 0;
+      begin = pos;
+    }
+  if (pos > offset+length)
+    goto out;
+
+  len += sprintf(buffer + len, "%lu calls to system_call function %lu, last arg was %p.\n",
+                 nr_system_calls,
+                 syscall_dispatcher_handle,
+                 system_call_arg);
+  pos = begin + len;
+  if (pos < offset)
+    {
+      len = 0;
+      begin = pos;
+    }
+  if (pos > offset+length)
+    goto out;
+
+out:
+  *start = buffer + (offset - begin);
+  len -= (offset - begin);
+  
+  if (len > length)
+    len = length;
+  return len;
+}
+#endif /* CONFIG_RSBAC_PROC */
+
+
+/**** Read/Write Functions ****/
+
+/* read_info() */
+/* reading the system wide adf_sample2 data */
+
+static int read_info(void)
+  {
+    struct file                     file;
+    char                            name[RSBAC_MAXNAMELEN];
+    int                             err = 0;
+    int                             tmperr;
+    mm_segment_t                    oldfs;
+    u_int                           version;
+    u_long                          tmpval;
+
+    /* copy name from base name */
+    strcpy(name, FILENAME);
+
+    /* open file */
+    if ((err = rsbac_read_open(name,
+                               &file,
+                               rsbac_root_dev) ))
+      return(err);
+
+    /* OK, now we can start reading */
+
+    /* There is a read function for this file, so read data from
+     * previous module load.
+     * A positive read return value means a read success,
+     * 0 end of file and a negative value an error.
+     */
+
+    /* Set current user space to kernel space, because read() writes */
+    /* to user space */
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+
+    tmperr = __vfs_read(&file,
+                        (char *) &version,
+                        sizeof(version),
+                        &file.f_pos);
+    /* error? */
+    if (tmperr < sizeof(version))
+      {
+        rsbac_printk(KERN_WARNING
+               "read_info(): read error from file!\n");
+        err = -RSBAC_EREADFAILED;
+        goto end_read;
+      }
+    /* if wrong version, warn and skip */
+    if (version != FILE_VERSION)
+      {
+        rsbac_printk(KERN_WARNING
+               "read_info(): wrong version %u, expected %u - skipping file and setting no_write!\n",
+               version, FILE_VERSION);
+        no_write = TRUE;
+        err = -RSBAC_EREADFAILED;
+        goto end_read;
+      }
+
+    /* read nr_request_calls */
+    tmperr = __vfs_read(&file,
+                        (char *) &tmpval,
+                        sizeof(tmpval),
+                        &file.f_pos);
+    if (tmperr < sizeof(tmpval))
+      {
+        rsbac_printk(KERN_WARNING "%s\n",
+               "read_info(): read error from file!");
+        err = -RSBAC_EREADFAILED;
+        goto end_read;
+      }
+    nr_request_calls = tmpval;
+
+    /* read nr_set_attr_calls */
+    tmperr = __vfs_read(&file,
+                        (char *) &tmpval,
+                        sizeof(tmpval),
+                        &file.f_pos);
+    if (tmperr < sizeof(tmpval))
+      {
+        rsbac_printk(KERN_WARNING "%s\n",
+               "read_info(): read error from file!");
+        err = -RSBAC_EREADFAILED;
+        goto end_read;
+      }
+    nr_set_attr_calls = tmpval;
+
+    /* read nr_need_overwrite_calls */
+    tmperr = __vfs_read(&file,
+                        (char *) &tmpval,
+                        sizeof(tmpval),
+                        &file.f_pos);
+    if (tmperr < sizeof(tmpval))
+      {
+        rsbac_printk(KERN_WARNING "%s\n",
+               "read_info(): read error from file!");
+        err = -RSBAC_EREADFAILED;
+        goto end_read;
+      }
+    nr_need_overwrite_calls = tmpval;
+
+end_read:
+    /* Set current user space back to user space, because read() writes */
+    /* to user space */
+    set_fs(oldfs);
+
+    /* We do not need this file dentry any more */
+    rsbac_read_close(&file);
+
+    /* ready */
+    return(err);
+  }; /* end of read_info() */
+
+static int write_info(void)
+  {
+    struct file                     file;
+    char                            name[RSBAC_MAXNAMELEN];
+    int                             err = 0;
+    int                             tmperr;
+    mm_segment_t                    oldfs;
+    u_int                           version = FILE_VERSION;
+    
+    /* copy name from base name */
+    strcpy(name, FILENAME);
+
+    /* get rsbac write-to-disk semaphore */
+    down(&rsbac_write_sem);
+
+    /* open file */
+    if ((err = rsbac_write_open(name,
+                                &file,
+                                rsbac_root_dev) ))
+      {
+        up(&rsbac_write_sem);
+        return(err);
+      }
+
+    /* OK, now we can start writing all sample items.
+     * A positive return value means a write success,
+     * 0 end of file and a negative value an error.
+     */
+
+    /* Set current user space to kernel space, because write() reads
+     * from user space */
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+
+    tmperr = __vfs_write(&file,
+                         (char *) &version,
+                         sizeof(version),
+                         &file.f_pos);
+    if (tmperr < sizeof(version))
+      {
+        rsbac_printk(KERN_WARNING
+               "write_info(): write error %i on file!\n",
+               tmperr);
+        err = -RSBAC_EWRITEFAILED;
+        goto end_write;
+      }
+
+    tmperr = __vfs_write(&file,
+                         (char *) &nr_request_calls,
+                         sizeof(nr_request_calls),
+                         &file.f_pos);
+    if (tmperr < sizeof(nr_request_calls))
+      {
+        rsbac_printk(KERN_WARNING
+               "write_info(): write error %i on file!\n",
+               tmperr);
+        err = -RSBAC_EWRITEFAILED;
+        goto end_write;
+      }
+
+    tmperr = __vfs_write(&file,
+                         (char *) &nr_set_attr_calls,
+                         sizeof(nr_set_attr_calls),
+                         &file.f_pos);
+    if (tmperr < sizeof(nr_set_attr_calls))
+      {
+        rsbac_printk(KERN_WARNING
+               "write_info(): write error %i on file!\n",
+               tmperr);
+        err = -RSBAC_EWRITEFAILED;
+        goto end_write;
+      }
+
+    tmperr = __vfs_write(&file,
+                         (char *) &nr_need_overwrite_calls,
+                         sizeof(nr_need_overwrite_calls),
+                         &file.f_pos);
+    if (tmperr < sizeof(nr_need_overwrite_calls))
+      {
+        rsbac_printk(KERN_WARNING
+               "write_info(): write error %i on file!\n",
+               tmperr);
+        err = -RSBAC_EWRITEFAILED;
+        goto end_write;
+      }
+
+end_write:
+    /* Set current user space back to user space, because write() reads */
+    /* from user space */
+    set_fs(oldfs);
+
+    /* End of write access */
+    rsbac_write_close(&file);
+    up(&rsbac_write_sem);
+    return(err);
+  }; /* end of write_info() */
+
+
+/**** Decision Functions ****/
+
+static  int request_func  ( enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             owner_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)
+  {
+    /* count call, but not for SEARCH request */
+    if(request != R_SEARCH)
+      nr_request_calls++;
+    return GRANTED;
+  }
+
+static  int set_attr_func ( enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             owner_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)
+  {
+    /* count call, but not for SEARCH request */
+    if(request != R_SEARCH)
+      nr_set_attr_calls++;
+    return 0;
+  }
+
+static rsbac_boolean_t need_overwrite_func (struct dentry * dentry_p)
+  {
+    nr_need_overwrite_calls++;
+    return FALSE;
+  }
+
+static int write_func(rsbac_boolean_t need_lock)
+  {
+    int res=0;
+
+    if(!write_info())
+      res = 1;
+
+    return(res);
+  }
+
+static int syscall_func (void * arg)
+  {
+    nr_system_calls++;
+    system_call_arg = arg;
+    return nr_system_calls;
+   }
+
+/**** Init ****/
+
+int init_module(void)
+{
+  struct rsbac_reg_entry_t entry;
+  struct rsbac_reg_syscall_entry_t syscall_entry;
+
+  if(!handle)
+    handle = 123457;
+  if(!syscall_registration_handle)
+    syscall_registration_handle = 754321;
+  if(!syscall_dispatcher_handle)
+    syscall_dispatcher_handle = 2;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: Initializing.\n");
+
+  /* clearing registration entries */
+  memset(&entry, 0, sizeof(entry));
+  memset(&syscall_entry, 0, sizeof(syscall_entry));
+
+  if((dummy_buf[0] != 'T') || (dummy_buf2[0] != 'T'))
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 2: Not loaded due to invalid param string.\n");
+      return -ENOEXEC;
+    }
+  if(name)
+    {
+      strncpy(entry.name, name, RSBAC_REG_NAME_LEN);
+      entry.name[RSBAC_REG_NAME_LEN] = 0;
+    }
+  else
+    strcpy(entry.name, "RSBAC REG sample 2 ADF module");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: REG Version: %u, Name: %s, Handle: %li\n",
+         RSBAC_REG_VERSION, entry.name, handle);
+
+  entry.handle = handle;
+  entry.request_func = request_func;
+  entry.set_attr_func = set_attr_func;
+  entry.need_overwrite_func = need_overwrite_func;
+  entry.write_func = write_func;
+  entry.switch_on = TRUE;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: Registering to ADF.\n");
+  if(rsbac_reg_register(RSBAC_REG_VERSION, entry) < 0)
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 2: Registering failed. Unloading.\n");
+      return -ENOEXEC;
+    }
+
+  if(syscall_name)
+    {
+      strncpy(syscall_entry.name, syscall_name, RSBAC_REG_NAME_LEN);
+      syscall_entry.name[RSBAC_REG_NAME_LEN] = 0;
+    }
+  else
+    strcpy(syscall_entry.name, "RSBAC REG sample 2 syscall");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: REG Version: %u, Name: %s, Dispatcher Handle: %li\n",
+         RSBAC_REG_VERSION, syscall_entry.name, syscall_dispatcher_handle);
+
+  syscall_entry.registration_handle = syscall_registration_handle;
+  syscall_entry.dispatcher_handle = syscall_dispatcher_handle;
+  syscall_entry.syscall_func = syscall_func;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: Registering syscall.\n");
+  syscall_registration_handle = rsbac_reg_register_syscall(RSBAC_REG_VERSION, syscall_entry);
+  if(syscall_registration_handle < 0)
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 2: Registering syscall failed. Unloading.\n");
+      if(rsbac_reg_unregister(handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 2: Unregistering failed - beware of possible system failure!\n");
+        }
+      return -ENOEXEC;
+    }
+
+  if(read_info())
+    {
+      rsbac_printk(KERN_WARNING
+             "RSBAC REG decision module sample 2: Could not read info from previous session.\n");
+    }
+  
+  #if defined(CONFIG_RSBAC_PROC)
+  proc_reg_sample_p = create_proc_entry(PROC_NAME,
+                                        S_IFREG | S_IRUGO,
+                                        proc_rsbac_root_p);
+  if(!proc_reg_sample_p)
+    {
+      rsbac_printk(KERN_WARNING "%s: Not loaded due to failed proc entry registering.\n", name);
+      if(rsbac_reg_unregister_syscall(syscall_registration_handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 2: Unregistering syscall failed - beware of possible system failure!\n");
+        }
+      if(rsbac_reg_unregister(handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 2: Unregistering from ADF failed - beware of possible system failure!\n");
+        }
+      return -ENOEXEC;
+    }
+  proc_reg_sample_p->get_info = adf_sample_proc_info;
+  #endif 
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: Loaded.\n");
+
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: Unregistering.\n");
+  #if defined(CONFIG_RSBAC_PROC)
+  remove_proc_entry(PROC_NAME, proc_rsbac_root_p);
+  #endif 
+  if(write_info())
+    {
+      rsbac_printk(KERN_WARNING
+             "RSBAC REG decision module sample 2: Could not save info for next session.\n");
+    }
+  if(rsbac_reg_unregister_syscall(syscall_registration_handle))
+    {
+      rsbac_printk(KERN_ERR "RSBAC REG decision module sample 2: Unregistering syscall failed - beware of possible system failure!\n");
+    }
+  if(rsbac_reg_unregister(handle))
+    {
+      rsbac_printk(KERN_ERR "RSBAC REG decision module sample 2: Unregistering module failed - beware of possible system failure!\n");
+    }
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 2: Unloaded.\n");
+}
diff --git a/rsbac/adf/reg/reg_sample3.c b/rsbac/adf/reg/reg_sample3.c
new file mode 100644
index 0000000..2fef23d
--- /dev/null
+++ b/rsbac/adf/reg/reg_sample3.c
@@ -0,0 +1,369 @@
+/*
+ * RSBAC REG decision module sample
+ *
+ * Author and (c) 1999-2009 Amon Ott <ao@rsbac.org>
+ */
+
+/* general stuff */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+/* for file access */
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+/* rsbac */
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/lists.h>
+#include <rsbac/getname.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+
+static u_long nr_request_calls = 0;
+#define ORD_request 1
+static u_long nr_set_attr_calls = 0;
+#define ORD_set_attr 2
+static u_long nr_need_overwrite_calls = 0;
+#define ORD_overwrite 3
+static u_long nr_write_calls = 0;
+#define ORD_write 4
+static u_long nr_system_calls = 0;
+#define ORD_syscall 5
+static void * system_call_arg = 0;
+
+MODULE_AUTHOR("Amon Ott");
+MODULE_DESCRIPTION("RSBAC REG sample decision module 3");
+MODULE_LICENSE("GPL");
+
+static char * name = NULL;
+static char * syscall_name = NULL;
+static u_int listkey = 133457;
+static long handle = 133457;
+static long syscall_registration_handle = 754331;
+static long syscall_dispatcher_handle = 3;
+
+module_param(name, charp, 0000);
+MODULE_PARM_DESC(name, "Name");
+module_param(syscall_name, charp, 0000);
+MODULE_PARM_DESC(syscall_name, "Syscall name");
+module_param(listkey, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(listkey, "List key");
+module_param(handle, long, S_IRUSR);
+MODULE_PARM_DESC(handle, "Handle");
+module_param(syscall_registration_handle, long, S_IRUSR);
+MODULE_PARM_DESC(syscall_registration_handle, "Syscall registration handle");
+module_param(syscall_dispatcher_handle, long, S_IRUSR);
+MODULE_PARM_DESC(syscall_dispatcher_handle, "Syscall dispatcher handle");
+
+/* Filename for persistent data in /rsbac dir of ROOT_DEV (max 7 chars) */
+#define FILENAME "regsmp3"
+
+/* Version number for on disk data structures */
+#define LIST_VERSION 1
+
+static rsbac_list_handle_t list_handle;
+
+/* PROC functions */
+
+#if defined(CONFIG_RSBAC_PROC)
+#define PROC_NAME "reg_sample3"
+static struct proc_dir_entry * reg_sample_proc_p;
+
+static int
+reg_sample_proc_show(struct seq_file *m, void *v)
+{
+  union rsbac_target_id_t       rsbac_target_id;
+  union rsbac_attribute_value_t rsbac_attribute_value;
+
+  if (!rsbac_is_initialized())
+    return -ENOSYS;
+
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                         task_pid(current),
+                         T_SCD,
+                         rsbac_target_id,
+                         A_none,
+                         rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+  seq_puts(m, "RSBAC REG decision module sample 3\n----------------------------------\n");
+  seq_printf(m, "%lu calls to request function.\n",
+                 nr_request_calls);
+  seq_printf(m, "%lu calls to set_attr function.\n",
+                 nr_set_attr_calls);
+  seq_printf(m, "%lu calls to need_overwrite function.\n",
+                 nr_need_overwrite_calls);
+  seq_printf(m, "%lu calls to write function.\n",
+                 nr_write_calls);
+  seq_printf(m, "%lu calls to system_call function %lu, last arg was %p.\n",
+                 nr_system_calls,
+                 syscall_dispatcher_handle,
+                 system_call_arg);
+  seq_printf(m, "%li list items.\n",
+                 rsbac_list_count(list_handle));
+  return 0;
+}
+
+static int reg_sample_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, reg_sample_proc_show, NULL);
+}
+
+static const struct file_operations reg_sample_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = reg_sample_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+#endif /* CONFIG_RSBAC_PROC */
+
+/**** List helper functions ****/
+
+static int compare(void * desc1, void * desc2)
+  {
+    return memcmp((u_int *) desc1, (u_int *) desc2, sizeof(u_int) );
+  }
+
+/*
+static rsbac_list_conv_function_t * get_conv(rsbac_version_t version)
+  {
+    return compare;
+  }
+*/
+
+/**** Decision Functions ****/
+
+static  int request_func  ( enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             owner_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)
+  {
+    /* count call, but not for SEARCH request */
+    if(request != R_SEARCH)
+      {
+        __u32 ord = ORD_request;
+
+        nr_request_calls++;
+        rsbac_list_add(list_handle, &ord, &nr_request_calls);
+      }
+    return GRANTED;
+  }
+
+static  int set_attr_func ( enum  rsbac_adf_request_t     request,
+                                  rsbac_pid_t             owner_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)
+  {
+    __u32 ord = ORD_set_attr;
+
+    /* count call, but not for SEARCH request */
+    if(request != R_SEARCH)
+      {
+        nr_set_attr_calls++;
+        rsbac_list_add(list_handle, &ord, &nr_set_attr_calls);
+      }
+    return 0;
+  }
+
+static rsbac_boolean_t need_overwrite_func (struct dentry * dentry_p)
+  {
+    __u32 ord = ORD_overwrite;
+
+    nr_need_overwrite_calls++;
+    rsbac_list_add(list_handle, &ord, &nr_need_overwrite_calls);
+    return FALSE;
+  }
+
+static int write_func(rsbac_boolean_t need_lock)
+  {
+    __u32 ord = ORD_write;
+
+    nr_write_calls++;
+    rsbac_list_add(list_handle, &ord, &nr_write_calls);
+    return(0);
+  }
+
+static int syscall_func (void * arg)
+  {
+    __u32 ord = ORD_syscall;
+
+    nr_system_calls++;
+    system_call_arg = arg;
+    rsbac_list_add(list_handle, &ord, &nr_system_calls);
+    return nr_system_calls;
+   }
+
+/**** Init ****/
+
+int init_module(void)
+{
+  struct rsbac_reg_entry_t entry;
+  struct rsbac_reg_syscall_entry_t syscall_entry;
+  struct rsbac_list_info_t list_info;
+  __u32 ord;
+
+  if(!listkey)
+    listkey = 133457;
+  if(!handle)
+    handle = 133457;
+  if(!syscall_registration_handle)
+    syscall_registration_handle = 754331;
+  if(!syscall_dispatcher_handle)
+    syscall_dispatcher_handle = 3;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: Initializing.\n");
+
+  /* clearing registration entries */
+  memset(&entry, 0, sizeof(entry));
+  memset(&syscall_entry, 0, sizeof(syscall_entry));
+  /* Register a generic list */
+  list_info.version = LIST_VERSION;
+  list_info.key = listkey;
+  list_info.desc_size = sizeof(__u32);
+  list_info.data_size = sizeof(nr_request_calls);
+  list_info.max_age = 3600; /* 1h */
+  if(rsbac_list_register(RSBAC_LIST_VERSION,
+                         &list_handle,
+                         &list_info,
+                         RSBAC_LIST_PERSIST | RSBAC_LIST_BACKUP,
+                         compare,
+                         NULL,
+                         NULL,
+                         FILENAME,
+                         0))
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Registering list failed. Unloading.\n");
+      return -ENOEXEC;
+    }
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: List Version: %u, Name: %s, Handle: %p, Key: %u\n",
+         RSBAC_LIST_VERSION, FILENAME, list_handle, listkey);
+  ord = ORD_request;
+  if(rsbac_list_exist(list_handle, &ord))
+    rsbac_list_get_data(list_handle, &ord, &nr_request_calls);
+  ord = ORD_set_attr;
+  if(rsbac_list_exist(list_handle, &ord))
+    rsbac_list_get_data(list_handle, &ord, &nr_set_attr_calls);
+  ord = ORD_overwrite;
+  if(rsbac_list_exist(list_handle, &ord))
+    rsbac_list_get_data(list_handle, &ord, &nr_need_overwrite_calls);
+  ord = ORD_write;
+  if(rsbac_list_exist(list_handle, &ord))
+    rsbac_list_get_data(list_handle, &ord, &nr_write_calls);
+  ord = ORD_syscall;
+  if(rsbac_list_exist(list_handle, &ord))
+    rsbac_list_get_data(list_handle, &ord, &nr_system_calls);
+
+  /* Register to ADF */
+  if(name)
+    {
+      strncpy(entry.name, name, RSBAC_REG_NAME_LEN);
+      entry.name[RSBAC_REG_NAME_LEN] = 0;
+    }
+  else
+    strcpy(entry.name, "RSBAC REG sample 3 ADF module");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: REG Version: %u, Name: %s, Handle: %li\n",
+         RSBAC_REG_VERSION, entry.name, handle);
+
+  entry.handle = handle;
+  entry.request_func = request_func;
+  entry.set_attr_func = set_attr_func;
+  entry.need_overwrite_func = need_overwrite_func;
+  entry.write_func = write_func;
+  entry.switch_on = TRUE;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: Registering to ADF.\n");
+  if(rsbac_reg_register(RSBAC_REG_VERSION, entry) < 0)
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Registering failed. Unloading.\n");
+      if(rsbac_list_detach(&list_handle, listkey))
+        rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Unregistering list failed - beware!\n");
+      return -ENOEXEC;
+    }
+
+  if(syscall_name)
+    {
+      strncpy(syscall_entry.name, syscall_name, RSBAC_REG_NAME_LEN);
+      syscall_entry.name[RSBAC_REG_NAME_LEN] = 0;
+    }
+  else
+    strcpy(syscall_entry.name, "RSBAC REG sample 3 syscall");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: REG Version: %u, Name: %s, Dispatcher Handle: %li\n",
+         RSBAC_REG_VERSION, syscall_entry.name, syscall_dispatcher_handle);
+
+  syscall_entry.registration_handle = syscall_registration_handle;
+  syscall_entry.dispatcher_handle = syscall_dispatcher_handle;
+  syscall_entry.syscall_func = syscall_func;
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: Registering syscall.\n");
+  syscall_registration_handle = rsbac_reg_register_syscall(RSBAC_REG_VERSION, syscall_entry);
+  if(syscall_registration_handle < 0)
+    {
+      rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Registering syscall failed. Unloading.\n");
+      if(rsbac_reg_unregister(handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 3: Unregistering failed - beware of possible system failure!\n");
+        }
+      if(rsbac_list_detach(&list_handle, listkey))
+        rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Unregistering list failed - beware!\n");
+      return -ENOEXEC;
+    }
+
+  #if defined(CONFIG_RSBAC_PROC)
+  reg_sample_proc_p = proc_create(PROC_NAME, S_IFREG | S_IRUGO, proc_rsbac_root_p, &reg_sample_proc_fops);
+  if(!reg_sample_proc_p)
+    {
+      rsbac_printk(KERN_WARNING "%s: Not loaded due to failed proc entry registering.\n", name);
+      if(rsbac_reg_unregister_syscall(syscall_registration_handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 3: Unregistering syscall failed - beware of possible system failure!\n");
+        }
+      if(rsbac_reg_unregister(handle))
+        {
+          rsbac_printk(KERN_ERR "RSBAC REG decision module sample 3: Unregistering from ADF failed - beware of possible system failure!\n");
+        }
+      if(rsbac_list_detach(&list_handle, listkey))
+        rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Unregistering list failed - beware!\n");
+      return -ENOEXEC;
+    }
+  #endif 
+
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: Loaded.\n");
+
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: Unregistering.\n");
+  #if defined(CONFIG_RSBAC_PROC)
+  remove_proc_entry(PROC_NAME, proc_rsbac_root_p);
+  #endif 
+  if(rsbac_reg_unregister_syscall(syscall_registration_handle))
+    {
+      rsbac_printk(KERN_ERR "RSBAC REG decision module sample 3: Unregistering syscall failed - beware of possible system failure!\n");
+    }
+  if(rsbac_reg_unregister(handle))
+    {
+      rsbac_printk(KERN_ERR "RSBAC REG decision module sample 3: Unregistering module failed - beware of possible system failure!\n");
+    }
+  if(rsbac_list_detach(&list_handle, listkey))
+    rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 3: Unregistering list failed - beware!\n");
+  rsbac_printk(KERN_INFO "RSBAC REG decision module sample 3: Unloaded.\n");
+}
diff --git a/rsbac/adf/reg/root_plug.c b/rsbac/adf/reg/root_plug.c
new file mode 100644
index 0000000..4679d5f
--- /dev/null
+++ b/rsbac/adf/reg/root_plug.c
@@ -0,0 +1,138 @@
+/*
+ * RSBAC REG decision module kproc_hide.
+ *
+ * Originally written for a Linux Journal as LSM sample module.
+ * Rewriten for RSBAC by Michal Purzynski <albeiro@rsbac.org>
+ *
+ * Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ * Prevents any programs running with egid == 0 if a specific USB device
+ * is not present in the system.  Yes, it can be gotten around, but is a
+ * nice starting point for people to play with, and learn the LSM interface.
+ *
+ * See http://www.linuxjournal.com/article.php?sid=6279 for more information about this code.
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <rsbac/types.h>
+#include <rsbac/reg.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/getname.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+#include <linux/usb.h>
+#include <linux/moduleparam.h>
+
+MODULE_AUTHOR("Michal Purzynski");
+MODULE_DESCRIPTION("RSBAC REG root_plug decision module");
+MODULE_LICENSE("GPL");
+
+#ifdef CONFIG_USB
+/* default is a generic type of usb to serial converter */
+static int vendor_id = 0x0557;
+static int product_id = 0x2008;
+
+module_param(vendor_id, uint, 0400);
+module_param(product_id, uint, 0400);
+#endif
+
+static long handle = 999999;
+
+/**** Decision Functions ****/
+
+static int request_func (enum  rsbac_adf_request_t	request,
+			rsbac_pid_t			owner_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)
+{
+	struct usb_device *dev = NULL;
+#ifdef CONFIG_USB 
+	dev = usb_find_device(vendor_id, product_id);
+#endif
+
+	if (!dev) {
+
+		switch (request) {
+			case R_CHANGE_OWNER:
+			case R_CHANGE_GROUP:
+			case R_CLONE:
+				switch (target) {
+					case T_PROCESS:
+						switch (attr) {
+							case A_owner:
+								switch (attr_val.owner) {
+									case 0:
+										return NOT_GRANTED;
+									default:
+										return DO_NOT_CARE;
+								}
+							default:
+								return DO_NOT_CARE;
+						}
+					default:
+						return DO_NOT_CARE;
+				}
+			default:
+				return DO_NOT_CARE;
+		}
+	}
+	
+	return DO_NOT_CARE;
+}
+
+/**** Init ****/
+
+int init_module(void)
+{
+	struct rsbac_reg_entry_t entry;
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module root_plug: Initializing.\n");
+
+	/* clearing registration entries */
+	memset(&entry, 0, sizeof(entry));
+
+	strcpy(entry.name, "RSBAC REG root_plug ADF module");
+	rsbac_printk(KERN_INFO "RSBAC REG decision module root_plug: REG Version: %u, Name: %s, Handle: %li\n",
+			RSBAC_REG_VERSION, entry.name, handle);
+
+	entry.handle = handle;
+	entry.request_func = request_func;
+	entry.switch_on = TRUE;
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module root_plug: Registering to ADF.\n");
+
+	if(rsbac_reg_register(RSBAC_REG_VERSION, entry) < 0) {
+		rsbac_printk(KERN_WARNING "RSBAC REG decision module sample 1: Registering failed. Unloading.\n");
+		return -ENOEXEC;
+	}
+
+	rsbac_printk(KERN_INFO "RSBAC REG decision module root_plug: Loaded.\n");
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	rsbac_printk(KERN_INFO "RSBAC REG decision module root_plug: Unregistering.\n");
+	
+	if(rsbac_reg_unregister(handle))
+	{
+		rsbac_printk(KERN_ERR "RSBAC REG decision module root_plug: Unregistering failed - beware of possible system failure!\n");
+	}
+	
+	rsbac_printk(KERN_INFO "RSBAC REG decision module root_plug: Unloaded.\n");
+}
+
diff --git a/rsbac/adf/res/Makefile b/rsbac/adf/res/Makefile
new file mode 100644
index 0000000..bcf8e21
--- /dev/null
+++ b/rsbac/adf/res/Makefile
@@ -0,0 +1,10 @@
+#
+# File: rsbac/adf/res/Makefile
+#
+# Makefile for the Linux rsbac RES decision module.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+# 2.6.x
+obj-y    := res_main.o
diff --git a/rsbac/adf/res/res_main.c b/rsbac/adf/res/res_main.c
new file mode 100644
index 0000000..82fcd12
--- /dev/null
+++ b/rsbac/adf/res/res_main.c
@@ -0,0 +1,430 @@
+/**************************************************** */
+/* Rule Set Based Access Control                      */
+/* Implementation of the Access Control Decision      */
+/* Facility (ADF) - System Resources (RES)            */
+/* File: rsbac/adf/res/main.c                         */
+/*                                                    */
+/* Author and (c) 2002-2016: Amon Ott <ao@rsbac.org>  */
+/*                                                    */
+/* Last modified: 04/Apr/2016                         */
+/**************************************************** */
+
+#include <linux/string.h>
+#include <linux/version.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+enum rsbac_adf_req_ret_t
+   rsbac_adf_request_res (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)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    switch (request)
+      {
+        case R_MODIFY_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_system_role:
+                case A_res_role:
+                case A_res_min:
+                case A_res_max:
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_RES,
+                                     T_USER,
+                                     i_tid,
+                                     A_res_role,
+                                     &i_attr_val1,
+                                     TRUE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_res()", A_res_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_READ_ATTRIBUTE:
+            switch(attr)
+              {
+                case A_system_role:
+                case A_res_role:
+                case A_res_min:
+                case A_res_max:
+                /* All attributes (remove target!) */
+                case A_none:
+                  /* Security Officer or Admin? */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_RES,
+                                     T_USER,
+                                     i_tid,
+                                     A_res_role,
+                                     &i_attr_val1,
+                                     TRUE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_res()", A_res_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* if sec_officer, then grant */
+                  if(   (i_attr_val1.system_role == SR_security_officer)
+                     || (i_attr_val1.system_role == SR_administrator)
+                    )
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                default:
+                  return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_LOG:
+            switch(target)
+              {
+                case T_NONE:
+                  /* test owner's res_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_RES,
+                                     T_USER,
+                                     i_tid,
+                                     A_res_role,
+                                     &i_attr_val1,
+                                     TRUE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_res()", A_res_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are unknown */
+                default: return(DO_NOT_CARE);
+              }
+
+        case R_SWITCH_MODULE:
+            switch(target)
+              {
+                case T_NONE:
+                  /* we need the switch_target */
+                  if(attr != A_switch_target)
+                    return NOT_GRANTED;
+                  /* do not care for other modules */
+                  if(   (attr_val.switch_target != SW_RES)
+                     #ifdef CONFIG_RSBAC_SOFTMODE
+                     && (attr_val.switch_target != SW_SOFTMODE)
+                     #endif
+                     #ifdef CONFIG_RSBAC_FREEZE
+                     && (attr_val.switch_target != SW_FREEZE)
+                     #endif
+                    )
+                    return(DO_NOT_CARE);
+                  /* test owner's res_role */
+                  i_tid.user = owner;
+                  if (rsbac_get_attr(SW_RES,
+                                     T_USER,
+                                     i_tid,
+                                     A_res_role,
+                                     &i_attr_val1,
+                                     TRUE))
+                    {
+                      rsbac_ds_get_error("rsbac_adf_request_res()", A_res_role);
+                      return(NOT_GRANTED);
+                    }
+                  /* security officer? -> grant  */
+                  if (i_attr_val1.system_role == SR_security_officer)
+                    return(GRANTED);
+                  else
+                    return(NOT_GRANTED);
+
+                /* all other cases are unknown */
+                default: return(DO_NOT_CARE);
+              }
+
+
+/*********************/
+        default: return DO_NOT_CARE;
+      }
+
+    return DO_NOT_CARE;
+  } /* end of rsbac_adf_request_res() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up.                                                              */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+int  rsbac_adf_set_attr_res(
+                      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)
+  {
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    switch (request)
+      {
+        case R_CHANGE_OWNER:
+            switch(target)
+              {
+                case T_PROCESS:
+                  if(attr != A_owner)
+                    return(-RSBAC_EINVALIDATTR);
+                  /* Adjust Linux resources */
+                  i_tid.user = attr_val.owner;
+#ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RES]
+#endif
+                    )
+#endif
+                    {
+                      int maxval = rsbac_min(RLIM_NLIMITS - 1, RSBAC_RES_MAX);
+                      int i;
+
+                      if (rsbac_get_attr(SW_RES,
+                                         T_USER,
+                                         i_tid,
+                                         A_res_max,
+                                         &i_attr_val1,
+                                         TRUE))
+                        {
+                          rsbac_ds_get_error("rsbac_adf_set_attr_res()", A_res_max);
+                          return -RSBAC_EREADFAILED;
+                        }
+                      for(i = 0; i <= maxval ; i++)
+                        {
+                          if(i_attr_val1.res_array[i])
+                            {
+                              task_lock(current->group_leader);
+                              if(current->signal->rlim[i].rlim_max > i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_max = i_attr_val1.res_array[i];
+                              if(current->signal->rlim[i].rlim_cur > i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_cur = i_attr_val1.res_array[i];
+                              task_unlock(current->group_leader);
+                            }
+                        }
+                      if (rsbac_get_attr(SW_RES,
+                                         T_USER,
+                                         i_tid,
+                                         A_res_min,
+                                         &i_attr_val1,
+                                         TRUE))
+                        {
+                          rsbac_ds_get_error("rsbac_adf_set_attr_res()", A_res_min);
+                          return -RSBAC_EREADFAILED;
+                        }
+                      if(i_attr_val1.res_array[RLIMIT_NOFILE] > sysctl_nr_open)
+                        i_attr_val1.res_array[RLIMIT_NOFILE] = sysctl_nr_open;
+                      for(i = 0; i <= maxval ; i++)
+                        {
+                          if(i_attr_val1.res_array[i])
+                            {
+                              task_lock(current->group_leader);
+                              if(current->signal->rlim[i].rlim_max < i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_max = i_attr_val1.res_array[i];
+                              if(current->signal->rlim[i].rlim_cur < i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_cur = i_attr_val1.res_array[i];
+                              task_unlock(current->group_leader);
+                            }
+                        }
+                    }
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return(0);
+              }
+            break;
+
+        case R_EXECUTE:
+            switch(target)
+              {
+                case T_FILE:
+#ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RES]
+#endif
+                    )
+#endif
+                    {
+                      int maxval = rsbac_min(RLIM_NLIMITS - 1, RSBAC_RES_MAX);
+                      int i;
+
+                      if (rsbac_get_attr(SW_RES,
+                                         target,
+                                         tid,
+                                         A_res_max,
+                                         &i_attr_val1,
+                                         FALSE))
+                        {
+                          rsbac_ds_get_error("rsbac_adf_set_attr_res()", A_res_max);
+                          return -RSBAC_EREADFAILED;
+                        }
+                      for(i = 0; i <= maxval ; i++)
+                        {
+                          if(i_attr_val1.res_array[i])
+                            {
+                              task_lock(current->group_leader);
+                              if(current->signal->rlim[i].rlim_max > i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_max = i_attr_val1.res_array[i];
+                              if(current->signal->rlim[i].rlim_cur > i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_cur = i_attr_val1.res_array[i];
+                              task_unlock(current->group_leader);
+                            }
+                        }
+                      if (rsbac_get_attr(SW_RES,
+                                         target,
+                                         tid,
+                                         A_res_min,
+                                         &i_attr_val1,
+                                         FALSE))
+                        {
+                          rsbac_ds_get_error("rsbac_adf_set_attr_res()", A_res_min);
+                          return -RSBAC_EREADFAILED;
+                        }
+                      for(i = 0; i <= maxval ; i++)
+                        {
+                          if(i_attr_val1.res_array[i])
+                            {
+                              task_lock(current->group_leader);
+                              if(current->signal->rlim[i].rlim_max < i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_max = i_attr_val1.res_array[i];
+                              if(current->signal->rlim[i].rlim_cur < i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_cur = i_attr_val1.res_array[i];
+                              task_unlock(current->group_leader);
+                            }
+                        }
+                    }
+                  return 0;
+
+                /* all other cases are unknown */
+                default:
+                  return 0;
+              }
+            break;
+
+        case R_MODIFY_SYSTEM_DATA:
+            if (   (target == T_SCD)
+                && (tid.scd == ST_rlimit)
+               )
+              {
+                  /* Adjust Linux resources */
+                  i_tid.user = owner;
+#ifdef CONFIG_RSBAC_SOFTMODE
+                  if(   !rsbac_softmode
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+                     && !rsbac_ind_softmode[SW_RES]
+#endif
+                    )
+#endif
+                    {
+                      int maxval = rsbac_min(RLIM_NLIMITS - 1, RSBAC_RES_MAX);
+                      int i;
+
+                      if (rsbac_get_attr(SW_RES,
+                                         T_USER,
+                                         i_tid,
+                                         A_res_max,
+                                         &i_attr_val1,
+                                         TRUE))
+                        {
+                          rsbac_ds_get_error("rsbac_adf_set_attr_res()", A_res_max);
+                          return -RSBAC_EREADFAILED;
+                        }
+                      for(i = 0; i <= maxval ; i++)
+                        {
+                          if(i_attr_val1.res_array[i])
+                            {
+                              task_lock(current->group_leader);
+                              if(current->signal->rlim[i].rlim_max > i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_max = i_attr_val1.res_array[i];
+                              if(current->signal->rlim[i].rlim_cur > i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_cur = i_attr_val1.res_array[i];
+                              task_unlock(current->group_leader);
+                            }
+                        }
+                      if (rsbac_get_attr(SW_RES,
+                                         T_USER,
+                                         i_tid,
+                                         A_res_min,
+                                         &i_attr_val1,
+                                         TRUE))
+                        {
+                          rsbac_ds_get_error("rsbac_adf_set_attr_res()", A_res_min);
+                          return -RSBAC_EREADFAILED;
+                        }
+                      if(i_attr_val1.res_array[RLIMIT_NOFILE] > sysctl_nr_open)
+                        i_attr_val1.res_array[RLIMIT_NOFILE] = sysctl_nr_open;
+                      for(i = 0; i <= maxval ; i++)
+                        {
+                          if(i_attr_val1.res_array[i])
+                            {
+                              task_lock(current->group_leader);
+                              if(current->signal->rlim[i].rlim_max < i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_max = i_attr_val1.res_array[i];
+                              if(current->signal->rlim[i].rlim_cur < i_attr_val1.res_array[i])
+                                current->signal->rlim[i].rlim_cur = i_attr_val1.res_array[i];
+                              task_unlock(current->group_leader);
+                            }
+                        }
+                    }
+                  return 0;
+              }
+            break;
+
+/*********************/
+        default: return 0;
+      }
+
+    return 0;
+  } /* end of rsbac_adf_set_attr_res() */
+
+/* end of rsbac/adf/res/main.c */
diff --git a/rsbac/adf/udf/Makefile b/rsbac/adf/udf/Makefile
new file mode 100644
index 0000000..ee7b3f7
--- /dev/null
+++ b/rsbac/adf/udf/Makefile
@@ -0,0 +1,10 @@
+#
+# File: rsbac/adf/udf/Makefile
+#
+# Makefile for the Linux rsbac UDF decision module.
+#
+# Author and (c) 1999-2013 Amon Ott <ao@rsbac.org>
+#
+
+# 2.6.x
+obj-y    := udf_main.o
diff --git a/rsbac/adf/udf/udf_main.c b/rsbac/adf/udf/udf_main.c
new file mode 100644
index 0000000..7cdc7e3
--- /dev/null
+++ b/rsbac/adf/udf/udf_main.c
@@ -0,0 +1,779 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of the Access Control Decision     */
+/* Facility (ADF) - User Space Decision Facility     */
+/* File: rsbac/adf/udf/udf_main.c                    */
+/*                                                   */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 04/Apr/2016                        */
+/*************************************************** */
+
+#include <linux/init.h>
+#include <linux/unistd.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/syscalls.h>
+#include <linux/kmod.h>
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/adf.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/debug.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/proc_fs.h>
+
+/************************************************* */
+/*           Global Variables                      */
+/************************************************* */
+
+#define UDF_MAX_PROGNAME PATH_MAX
+
+static char udf_checker_prog[RSBAC_MAXNAMELEN] = "";
+
+static int R_INIT udf_checker_setup(char *line)
+  {
+    strncpy(udf_checker_prog, line, RSBAC_MAXNAMELEN - 1);
+    udf_checker_prog[RSBAC_MAXNAMELEN - 1] = 0;
+    return 1;
+  }
+__setup("rsbac_udf_checker=", udf_checker_setup);
+
+static int udf_checker_wait = UMH_WAIT_PROC | UMH_KILLABLE;
+
+static int R_INIT udf_checker_wait_setup(char *line)
+  {
+    udf_checker_wait = UMH_WAIT_PROC;
+    return 1;
+  }
+__setup("rsbac_udf_nokill", udf_checker_wait_setup);
+
+/************************************************* */
+/*          Internal Help functions                */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC)
+#ifndef PROC_BLOCK_SIZE
+#define PROC_BLOCK_SIZE	(3*1024)  /* 4K page size but our output routines use some slack for overruns */
+#endif
+
+static int
+udf_checker_proc_show(struct seq_file *m, void *v)
+{
+  union rsbac_target_id_t       rsbac_target_id;
+  union rsbac_attribute_value_t rsbac_attribute_value;
+
+  if (!rsbac_is_initialized())
+    return (-ENOSYS);
+
+#ifdef CONFIG_RSBAC_DEBUG
+  if (rsbac_debug_aef)
+    {
+      rsbac_printk(KERN_DEBUG "udf_checker_proc_info(): calling ADF.\n");
+    }
+#endif
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			 task_pid(current),
+			 T_SCD,
+			 rsbac_target_id,
+			 A_none,
+			 rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+
+  seq_printf(m, "%s\n", udf_checker_prog);
+
+  return 0;
+}
+
+static ssize_t udf_checker_proc_write(struct file * file, const char __user * buf,
+				     size_t count, loff_t *ppos)
+{
+    ssize_t err;
+    char * k_buf;
+    char * p;
+
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(count > RSBAC_MAXNAMELEN - 1) {
+	return -EOVERFLOW;
+    }
+
+    if (!rsbac_is_initialized()) {
+      return -ENOSYS;
+    }
+
+    if (!(k_buf = (char *) __get_free_page(GFP_KERNEL)))
+      return -ENOMEM;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef) {
+      rsbac_printk(KERN_DEBUG "udf_checker_proc_write(): calling ADF.\n");
+    }
+#endif
+    rsbac_target_id.dummy = 0;
+    rsbac_attribute_value.switch_target = SW_UDF;
+    if (!rsbac_adf_request(R_SWITCH_MODULE,
+			   task_pid(current),
+			   T_NONE,
+			   rsbac_target_id,
+			   A_switch_target,
+			   rsbac_attribute_value)) {
+       err = -EPERM;
+       goto out;
+    }
+
+    /*
+     * Usage: echo "/path/to/program" > /proc/rsbac_info/udf_checker
+     *   to set checker program to given value and enable checking
+     *   Program gets called with single parameter "path to file"
+     *   and must exit with either 0 (allowed) or another value (denied)
+     */
+    err = copy_from_user(k_buf, buf, count);
+    if(err < 0)
+      return err;
+    k_buf[RSBAC_MAXNAMELEN - 1] = 0;
+    p = k_buf;
+    if (*p && (*p != '/') && (*p != '\n')) {
+      err = -EINVAL;
+      goto out;
+    }
+    while (*p && (*p != '\n')) {
+      if (! (   ((*p >= 'A') && (*p <= 'Z'))
+	     || ((*p >= 'a') && (*p <= 'z'))
+	     || ((*p >= '0') && (*p <= '9'))
+	     || (*p == '/')
+	     || (*p == '_')
+	     || (*p == '-')
+	     || (*p == '.')
+	    )
+	 ) {
+        rsbac_printk(KERN_INFO
+		     "udf_checker_proc_write(): setting UDF checker denied, invalid character detected.\n");
+	err = -EINVAL;
+	goto out;
+      }
+      p++;
+    }
+    if (*p)
+      *p = 0;
+
+    strncpy(udf_checker_prog, k_buf, RSBAC_MAXNAMELEN - 1);
+    udf_checker_prog[RSBAC_MAXNAMELEN - 1] = 0;
+    if (udf_checker_prog[0])
+      rsbac_printk(KERN_INFO
+		   "udf_checker_proc_write(): setting UDF checker to %s, checking is now enabled\n",
+		   udf_checker_prog);
+    else
+      rsbac_printk(KERN_INFO
+		   "udf_checker_proc_write(): UDF checker set to empty, checking is now disabled\n",
+		   udf_checker_prog);
+    err = count;
+
+out:
+  free_page((ulong) k_buf);
+  return err;
+  }
+
+static int udf_checker_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, udf_checker_proc_show, NULL);
+}
+
+static const struct file_operations udf_checker_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = udf_checker_proc_open,
+       .read           = seq_read,
+       .write          = udf_checker_proc_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *udf_checker;
+
+#endif /* CONFIG_RSBAC_PROC */
+
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+static int udf_reset_checked(struct rsbac_fs_file_t file)
+{
+	union rsbac_attribute_value_t i_attr_val1;
+	union rsbac_target_id_t       i_tid;
+
+	/* reset checked status for file */
+	rsbac_pr_debug(adf_udf, "pid %u(%s), resetting checked status.\n",
+				       current->pid, current->comm);
+	i_tid.file=file;
+	i_attr_val1.udf_checked = UDF_unchecked;
+	if(rsbac_set_attr(SW_UDF,
+				T_FILE,
+				i_tid,
+				A_udf_checked,
+				i_attr_val1))
+	{
+		rsbac_printk(KERN_WARNING "udf_reset_checked(): rsbac_set_attr() for udf_checked on device %02u:%02u inode %lu returned error!\n",
+			MAJOR(file.device), MINOR(file.device), file.inode);
+		return -RSBAC_EWRITEFAILED;
+	}
+	if (rsbac_get_attr(SW_UDF,
+		T_FILE,
+		i_tid,
+		A_udf_checker,
+		&i_attr_val1,
+		TRUE)) {
+		rsbac_printk(KERN_WARNING
+			"udf_reset_checked(): rsbac_get_attr() for udf_checker returned error!\n");
+		return -RSBAC_EREADFAILED;
+	}
+	if (i_attr_val1.udf_checker) {
+		/* reset checker flag for file */
+		i_attr_val1.udf_checker = FALSE;
+		if(rsbac_set_attr(SW_UDF,
+					T_FILE,
+					i_tid,
+					A_udf_checker,
+					i_attr_val1))
+		{
+			rsbac_printk(KERN_WARNING "udf_reset_checked(): rsbac_set_attr() for udf_checker on device %02u:%02u inode %lu returned error!\n",
+				MAJOR(file.device), MINOR(file.device), file.inode);
+			return -RSBAC_EWRITEFAILED;
+		}
+	}
+	return 0;
+}
+#else
+static inline int udf_reset_checked(struct rsbac_fs_file_t file)
+{
+	return 0;
+}
+#endif
+
+enum rsbac_adf_req_ret_t udf_do_check(union rsbac_target_id_t tid)
+{
+	char *envp[] = { "HOME=/",
+			"TERM=linux",
+			"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
+			NULL };
+	char *argv[] = {udf_checker_prog, NULL, NULL };
+	char * progname;
+	int err;
+	u_int result;
+
+	progname = rsbac_kmalloc_unlocked(RSBAC_UDF_PATH_MAX);
+	if (!progname) {
+		rsbac_printk(KERN_WARNING
+			"udf_do_check(): cannot allocate memory!\n");
+		return NOT_GRANTED;
+	}
+
+	err = rsbac_lookup_full_path(tid.file.dentry_p, progname, RSBAC_UDF_PATH_MAX, 0);
+	if (err < 0) {
+		char * tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING
+				"udf_do_check(): rsbac_lookup_full_path() returned error %s!\n", get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+		return NOT_GRANTED;
+	}
+	rsbac_pr_debug(adf_udf, "udf_do_check(): calling %s for path %s.\n", udf_checker_prog, progname);
+
+	argv[1] = progname;
+	err = call_usermodehelper(argv[0], argv, envp, udf_checker_wait);
+	rsbac_kfree(progname);
+	result = err >> 8;
+
+	if (err < 0) {
+		if (err != -ERESTARTSYS)
+			rsbac_printk(KERN_WARNING "udf_do_check(): call_usermodehelper() could not execute %s, error %i.\n", udf_checker_prog, err);
+#if defined(CONFIG_RSBAC_DEBUG)
+		else
+			rsbac_pr_debug(adf_udf, "udf_do_check(): call_usermodehelper() returned -ERESTARTSYS, checker was interrupted.\n");
+#endif
+	}
+#if defined(CONFIG_RSBAC_DEBUG) || defined(CONFIG_RSBAC_UDF_CACHE)
+	else {
+		u_int signal;
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+		union rsbac_attribute_value_t i_attr_val1;
+#endif
+
+		signal = err & 255;
+		rsbac_pr_debug(adf_udf, "udf_do_check(): call_usermodehelper() returned %u (result %u, signal %u).\n", err, result, signal);
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+		/* only cache, if not killed by signal and no temp fail */
+		if (   !signal
+		    && (result != UDF_res_temp_fail_allow)
+		    && (result != UDF_res_temp_fail_deny)
+		   ) {
+			if(!result)
+				i_attr_val1.udf_checked = UDF_allowed;
+			else
+				i_attr_val1.udf_checked = UDF_denied;
+			if (rsbac_set_attr(SW_UDF,
+				T_FILE,
+				tid,
+				A_udf_checked,
+				i_attr_val1))
+				rsbac_printk(KERN_WARNING "udf_do_check(): rsbac_set_attr() returned error!\n");
+		}
+#endif
+	}
+#endif
+
+	if (!err || (result == UDF_res_temp_fail_allow))
+		return GRANTED;
+	else
+		return NOT_GRANTED;
+}
+
+static int udf_ignored(union rsbac_target_id_t tid)
+{
+	union rsbac_attribute_value_t i_attr_val1;
+
+	if (rsbac_get_attr(SW_UDF,
+		T_FILE,
+		tid,
+		A_udf_do_check,
+		&i_attr_val1,
+		TRUE)) {
+		rsbac_printk(KERN_WARNING
+			"rsbac_adf_request_udf(): rsbac_get_attr() for udf_do_check returned error!\n");
+		return FALSE;
+	}
+	if(i_attr_val1.udf_do_check == UDF_never)
+		return TRUE;
+	return FALSE;
+}
+
+#if defined(CONFIG_RSBAC_UDF_UDF_PROT)
+static enum rsbac_adf_req_ret_t udf_check_secoff(rsbac_uid_t owner, enum rsbac_attribute_t attr, int readonly)
+{
+	union rsbac_target_id_t       i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	/* Security Officer? */
+	i_tid.user = owner;
+	if (rsbac_get_attr(SW_UDF,
+			T_USER,
+			i_tid,
+			A_udf_role,
+			&i_attr_val1,
+			TRUE)) {
+			rsbac_printk(KERN_WARNING
+					"rsbac_adf_request_udf(): rsbac_get_attr() returned error!\n");
+			return NOT_GRANTED;
+	}
+	/* if sec_officer, then grant */
+	if (   (i_attr_val1.system_role == SR_security_officer)
+	    || (readonly && (i_attr_val1.system_role == SR_administrator))
+	   )
+		return GRANTED;
+	else
+		return NOT_GRANTED;
+}
+#endif
+
+/************************************************* */
+/*          Externally visible functions           */
+/************************************************* */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_udf(void)
+#else
+int __init rsbac_init_udf(void)
+#endif
+{
+	if (rsbac_is_initialized())
+	{
+		rsbac_printk(KERN_WARNING "rsbac_init_udf(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+
+	/* init data structures */
+	rsbac_printk(KERN_INFO "rsbac_init_udf(): Initializing RSBAC: UDF subsystem\n");
+	if (udf_checker_prog[0])
+		rsbac_printk(KERN_DEBUG "rsbac_init_udf(): rsbac_udf_checker is %s\n", udf_checker_prog);
+	else
+		rsbac_printk(KERN_DEBUG "rsbac_init_udf(): rsbac_udf_checker is unset, no checking\n");
+
+	if (udf_checker_wait & UMH_KILLABLE)
+		rsbac_printk(KERN_DEBUG "rsbac_init_udf(): rsbac_udf_nokill is not set, checker is killable\n");
+	else
+		rsbac_printk(KERN_DEBUG "rsbac_init_udf(): rsbac_udf_nokill is set, checker is not killable\n");
+
+	#if defined(CONFIG_RSBAC_PROC)
+	udf_checker = proc_create("udf_checker", S_IFREG | S_IRUGO | S_IWUGO, proc_rsbac_root_p, &udf_checker_proc_fops);
+	#endif
+
+	return 0;
+}
+
+inline enum rsbac_adf_req_ret_t
+rsbac_adf_request_udf (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)
+{
+	int daemon_allowed;
+
+	union rsbac_target_id_t       i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	/* get udf_do_check for target */
+	switch(target) {
+		case T_FILE:
+			switch(request) {
+				case R_EXECUTE:
+					if(udf_ignored(tid))
+						return DO_NOT_CARE;
+					daemon_allowed = 0;
+					break;
+				case R_READ_WRITE_OPEN:
+				case R_READ_OPEN:
+					if(udf_ignored(tid))
+						return DO_NOT_CARE;
+					daemon_allowed = 1;
+					break;
+#if defined(CONFIG_RSBAC_UDF_UDF_PROT)
+				case R_READ_ATTRIBUTE:
+					switch (attr) {
+						case A_udf_role:
+						case A_udf_checker:
+						case A_udf_checked:
+						case A_udf_do_check:
+						case A_system_role:
+						case A_none:
+							return udf_check_secoff(owner, attr, TRUE);
+						default:
+							return DO_NOT_CARE;
+					}
+				case R_MODIFY_ATTRIBUTE:
+					switch (attr) {
+						case A_udf_role:
+						case A_udf_checker:
+						case A_udf_checked:
+						case A_udf_do_check:
+						case A_system_role:
+						case A_none:
+							return udf_check_secoff(owner, attr, FALSE);
+						default:
+							return DO_NOT_CARE;
+					}
+#endif
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+
+#if defined(CONFIG_RSBAC_UDF_UDF_PROT)
+		case T_DIR:
+		case T_PROCESS:
+		case T_USER:
+			switch(request) {
+				case R_READ_ATTRIBUTE:
+					switch (attr) {
+						case A_udf_role:
+						case A_udf_checker:
+						case A_udf_checked:
+						case A_udf_do_check:
+						case A_system_role:
+						case A_none:
+							return udf_check_secoff(owner, attr, TRUE);
+						default:
+							return DO_NOT_CARE;
+					}
+				case R_MODIFY_ATTRIBUTE:
+					switch (attr) {
+						case A_udf_role:
+						case A_udf_checker:
+						case A_udf_checked:
+						case A_udf_do_check:
+						case A_system_role:
+						case A_none:
+							return udf_check_secoff(owner, attr, FALSE);
+						default:
+							return DO_NOT_CARE;
+					}
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+		case T_NONE:
+			switch(request) {
+				case R_SWITCH_MODULE:
+					/* we need the switch_target */
+					if(attr != A_switch_target)
+						return NOT_GRANTED;
+					/* do not care for other modules */
+					if(   (attr_val.switch_target != SW_UDF)
+#ifdef CONFIG_RSBAC_SOFTMODE
+						&& (attr_val.switch_target != SW_SOFTMODE)
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+						&& (attr_val.switch_target != SW_FREEZE)
+#endif
+					  )
+						return DO_NOT_CARE;
+					return udf_check_secoff(owner, attr, FALSE);
+				default:
+					return DO_NOT_CARE;
+			}
+			break;
+#endif /* UDF_UDF_PROT */
+
+		default:
+			return DO_NOT_CARE;
+	}
+
+/* From here we can only have FILE targets */
+
+/* checker enabled? */
+	if (!udf_checker_prog[0]) {
+		rsbac_pr_debug(adf_udf, "pid %u(%s), no checker defined.\n",
+				current->pid, current->comm);
+		return DO_NOT_CARE;
+	}
+
+	if (daemon_allowed) {
+		i_tid.process = caller_pid;
+		if (rsbac_get_attr(SW_UDF,
+					T_PROCESS,
+					i_tid,
+					A_udf_checker,
+					&i_attr_val1,
+					FALSE)) {
+			rsbac_printk(KERN_WARNING
+					"rsbac_adf_request_udf(): rsbac_get_attr() returned error!\n");
+			return NOT_GRANTED;
+		}
+		/* if checker, then grant */
+		if (i_attr_val1.udf_checker) {
+			rsbac_pr_debug(adf_udf, "pid %u(%s) is a checker, no checking required for device %02u:%02u inode %lu.\n",
+					current->pid, current->comm,
+					RSBAC_MAJOR(tid.file.device),
+					RSBAC_MINOR(tid.file.device),
+					tid.file.inode);
+			return GRANTED;
+		}
+	}
+
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	if (rsbac_get_attr(SW_UDF,
+				target,
+				tid,
+				A_udf_checked,
+				&i_attr_val1,
+				FALSE)) {
+		rsbac_printk(KERN_WARNING
+				"rsbac_adf_request_udf(): rsbac_get_attr() returned error!\n");
+		return NOT_GRANTED;
+	}
+	if(i_attr_val1.udf_checked == UDF_allowed) {
+		rsbac_pr_debug(adf_udf, "pid %u(%s), result allowed for device %02u:%02u inode %lu taken from cache.\n",
+				current->pid, current->comm,
+				RSBAC_MAJOR(tid.file.device),
+				RSBAC_MINOR(tid.file.device),
+				tid.file.inode);
+		return GRANTED;
+	}
+	if(i_attr_val1.udf_checked == UDF_denied) {
+		rsbac_pr_debug(adf_udf, "pid %u(%s), result denied for device %02u:%02u inode %lu taken from cache.\n",
+				current->pid, current->comm,
+				RSBAC_MAJOR(tid.file.device),
+				RSBAC_MINOR(tid.file.device),
+				tid.file.inode);
+		return NOT_GRANTED;
+	}
+#endif
+
+	rsbac_pr_debug(adf_udf, "pid %u(%s), checking required for device %02u:%02u inode %lu.\n",
+			current->pid, current->comm,
+			RSBAC_MAJOR(tid.file.device),
+			RSBAC_MINOR(tid.file.device),
+			tid.file.inode);
+	/* call checker */
+	return udf_do_check(tid);
+} /* end of rsbac_adf_request_udf() */
+
+
+/*****************************************************************************/
+/* If the request returned granted and the operation is performed,           */
+/* the following function can be called by the AEF to get all aci set        */
+/* correctly. For write accesses that are performed fully within the kernel, */
+/* this is usually not done to prevent extra calls, including R_CLOSE for    */
+/* cleaning up. Because of this, the write boundary is not adjusted - there  */
+/* is no user-level writing anyway...                                        */
+/* The second instance of target specification is the new target, if one has */
+/* been created, otherwise its values are ignored.                           */
+/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */
+
+inline int rsbac_adf_set_attr_udf(
+		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)
+{
+	union rsbac_target_id_t       i_tid;
+	union rsbac_attribute_value_t i_attr_val1;
+
+	switch(target) {
+		case T_FILE:
+			switch(request) {
+				case R_EXECUTE:
+					/* get udf_checker for file */
+					if (rsbac_get_attr(SW_UDF,
+								T_FILE,
+								tid,
+								A_udf_checker,
+								&i_attr_val1,
+								TRUE)) {
+						rsbac_printk(KERN_WARNING
+								"rsbac_adf_set_attr_udf(): rsbac_get_attr() returned error!\n");
+						return -RSBAC_EREADFAILED;
+					}
+					/* and set for process, if new program is checker */
+					if(i_attr_val1.udf_checker) {
+						i_tid.process = caller_pid;
+						if (rsbac_set_attr(SW_UDF,
+								T_PROCESS,
+								i_tid,
+								A_udf_checker,
+								i_attr_val1)) {
+							rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_udf(): rsbac_set_attr() returned error!\n");
+							return -RSBAC_EWRITEFAILED;
+						}
+					}
+					return 0;
+				case R_CLOSE:
+					if(udf_ignored(tid))
+						return 0;
+					if(   (attr == A_f_mode)
+						&& (attr_val.f_mode & FMODE_WRITE)
+					) {
+						udf_reset_checked(tid.file);
+#if defined(CONFIG_RSBAC_UDF_ON_CLOSE)
+						break;
+#endif
+					}
+					return 0;
+				case R_APPEND_OPEN:
+				case R_READ_WRITE_OPEN:
+				case R_WRITE_OPEN:
+					if(!udf_ignored(tid))
+						udf_reset_checked(tid.file);
+					return 0;
+				case R_DELETE:
+					if(!udf_ignored(tid))
+						udf_reset_checked(tid.file);
+					return 0;
+				default:
+					return 0;
+			}
+			break;
+		case T_PROCESS:
+			switch(request) {
+				case R_CLONE:
+					/* Get udf_checker from first process */
+					if (rsbac_get_attr(SW_UDF,
+							T_PROCESS,
+							tid,
+							A_udf_checker,
+							&i_attr_val1,
+							FALSE)) {
+						rsbac_printk(KERN_WARNING
+							"rsbac_adf_set_attr_udf(): rsbac_get_attr() returned error!\n");
+						return -RSBAC_EREADFAILED;
+					}
+					/* Set udf_checker for new process, if set for first */
+					if (   i_attr_val1.udf_checker
+						&& (rsbac_set_attr(SW_UDF,
+								T_PROCESS,
+								new_tid,
+								A_udf_checker,
+								i_attr_val1)) ) {
+						rsbac_printk(KERN_WARNING "rsbac_adf_set_attr_udf(): rsbac_set_attr() returned error!\n");
+						return -RSBAC_EWRITEFAILED;
+					}
+					return 0;
+				default:
+					return 0;
+			}
+		default:
+			return 0;
+	}
+
+/* only needed for CLOSE, if enabled */
+#if defined(CONFIG_RSBAC_UDF_ON_CLOSE)
+/* checker enabled? */
+	if (!udf_checker_prog[0])
+		return 0;
+
+	i_tid.process = caller_pid;
+	if (rsbac_get_attr(SW_UDF,
+				T_PROCESS,
+				i_tid,
+				A_udf_checker,
+				&i_attr_val1,
+				FALSE)) {
+		rsbac_printk(KERN_WARNING
+				"rsbac_adf_set_attr_udf(): rsbac_get_attr() returned error!\n");
+		return -RSBAC_EREADFAILED;
+	}
+	/* if checker, then grant */
+	if (i_attr_val1.udf_checker) {
+		rsbac_pr_debug(adf_udf, "pid %u(%s) is a checker, no checking required for device %02u:%02u inode %lu.\n",
+				current->pid, current->comm,
+				RSBAC_MAJOR(tid.file.device),
+				RSBAC_MINOR(tid.file.device),
+				tid.file.inode);
+		return 0;
+	}
+
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	/* get udf_checked for file */
+	if (rsbac_get_attr(SW_UDF,
+				target,
+				tid,
+				A_udf_checked,
+				&i_attr_val1,
+				FALSE))
+	{
+		rsbac_printk(KERN_WARNING
+				"rsbac_adf_set_attr_udf(): rsbac_get_attr() returned error!\n");
+		return -RSBAC_EREADFAILED;
+	}
+	if(i_attr_val1.udf_checked == UDF_allowed)
+		return 0;
+	if(i_attr_val1.udf_checked == UDF_denied)
+		return 0;
+#endif
+
+	rsbac_pr_debug(adf_udf, "pid %u(%s), checking required for device %02u:%02u inode %lu.\n",
+			current->pid, current->comm,
+			RSBAC_MAJOR(tid.file.device),
+			RSBAC_MINOR(tid.file.device),
+			tid.file.inode);
+	/* call checker */
+	udf_do_check(tid);
+#endif /* RSBAC_UDF_ON_CLOSE */
+
+	return 0;
+} /* end of rsbac_adf_set_attr_udf() */
diff --git a/rsbac/data_structures/Makefile b/rsbac/data_structures/Makefile
new file mode 100644
index 0000000..83b2a5a
--- /dev/null
+++ b/rsbac/data_structures/Makefile
@@ -0,0 +1,18 @@
+#
+# File: rsbac/data_structures/Makefile
+#
+# Makefile for the RSBAC data structures.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+#
+
+obj-y += aci_data_structures.o gen_lists.o
+
+# Adding policy dependent data structures
+
+obj-$(CONFIG_RSBAC_MAC) += mac_data_structures.o
+obj-$(CONFIG_RSBAC_RC) += rc_data_structures.o
+obj-$(CONFIG_RSBAC_AUTH) += auth_data_structures.o
+obj-$(CONFIG_RSBAC_ACL) += acl_data_structures.o
+obj-$(CONFIG_RSBAC_UM) += um_data_structures.o
+
diff --git a/rsbac/data_structures/aci_data_structures.c b/rsbac/data_structures/aci_data_structures.c
new file mode 100644
index 0000000..47b4c59
--- /dev/null
+++ b/rsbac/data_structures/aci_data_structures.c
@@ -0,0 +1,14463 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of ACI data structures             */
+/* Author and (c) 1999-2018: Amon Ott <ao@rsbac.org> */
+/* (some smaller parts copied from fs/namei.c        */
+/*  and others)                                      */
+/*                                                   */
+/* Last modified: 09/Apr/2018                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/fs_struct.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+#include <linux/quotaops.h>
+#include <linux/proc_fs.h>
+#include <linux/msdos_fs.h>
+#include <linux/iso_fs.h>
+#include <linux/nfs_fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/kthread.h>
+#include <linux/coda.h>
+#include <linux/initrd.h>
+#include <linux/security.h>
+#include <linux/syscalls.h>
+#include <linux/srcu.h>
+#include <linux/seq_file.h>
+#include <linux/magic.h>
+#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
+#include <linux/mm.h>
+#include <linux/blkdev.h>
+#include <linux/freezer.h>
+#include <net/net_namespace.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/file.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/fs.h>
+#include <rsbac/getname.h>
+#include <rsbac/net_getname.h>
+#include <rsbac/adf.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/reg.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/gen_lists.h>
+#include <rsbac/jail.h>
+#include <linux/string.h>
+#include <linux/kdev_t.h>
+#include "../../fs/mount.h"
+
+#define FUSE_SUPER_MAGIC 0x65735546
+#define CEPH_SUPER_MAGIC 0x00c36400
+
+#ifdef CONFIG_RSBAC_MAC
+#include <rsbac/mac.h>
+#endif
+
+#ifdef CONFIG_RSBAC_DAZ
+#include <rsbac/daz.h>
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+#include <rsbac/rc.h>
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+#include <rsbac/auth.h>
+#endif
+
+#if defined(CONFIG_RSBAC_ACL)
+#include <rsbac/acl.h>
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+rsbac_jail_id_t rsbac_jail_syslog_jail_id = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_PAX) && (defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR))
+#include <rsbac/pax.h>
+#endif
+
+#ifdef CONFIG_RSBAC_UM
+#include <rsbac/um.h>
+#endif
+
+#ifdef CONFIG_RSBAC_UDF
+#include <rsbac/udf.h>
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+#include <linux/unistd.h>
+#include <linux/timer.h>
+static u_int auto_interval = CONFIG_RSBAC_AUTO_WRITE * HZ;
+#endif				/* CONFIG_RSBAC_AUTO_WRITE */
+
+#if  (defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)) \
+   || defined(CONFIG_RSBAC_INIT_THREAD)
+static DECLARE_WAIT_QUEUE_HEAD(rsbacd_wait);
+#endif
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+#include <rsbac/network.h>
+#endif
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+/* The following global variables are needed for access to ACI data.        */
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_initialized);
+#endif
+rsbac_boolean_t rsbac_initialized = FALSE;
+
+static rsbac_boolean_t rsbac_allow_mounts = FALSE;
+
+static char compiled_modules[80];
+
+kdev_t rsbac_root_dev;
+#ifdef CONFIG_RSBAC_INIT_DELAY
+struct vfsmount * rsbac_root_vfsmount_p = NULL;
+#endif
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_root_dev);
+#endif
+DEFINE_SEMAPHORE(rsbac_write_sem);
+
+static struct rsbac_device_list_head_t * device_head_p[RSBAC_NR_DEVICE_LISTS];
+static spinlock_t device_list_locks[RSBAC_NR_DEVICE_LISTS];
+static struct srcu_struct device_list_srcu[RSBAC_NR_DEVICE_LISTS];
+static struct lock_class_key device_list_lock_class;
+
+#ifdef CONFIG_RSBAC_XSTATS
+__u64 syscall_count[RSYS_none];
+#endif
+
+static struct rsbac_dev_handles_t dev_handles;
+static struct rsbac_dev_handles_t dev_major_handles;
+static struct rsbac_ipc_handles_t ipc_handles;
+static struct rsbac_user_handles_t user_handles;
+#ifdef CONFIG_RSBAC_RC_UM_PROT
+static struct rsbac_group_handles_t group_handles;
+#endif
+static struct rsbac_process_handles_t process_handles;
+
+#ifdef CONFIG_RSBAC_NET_DEV
+static struct rsbac_netdev_handles_t netdev_handles;
+#endif
+#ifdef CONFIG_RSBAC_NET_OBJ
+static rsbac_list_handle_t net_temp_handle;
+static struct rsbac_nettemp_handles_t nettemp_handles;
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC)
+static struct rsbac_lnetobj_handles_t lnetobj_handles;
+static struct rsbac_rnetobj_handles_t rnetobj_handles;
+#endif
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+static struct rsbac_gen_netobj_aci_t def_gen_netobj_aci =
+    DEFAULT_GEN_NETOBJ_ACI;
+#endif
+#endif
+
+/* Default ACIs: implemented as variables, might be changeable some time */
+
+/* rsbac root dir items, end of recursive inherit */
+static struct rsbac_gen_fd_aci_t def_gen_root_dir_aci =
+    DEFAULT_GEN_ROOT_DIR_ACI;
+static struct rsbac_gen_fd_aci_t def_gen_fd_aci = DEFAULT_GEN_FD_ACI;
+
+#if defined(CONFIG_RSBAC_MAC)
+static struct rsbac_mac_fd_aci_t def_mac_root_dir_aci =
+    DEFAULT_MAC_ROOT_DIR_ACI;
+static struct rsbac_mac_fd_aci_t def_mac_fd_aci = DEFAULT_MAC_FD_ACI;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+static struct rsbac_daz_fd_aci_t  def_daz_root_dir_aci  = DEFAULT_DAZ_ROOT_DIR_ACI;
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+static rsbac_time_t rsbac_daz_ttl = CONFIG_RSBAC_DAZ_TTL;
+#endif
+#endif
+#if defined(CONFIG_RSBAC_RC)
+static struct rsbac_rc_fd_aci_t def_rc_root_dir_aci =
+    DEFAULT_RC_ROOT_DIR_ACI;
+static struct rsbac_rc_fd_aci_t def_rc_fd_aci = DEFAULT_RC_FD_ACI;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+static struct rsbac_res_fd_aci_t def_res_fd_aci = DEFAULT_RES_FD_ACI;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+static struct rsbac_udf_fd_aci_t  def_udf_root_dir_aci  = DEFAULT_UDF_ROOT_DIR_ACI;
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+static rsbac_time_t rsbac_udf_ttl = CONFIG_RSBAC_UDF_TTL;
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_PROC)
+#include <rsbac/proc_fs.h>
+
+#ifdef CONFIG_RSBAC_XSTATS
+static __u64 get_attr_count[T_NONE] = { 0, 0, 0, 0, 0, 0, 0 };
+static __u64 set_attr_count[T_NONE] = { 0, 0, 0, 0, 0, 0, 0 };
+static __u64 remove_count[T_NONE] = { 0, 0, 0, 0, 0, 0, 0 };
+static __u64 get_parent_count = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(proc_rsbac_root_p);
+#endif
+struct proc_dir_entry *proc_rsbac_root_p = NULL;
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(proc_rsbac_backup_p);
+#endif
+struct proc_dir_entry *proc_rsbac_backup_p = NULL;
+
+#endif				/* PROC */
+
+#ifdef CONFIG_DEVFS_MOUNT
+#include <linux/devfs_fs_kernel.h>
+#endif
+
+static struct rsbac_mount_list_t * rsbac_mount_list = NULL;
+
+#ifdef CONFIG_RSBAC_MAC
+static struct rsbac_mac_process_aci_t mac_init_p_aci =
+    DEFAULT_MAC_P_INIT_ACI;
+#endif
+#ifdef CONFIG_RSBAC_RC
+static struct rsbac_rc_process_aci_t rc_kernel_p_aci =
+    DEFAULT_RC_P_KERNEL_ACI;
+#endif
+
+static kdev_t umount_device_in_progress = RSBAC_AUTO_DEV;
+
+static struct kmem_cache * device_item_slab = NULL;
+
+/**************************************************/
+/*       Declarations of internal functions       */
+/**************************************************/
+
+static struct rsbac_device_list_item_t *lookup_device(kdev_t kdev, u_int hash);
+
+/************************************************* */
+/*               Internal Help functions           */
+/************************************************* */
+
+static u_int gen_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+static u_int gen_nr_p_hash_bits = 1;
+
+#if defined(CONFIG_RSBAC_MAC)
+static u_int mac_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+static u_int mac_nr_p_hash_bits = 1;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+static u_int daz_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+static u_int daz_scanned_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#endif
+#if defined(CONFIG_RSBAC_FF)
+static u_int ff_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+static u_int rc_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+static u_int rc_nr_p_hash_bits = 1;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+static u_int auth_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+static u_int cap_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+static u_int jail_nr_p_hash_bits = 1;
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+static u_int pax_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+static u_int res_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+static u_int udf_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+static u_int udf_checked_nr_fd_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+#endif
+#endif
+
+static inline u_int device_hash(kdev_t id)
+{
+  return id & (RSBAC_NR_DEVICE_LISTS - 1);
+}
+
+/* These help functions do NOT handle data consistency protection by */
+/* rw-spinlocks! This is done exclusively by non-internal functions! */
+
+/************************************************************************** */
+/* Read/Write functions                                                     */
+
+/* This help function protects some filesystems from being written to */
+/* and disables writing under some conditions, e.g. in an interrupt */
+
+rsbac_boolean_t rsbac_type_writable(struct super_block * sb_p)
+{
+#ifdef CONFIG_RSBAC_NO_WRITE
+	return FALSE;
+#else
+	if (!sb_p || !sb_p->s_dev)
+		return FALSE;
+	if (   (sb_p->s_magic == SOCKFS_MAGIC)
+#ifndef CONFIG_RSBAC_MSDOS_WRITE
+	    || (sb_p->s_magic == MSDOS_SUPER_MAGIC)
+#endif
+	    || (sb_p->s_magic == PIPEFS_MAGIC)
+	    || (sb_p->s_magic == TMPFS_MAGIC)
+	    || (sb_p->s_magic == ANON_INODE_FS_MAGIC)
+	    || (sb_p->s_magic == 0xa10a10a1) /* AIO_RING_MAGIC */
+	    || (sb_p->s_magic == BDEVFS_MAGIC)
+	    || (sb_p->s_magic == DEVPTS_SUPER_MAGIC)
+	    || (sb_p->s_magic == NSFS_MAGIC)
+	    || (sb_p->s_magic == PROC_SUPER_MAGIC)
+	    || (sb_p->s_magic == DEBUGFS_MAGIC)
+	    || (sb_p->s_magic == CGROUP_SUPER_MAGIC)
+	    || (sb_p->s_magic == BINFMTFS_MAGIC)
+	    || (sb_p->s_magic == SECURITYFS_MAGIC)
+	    || (sb_p->s_magic == SELINUX_MAGIC)
+	    || (sb_p->s_magic == SYSFS_MAGIC)
+	    || (sb_p->s_magic == NFS_SUPER_MAGIC)
+	    || (sb_p->s_magic == CODA_SUPER_MAGIC)
+	    || (sb_p->s_magic == NCP_SUPER_MAGIC)
+	    || (sb_p->s_magic == SMB_SUPER_MAGIC)
+	    || (sb_p->s_magic == ISOFS_SUPER_MAGIC)
+	    || (sb_p->s_magic == OCFS2_SUPER_MAGIC)
+	    || (sb_p->s_magic == FUSE_SUPER_MAGIC)
+	    || (sb_p->s_magic == CEPH_SUPER_MAGIC)
+	   )
+		return FALSE;
+	else
+		return TRUE;
+#endif
+}
+
+rsbac_boolean_t rsbac_device_type_writable(struct rsbac_device_list_item_t *device_p)
+{
+	if (!device_p || !device_p->vfsmount_p || !device_p->vfsmount_p->mnt_sb)
+		return FALSE;
+	return rsbac_type_writable(device_p->vfsmount_p->mnt_sb);
+}
+
+rsbac_boolean_t rsbac_writable(struct super_block * sb_p)
+{
+#ifdef CONFIG_RSBAC_NO_WRITE
+	return FALSE;
+#else
+	if (!sb_p || !sb_p->s_dev)
+		return FALSE;
+	if (rsbac_debug_no_write || (sb_p->s_flags & MS_RDONLY)
+	    || in_interrupt())
+		return FALSE;
+	if (!MAJOR(sb_p->s_dev))
+		return FALSE;
+	return rsbac_type_writable(sb_p);
+#endif
+}
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+static rsbac_boolean_t rsbac_want_cache(struct rsbac_device_list_item_t * device_p)
+{
+	if (   !rsbac_fd_cache_disable
+	    && (   (RSBAC_MAJOR(device_p->id) > 1)
+	        || (   device_p->vfsmount_p
+	            && device_p->vfsmount_p->mnt_sb
+	            && (
+	                   (rsbac_fd_cache_fuse && device_p->vfsmount_p->mnt_sb->s_magic == FUSE_SUPER_MAGIC)
+	                || (rsbac_fd_cache_ceph && device_p->vfsmount_p->mnt_sb->s_magic == CEPH_SUPER_MAGIC)
+		       )
+	           )
+	       )
+	   )
+		return TRUE;
+	else
+		return FALSE;
+}
+#endif
+
+/* This lookup function ensures correct access to the file system.          */
+/* It returns a pointer to the dentry of the rsbac directory on the mounted */
+/* device specified by kdev. If the directory    */
+/* does not exist, it is created, if create_dir == TRUE and writable. */
+
+static int lookup_aci_path_dentry(struct vfsmount *vfsmount_p,
+				  struct dentry **dir_dentry_pp,
+				  rsbac_boolean_t create_dir, kdev_t kdev)
+{
+	struct dentry *dir_dentry_p = NULL;
+	struct dentry *root_dentry_p = NULL;
+	int err = 0;
+	struct rsbac_device_list_item_t *device_p;
+	u_int hash;
+	int srcu_idx;
+
+	if (!dir_dentry_pp)
+		return -RSBAC_EINVALIDPOINTER;
+
+	if (!vfsmount_p) {
+		vfsmount_p = rsbac_get_vfsmount(kdev);
+		if (!vfsmount_p) {
+			rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): unknown device %02u:%02u\n",
+				     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+			return -RSBAC_EINVALIDDEV;
+		}
+	}
+
+	/* pipefs and sockfs must not be read from */
+	if ((vfsmount_p->mnt_sb->s_magic == PIPEFS_MAGIC)
+	    || (vfsmount_p->mnt_sb->s_magic == SOCKFS_MAGIC)
+	    ) {
+		return -RSBAC_ENOTFOUND;
+	}
+	hash = device_hash(kdev);
+
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(kdev, hash);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): No entry for device %02u:%02u\n",
+			     MAJOR(kdev), MINOR(kdev));
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	/* already looked up earlier? */
+	if (device_p->rsbac_dir_dentry_p) {
+		*dir_dentry_pp = device_p->rsbac_dir_dentry_p;
+#ifdef CONFIG_RSBAC_DEBUG
+		if (rsbac_debug_ds) {
+			spin_lock(&device_p->rsbac_dir_dentry_p->d_lock);
+			rsbac_pr_debug(ds, "device_p->rsbac_dir_dentry_p->d_lockref.count "
+				       "for device %02u:%02u is %i!\n",
+				       MAJOR(vfsmount_p->mnt_sb->s_dev), MINOR(vfsmount_p->mnt_sb->s_dev),
+				       device_p->rsbac_dir_dentry_p->d_lockref.count);
+			spin_unlock(&device_p->rsbac_dir_dentry_p->d_lock);
+		}
+#endif
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		return 0;
+	}
+	/* Must unlock here for the lookup */
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	rsbac_pr_debug(ds, "first time lookup for or non-existing %s on device "
+		       "%02u:%02u!\n", RSBAC_ACI_PATH,
+		       MAJOR(vfsmount_p->mnt_sb->s_dev), MINOR(vfsmount_p->mnt_sb->s_dev));
+	if (!vfsmount_p->mnt_sb->s_root) {
+		rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): Super_block for device %02u:%02u has no root dentry!\n",
+			     MAJOR(vfsmount_p->mnt_sb->s_dev), MINOR(vfsmount_p->mnt_sb->s_dev));
+		err = -RSBAC_EINVALIDDEV;
+		goto out;
+	}
+
+	if (!vfsmount_p->mnt_sb->s_root->d_inode) {
+		rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): Super_block for device %02u:%02u has no root dentry->d_inode!\n",
+			     MAJOR(vfsmount_p->mnt_sb->s_dev), MINOR(vfsmount_p->mnt_sb->s_dev));
+		err = -RSBAC_EINVALIDDEV;
+		goto out;
+	}
+
+	/* lookup dentry of ACI_PATH on this device */
+#ifdef CONFIG_RSBAC_DEBUG
+	if (rsbac_debug_ds) {
+		spin_lock(&vfsmount_p->mnt_sb->s_root->d_lock);
+		rsbac_pr_debug(ds, "lookup rsbac path %s for device %02u:%02u, "
+			       "sb_p->s_root->d_lockref.count is %i!\n",
+			       RSBAC_ACI_PATH, MAJOR(vfsmount_p->mnt_sb->s_dev),
+			       MINOR(vfsmount_p->mnt_sb->s_dev),
+			       vfsmount_p->mnt_sb->s_root->d_lockref.count);
+		spin_unlock(&vfsmount_p->mnt_sb->s_root->d_lock);
+	}
+#endif
+	mutex_lock_nested(&vfsmount_p->mnt_sb->s_root->d_inode->i_mutex, I_MUTEX_XATTR);
+	dir_dentry_p =
+	    rsbac_lookup_one_len(RSBAC_ACI_PATH, vfsmount_p->mnt_sb->s_root,
+				 strlen(RSBAC_ACI_PATH));
+	mutex_unlock(&vfsmount_p->mnt_sb->s_root->d_inode->i_mutex);
+
+	if (IS_ERR(dir_dentry_p))
+		switch (PTR_ERR(dir_dentry_p)) {
+		case -ENOENT:
+		case -ENOTDIR:
+			err = -RSBAC_ENOTFOUND;
+			goto out;
+		case -ENOMEM:
+			rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): memory allocation error!\n");
+			err = -RSBAC_ENOROOTDIR;
+			goto out;
+		case -ENAMETOOLONG:
+			rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): ACI_PATH too long on fs!\n");
+			err = -RSBAC_EPATHTOOLONG;
+			goto out;
+		case -EACCES:
+			rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): No access to ACI_PATH!\n");
+			err = -RSBAC_EACCESS;
+			goto out;
+		default:
+			rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): Error on root dir: %li!\n",
+				     PTR_ERR(dir_dentry_p));
+			err = -RSBAC_ENOROOTDIR;
+			goto out;
+		}
+
+	if (!dir_dentry_p) {
+		rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): rsbac_lookup_(dentry|one) returned null pointer!\n");
+		err = -RSBAC_EINVALIDPOINTER;
+		goto out;
+	}
+	if (!dir_dentry_p->d_inode) {	/* dir could not be found -> try to create it */
+		/* but only, if allowed... */
+		if (!create_dir) {
+			err = -RSBAC_ENOTFOUND;
+			goto out_dir_dput;
+		}
+		rsbac_pr_debug(ds, "try to create dir, first test writable!\n");
+		/* ... and writable. */
+		if (!rsbac_writable(vfsmount_p->mnt_sb)) {	/* mounted read only or special case */
+			err = -RSBAC_ENOTWRITABLE;
+			goto out_dir_dput;
+		}
+		root_dentry_p = lock_parent(dir_dentry_p);
+		err = PTR_ERR(root_dentry_p);
+		if (IS_ERR(root_dentry_p)) {
+			err = -RSBAC_ECOULDNOTCREATEPATH;
+			goto out_dir_dput;
+		}
+		if (!root_dentry_p->d_inode
+		    || !root_dentry_p->d_inode->i_op
+		    || !root_dentry_p->d_inode->i_op->mkdir) {
+			unlock_dir(root_dentry_p);
+			err = -RSBAC_ECOULDNOTCREATEPATH;
+			goto out_dir_dput;
+		}
+		dquot_initialize(root_dentry_p->d_inode);
+		err =
+		    root_dentry_p->d_inode->i_op->mkdir(root_dentry_p->
+							d_inode,
+							dir_dentry_p,
+							RSBAC_ACI_DIR_MODE);
+		unlock_dir(root_dentry_p);
+		if (err) {
+			err = -RSBAC_ECOULDNOTCREATEPATH;
+			goto out_dir_dput;
+		}
+	} else {		/* was found */
+		/* check, whether this is a dir */
+		if (!S_ISDIR(dir_dentry_p->d_inode->i_mode)) {	/* no dir! We have a real prob here! */
+			rsbac_printk(KERN_WARNING "lookup_aci_path_dentry(): supposed /%s dir on dev %02u:%02u is no dir!\n",
+				     RSBAC_ACI_PATH,
+				     MAJOR(vfsmount_p->mnt_sb->s_dev),
+				     MINOR(vfsmount_p->mnt_sb->s_dev));
+			err = -RSBAC_EACCESS;
+			goto out_dir_dput;
+		}
+	}
+#ifdef CONFIG_RSBAC_DEBUG
+	if (rsbac_debug_ds) {
+		spin_lock(&dir_dentry_p->d_lock);
+		rsbac_pr_debug(ds, "dir_dentry_p->d_lockref.count is %i!\n",
+			       dir_dentry_p->d_lockref.count);
+		spin_unlock(&dir_dentry_p->d_lock);
+		spin_lock(&vfsmount_p->mnt_sb->s_root->d_lock);
+		rsbac_pr_debug(ds, "vfsmount_p->mnt_sb->s_root->d_lockref.count is now %i!\n",
+			       vfsmount_p->mnt_sb->s_root->d_lockref.count);
+		spin_unlock(&vfsmount_p->mnt_sb->s_root->d_lock);
+	}
+#endif
+	/* we want to keep dir_dentry_p in device_item */
+	/* dput must be done in remove_device_item! */
+	*dir_dentry_pp = dir_dentry_p;
+
+	/* Must lock and relookup device_p to cache result */
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(kdev, hash);
+	if (device_p && !device_p->rsbac_dir_dentry_p) {
+		device_p->rsbac_dir_dentry_p = dir_dentry_p;
+		device_p->rsbac_dir_inode = dir_dentry_p->d_inode->i_ino;
+	}
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+
+      out:
+	return err;
+
+      out_dir_dput:
+	dput(dir_dentry_p);
+	goto out;
+}
+
+/************************************************************************** */
+/* The lookup functions return NULL, if the item is not found, and a        */
+/* pointer to the item otherwise.                                           */
+
+/* First, a lookup for the device list item                                 */
+
+static struct rsbac_device_list_item_t *lookup_device(kdev_t kdev, u_int hash)
+{
+	struct rsbac_device_list_head_t *head_p = srcu_dereference(device_head_p[hash], &device_list_srcu[hash]);
+	struct rsbac_device_list_item_t *curr = srcu_dereference(head_p->curr, &device_list_srcu[hash]);
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!(curr && (MAJOR(curr->id) == MAJOR(kdev))
+	     && (MINOR(curr->id) == MINOR(kdev))))
+	{
+		curr = srcu_dereference(head_p->head, &device_list_srcu[hash]);
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = srcu_dereference(curr->next, &device_list_srcu[hash]);
+		}
+		if (curr)
+			device_head_p[hash]->curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_device_list_item_t *lookup_device_locked(kdev_t kdev, u_int hash)
+{
+	struct rsbac_device_list_item_t *curr = device_head_p[hash]->curr;
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!(curr && (MAJOR(curr->id) == MAJOR(kdev))
+	     && (MINOR(curr->id) == MINOR(kdev))))
+	{
+		curr = device_head_p[hash]->head;
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = curr->next;
+		}
+		if (curr)
+			device_head_p[hash]->curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static int dev_compare(void *desc1, void *desc2)
+{
+	int result;
+	struct rsbac_dev_desc_t *i_desc1 = desc1;
+	struct rsbac_dev_desc_t *i_desc2 = desc2;
+
+	result = memcmp(&i_desc1->type,
+			&i_desc2->type, sizeof(i_desc1->type));
+	if (result)
+		return result;
+	result = memcmp(&i_desc1->major,
+			&i_desc2->major, sizeof(i_desc1->major));
+	if (result)
+		return result;
+	return memcmp(&i_desc1->minor,
+		      &i_desc2->minor, sizeof(i_desc1->minor));
+}
+
+#ifdef CONFIG_RSBAC_RC
+static int dev_major_compare(void *desc1, void *desc2)
+{
+	int result;
+	struct rsbac_dev_desc_t *i_desc1 = desc1;
+	struct rsbac_dev_desc_t *i_desc2 = desc2;
+
+	result = memcmp(&i_desc1->type,
+			&i_desc2->type, sizeof(i_desc1->type));
+	if (result)
+		return result;
+	return memcmp(&i_desc1->major,
+		      &i_desc2->major, sizeof(i_desc1->major));
+}
+#endif
+
+static int ipc_compare(void *desc1, void *desc2)
+{
+	int result;
+	struct rsbac_ipc_t *i_desc1 = desc1;
+	struct rsbac_ipc_t *i_desc2 = desc2;
+
+	result = memcmp(&i_desc1->type,
+			&i_desc2->type, sizeof(i_desc1->type));
+	if (result)
+		return result;
+	else
+		return memcmp(&i_desc1->id.id_nr,
+			      &i_desc2->id.id_nr,
+			      sizeof(i_desc1->id.id_nr));
+}
+
+#ifdef CONFIG_RSBAC_NET_DEV
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG) || defined(CONFIG_RSBAC_RC)
+static int netdev_compare(void *desc1, void *desc2)
+{
+	return strncmp(desc1, desc2, RSBAC_IFNAMSIZ);
+}
+#endif
+#endif
+
+/************************************************************************** */
+/* Convert functions                                                        */
+
+static int gen_fd_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_gen_fd_aci_t *new_aci = new_data;
+	struct rsbac_gen_fd_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->log_array_low = old_aci->log_array_low;
+	new_aci->log_array_high = old_aci->log_array_high;
+	new_aci->log_program_based = old_aci->log_program_based;
+	new_aci->symlink_add_remote_ip = old_aci->symlink_add_remote_ip;
+	new_aci->symlink_add_uid = old_aci->symlink_add_uid;
+	new_aci->symlink_add_mac_level = old_aci->symlink_add_mac_level;
+	new_aci->symlink_add_rc_role = old_aci->symlink_add_rc_role;
+	new_aci->linux_dac_disable = old_aci->linux_dac_disable;
+	new_aci->fake_root_uid = old_aci->fake_root_uid;
+	new_aci->auid_exempt = old_aci->auid_exempt;
+	new_aci->vset = RSBAC_UM_VIRTUAL_KEEP;
+	return 0;
+}
+
+static int gen_fd_old_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_gen_fd_aci_t *new_aci = new_data;
+	struct rsbac_gen_fd_old_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->log_array_low = old_aci->log_array_low;
+	new_aci->log_array_high = old_aci->log_array_high;
+	new_aci->log_program_based = old_aci->log_program_based;
+	new_aci->symlink_add_remote_ip = 0;
+	new_aci->symlink_add_uid = old_aci->symlink_add_uid;
+	new_aci->symlink_add_mac_level = old_aci->symlink_add_mac_level;
+	new_aci->symlink_add_rc_role = old_aci->symlink_add_rc_role;
+	new_aci->linux_dac_disable = old_aci->linux_dac_disable;
+	new_aci->fake_root_uid = old_aci->fake_root_uid;
+	new_aci->auid_exempt = old_aci->auid_exempt;
+	new_aci->vset = RSBAC_UM_VIRTUAL_KEEP;
+	return 0;
+}
+
+static rsbac_list_conv_function_t *gen_fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_GEN_FD_OLD_ACI_VERSION:
+		return gen_fd_conv;
+	case RSBAC_GEN_FD_OLD_OLD_ACI_VERSION:
+		return gen_fd_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int gen_dev_conv(void *old_desc,
+			void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_dev_desc_t *new = new_desc;
+	struct rsbac_dev_t *old = old_desc;
+
+	memcpy(new_data, old_data, sizeof(struct rsbac_gen_dev_aci_t));
+	new->type = old->type;
+	new->major = RSBAC_MAJOR(old->id);
+	new->minor = RSBAC_MINOR(old->id);
+	return 0;
+}
+
+static rsbac_list_conv_function_t *gen_dev_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_GEN_DEV_OLD_ACI_VERSION:
+		return gen_dev_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int gen_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(struct rsbac_gen_user_aci_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *gen_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_GEN_USER_OLD_ACI_VERSION:
+		return gen_user_conv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_MAC
+static int mac_old_fd_conv(void *old_desc,
+			   void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_mac_fd_aci_t *new_aci = new_data;
+	struct rsbac_mac_fd_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->sec_level = old_aci->sec_level;
+	new_aci->mac_categories = old_aci->mac_categories;
+	new_aci->mac_auto = old_aci->mac_auto;
+	new_aci->mac_prop_trusted = old_aci->mac_prop_trusted;
+	new_aci->mac_file_flags = old_aci->mac_file_flags;
+	return 0;
+}
+
+static int mac_old_old_fd_conv(void *old_desc,
+			       void *old_data,
+			       void *new_desc, void *new_data)
+{
+	struct rsbac_mac_fd_aci_t *new_aci = new_data;
+	struct rsbac_mac_fd_old_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->sec_level = old_aci->sec_level;
+	new_aci->mac_categories = old_aci->mac_categories;
+	new_aci->mac_auto = old_aci->mac_auto;
+	new_aci->mac_prop_trusted = FALSE;
+	if (old_aci->mac_shared)
+		new_aci->mac_file_flags = MAC_write_up;
+	else
+		new_aci->mac_file_flags = 0;
+	return 0;
+}
+
+static int mac_old_old_old_fd_conv(void *old_desc,
+				   void *old_data,
+				   void *new_desc, void *new_data)
+{
+	struct rsbac_mac_fd_aci_t *new_aci = new_data;
+	struct rsbac_mac_fd_old_old_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->sec_level = old_aci->sec_level;
+	new_aci->mac_categories = old_aci->mac_categories;
+	new_aci->mac_auto = old_aci->mac_auto;
+	new_aci->mac_prop_trusted = FALSE;
+	new_aci->mac_file_flags = 0;
+	return 0;
+}
+
+static rsbac_list_conv_function_t *mac_fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_MAC_FD_OLD_ACI_VERSION:
+		return mac_old_fd_conv;
+	case RSBAC_MAC_FD_OLD_OLD_ACI_VERSION:
+		return mac_old_old_fd_conv;
+	case RSBAC_MAC_FD_OLD_OLD_OLD_ACI_VERSION:
+		return mac_old_old_old_fd_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int mac_dev_conv(void *old_desc,
+			void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_dev_desc_t *new = new_desc;
+	struct rsbac_dev_t *old = old_desc;
+
+	memcpy(new_data, old_data, sizeof(struct rsbac_mac_dev_aci_t));
+	new->type = old->type;
+	new->major = RSBAC_MAJOR(old->id);
+	new->minor = RSBAC_MINOR(old->id);
+	return 0;
+}
+
+static rsbac_list_conv_function_t *mac_dev_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_MAC_DEV_OLD_ACI_VERSION:
+		return mac_dev_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int mac_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(struct rsbac_mac_user_aci_t));
+	return 0;
+}
+
+static int mac_old_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	struct rsbac_mac_user_aci_t *new_aci = new_data;
+	struct rsbac_mac_user_old_aci_t *old_aci = old_data;
+
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	new_aci->security_level = old_aci->access_appr;
+	new_aci->initial_security_level = old_aci->access_appr;
+	new_aci->min_security_level = old_aci->min_access_appr;
+	new_aci->mac_categories = old_aci->mac_categories;
+	new_aci->mac_initial_categories = old_aci->mac_categories;
+	new_aci->mac_min_categories = old_aci->mac_min_categories;
+	new_aci->system_role = old_aci->system_role;
+	new_aci->mac_user_flags = RSBAC_MAC_DEF_U_FLAGS;
+	if (old_aci->mac_allow_auto)
+		new_aci->mac_user_flags |= MAC_allow_auto;
+	return 0;
+}
+
+static int mac_old_old_user_conv(void *old_desc,
+				 void *old_data,
+				 void *new_desc, void *new_data)
+{
+	struct rsbac_mac_user_aci_t *new_aci = new_data;
+	struct rsbac_mac_user_old_old_aci_t *old_aci = old_data;
+
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	new_aci->security_level = old_aci->access_appr;
+	new_aci->initial_security_level = old_aci->access_appr;
+	new_aci->min_security_level = old_aci->min_access_appr;
+	new_aci->mac_categories = old_aci->mac_categories;
+	new_aci->mac_initial_categories = old_aci->mac_categories;
+	new_aci->mac_min_categories = old_aci->mac_min_categories;
+	new_aci->system_role = old_aci->system_role;
+	new_aci->mac_user_flags = RSBAC_MAC_DEF_U_FLAGS;
+	return 0;
+}
+
+static int mac_old_old_old_user_conv(void *old_desc,
+				     void *old_data,
+				     void *new_desc, void *new_data)
+{
+	struct rsbac_mac_user_aci_t *new_aci = new_data;
+	struct rsbac_mac_user_old_old_old_aci_t *old_aci = old_data;
+
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	new_aci->security_level = old_aci->access_appr;
+	new_aci->initial_security_level = old_aci->access_appr;
+	new_aci->min_security_level = SL_unclassified;
+	new_aci->mac_categories = old_aci->mac_categories;
+	new_aci->mac_initial_categories = old_aci->mac_categories;
+	new_aci->mac_min_categories = RSBAC_MAC_MIN_CAT_VECTOR;
+	new_aci->system_role = old_aci->system_role;
+	new_aci->mac_user_flags = RSBAC_MAC_DEF_U_FLAGS;
+	return 0;
+}
+
+static rsbac_list_conv_function_t *mac_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_MAC_USER_OLD_ACI_VERSION:
+		return mac_user_conv;
+	case RSBAC_MAC_USER_OLD_OLD_ACI_VERSION:
+		return mac_old_user_conv;
+	case RSBAC_MAC_USER_OLD_OLD_OLD_ACI_VERSION:
+		return mac_old_old_user_conv;
+	case RSBAC_MAC_USER_OLD_OLD_OLD_OLD_ACI_VERSION:
+		return mac_old_old_old_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_DAZ
+static int daz_old_fd_conv(
+	void * old_desc,
+	void * old_data,
+	void * new_desc,
+	void * new_data)
+  {
+    struct rsbac_daz_fd_aci_t     * new_aci = new_data;
+    struct rsbac_daz_fd_old_aci_t * old_aci = old_data;
+
+    memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+    new_aci->daz_scanner = old_aci->daz_scanner;
+    new_aci->daz_do_scan = DEFAULT_DAZ_FD_DO_SCAN;
+    return 0;
+  }
+
+static rsbac_list_conv_function_t * daz_fd_get_conv(rsbac_version_t old_version)
+  {
+    switch(old_version)
+      {
+        case RSBAC_DAZ_FD_OLD_ACI_VERSION:
+          return daz_old_fd_conv;
+        default:
+          return NULL;
+      }
+  }
+
+static int daz_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(rsbac_system_role_int_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *daz_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_DAZ_USER_OLD_ACI_VERSION:
+		return daz_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_FF
+static int ff_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(rsbac_system_role_int_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *ff_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_FF_USER_OLD_ACI_VERSION:
+		return ff_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_RC
+static int rc_dev_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_dev_desc_t *new = new_desc;
+	struct rsbac_dev_t *old = old_desc;
+
+	memcpy(new_data, old_data, sizeof(rsbac_rc_type_id_t));
+	new->type = old->type;
+	new->major = RSBAC_MAJOR(old->id);
+	new->minor = RSBAC_MINOR(old->id);
+	return 0;
+}
+
+static rsbac_list_conv_function_t *rc_dev_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_RC_DEV_OLD_ACI_VERSION:
+		return rc_dev_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int rc_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(struct rsbac_rc_user_aci_t));
+	return 0;
+}
+
+static int rc_user_old_conv(void *old_desc,
+			void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_rc_user_aci_t *new_aci = new_data;
+	rsbac_rc_role_id_t *old_aci = old_data;
+
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	new_aci->rc_role = *old_aci;
+	new_aci->rc_type = RSBAC_RC_GENERAL_TYPE;
+	return 0;
+}
+
+static rsbac_list_conv_function_t *rc_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_RC_USER_OLD_ACI_VERSION:
+		return rc_user_conv;
+	case RSBAC_RC_USER_OLD_OLD_ACI_VERSION:
+		return rc_user_old_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH
+static int auth_old_fd_conv(void *old_desc,
+			    void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_auth_fd_aci_t *new_aci = new_data;
+	struct rsbac_auth_fd_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->auth_may_setuid = old_aci->auth_may_setuid;
+	new_aci->auth_may_set_cap = old_aci->auth_may_set_cap;
+	new_aci->auth_learn = FALSE;
+	return 0;
+}
+
+static rsbac_list_conv_function_t *auth_fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_AUTH_FD_OLD_ACI_VERSION:
+		return auth_old_fd_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int auth_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(rsbac_system_role_int_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *auth_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_AUTH_USER_OLD_ACI_VERSION:
+		return auth_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_CAP
+static int cap_old_fd_conv(void *old_desc, void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_cap_fd_aci_t *new_aci = new_data;
+	struct rsbac_cap_fd_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->min_caps.cap[0] = old_aci->min_caps;
+	new_aci->max_caps.cap[0] = old_aci->max_caps;
+	new_aci->min_caps.cap[1] = (__u32) 0;
+	new_aci->max_caps.cap[1] = (__u32) -1;
+	new_aci->cap_ld_env = old_aci->cap_ld_env;
+	return 0;
+}
+
+static int cap_old_old_fd_conv(void *old_desc, void *old_data, void *new_desc, void *new_data)
+{
+        struct rsbac_cap_fd_aci_t *new_aci = new_data;
+        struct rsbac_cap_fd_old_old_aci_t *old_aci = old_data;
+
+        memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	new_aci->min_caps.cap[0] = old_aci->min_caps;
+	new_aci->max_caps.cap[0] = old_aci->max_caps;
+	new_aci->min_caps.cap[1] = (__u32) 0;
+	new_aci->max_caps.cap[1] = (__u32) -1;
+        new_aci->cap_ld_env = LD_inherit;
+        return 0;
+}
+
+static rsbac_list_conv_function_t *cap_fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+		case RSBAC_CAP_FD_OLD_OLD_ACI_VERSION:
+			return cap_old_old_fd_conv;
+		case RSBAC_CAP_FD_OLD_ACI_VERSION:
+			return cap_old_fd_conv;
+		default:
+			return NULL;
+	}
+}
+
+static int cap_old_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	struct rsbac_cap_user_aci_t *new_aci = new_data;
+	struct rsbac_cap_user_old_aci_t *old_aci = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_uid_t));
+	new_aci->cap_role = old_aci->cap_role;
+	new_aci->min_caps.cap[0] = old_aci->min_caps;
+	new_aci->max_caps.cap[0] = old_aci->max_caps;
+	new_aci->min_caps.cap[1] = (__u32) 0;
+	new_aci->max_caps.cap[1] = (__u32) -1;
+	new_aci->cap_ld_env = old_aci->cap_ld_env;
+	return 0;
+}
+
+static int cap_old_old_user_conv(void *old_desc, void *old_data, void *new_desc, void *new_data)
+{
+        rsbac_uid_t *new_user = new_desc;
+        rsbac_old_uid_t *old_user = old_desc;
+        struct rsbac_cap_user_aci_t *new_aci = new_data;
+        struct rsbac_cap_user_old_old_aci_t *old_aci = old_data;
+
+        *new_user = RSBAC_GEN_UID(0,*old_user);
+	new_aci->cap_role = old_aci->cap_role;
+	new_aci->min_caps.cap[0] = old_aci->min_caps;
+	new_aci->max_caps.cap[0] = old_aci->max_caps;
+	new_aci->min_caps.cap[1] = (__u32) 0;
+	new_aci->max_caps.cap[1] = (__u32) -1;
+	new_aci->cap_ld_env = old_aci->cap_ld_env;
+        return 0;
+}
+
+static int cap_old_old_old_user_conv(void *old_desc, void *old_data, void *new_desc, void *new_data)
+{
+        rsbac_uid_t *new_user = new_desc;
+        rsbac_old_uid_t *old_user = old_desc;
+        struct rsbac_cap_user_aci_t *new_aci = new_data;
+        struct rsbac_cap_user_old_old_aci_t *old_aci = old_data;
+
+        *new_user = RSBAC_GEN_UID(0,*old_user);
+	new_aci->cap_role = old_aci->cap_role;
+	new_aci->min_caps.cap[0] = old_aci->min_caps;
+	new_aci->max_caps.cap[0] = old_aci->max_caps;
+	new_aci->min_caps.cap[1] = (__u32) 0;
+	new_aci->max_caps.cap[1] = (__u32) -1;
+	new_aci->cap_ld_env = LD_allow;
+        return 0;
+}
+
+static rsbac_list_conv_function_t *cap_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+		case RSBAC_CAP_USER_OLD_ACI_VERSION:
+			return cap_old_user_conv;
+		case RSBAC_CAP_USER_OLD_OLD_ACI_VERSION:
+			return cap_old_old_user_conv;
+		case RSBAC_CAP_USER_OLD_OLD_OLD_ACI_VERSION:
+			return cap_old_old_old_user_conv;
+		default:
+			return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_JAIL
+static int jail_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(rsbac_system_role_int_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *jail_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_JAIL_USER_OLD_ACI_VERSION:
+		return jail_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_PAX
+static int pax_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(rsbac_system_role_int_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *pax_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_PAX_USER_OLD_ACI_VERSION:
+		return pax_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_RES
+static int res_user_conv(void *old_desc,
+			     void *old_data,
+			     void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	memcpy(new_data, old_data, sizeof(struct rsbac_res_user_aci_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *res_user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_RES_USER_OLD_ACI_VERSION:
+		return res_user_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+static int net_temp_old_conv(void *old_desc, void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_net_temp_data_t *new_aci = new_data;
+	struct rsbac_net_temp_old_data_t *old_aci = old_data;
+
+        memcpy(new_desc, old_desc, sizeof(rsbac_net_temp_id_t));
+	new_aci->address_family = old_aci->address_family;
+	new_aci->type = old_aci->type;
+	new_aci->protocol = old_aci->protocol;
+	memcpy(new_aci->netdev, old_aci->netdev, sizeof(rsbac_netdev_id_t));
+	memcpy(new_aci->name, old_aci->name, sizeof(new_aci->name));
+	switch(new_aci->address_family) {
+		case AF_INET:
+			new_aci->address.inet.nr_addr = 1;
+			new_aci->address.inet.addr[0] = *((__u32 *) old_aci->address);
+			new_aci->address.inet.valid_bits[0] = old_aci->valid_len;
+			if((old_aci->min_port == 0) && (old_aci->max_port == RSBAC_NET_MAX_PORT))
+				new_aci->ports.nr_ports = 0;
+			else {
+				new_aci->ports.nr_ports = 1;
+				new_aci->ports.ports[0].min = old_aci->min_port;
+				new_aci->ports.ports[0].max = old_aci->max_port;
+			}
+			break;
+		default:
+			memcpy(new_aci->address.other.addr, old_aci->address, sizeof(old_aci->address));
+			new_aci->address.other.valid_len = old_aci->valid_len;
+			new_aci->ports.nr_ports = 0;
+			break;
+	}
+	return 0;
+}
+
+
+static rsbac_list_conv_function_t *net_temp_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+		case RSBAC_NET_TEMP_OLD_VERSION:
+			return net_temp_old_conv;
+		default:
+			return NULL;
+	}
+}
+#endif
+
+/************************************************************************** */
+/* The add_item() functions add an item to the list, set head.curr to it,   */
+/* and return a pointer to the item.                                        */
+/* These functions will NOT check, if there is already an item under the    */
+/* same ID! If this happens, the lookup functions will return the old item! */
+/* All list manipulation must be protected by rw-spinlocks to prevent       */
+/* inconsistency and undefined behaviour in other concurrent functions.     */
+
+/* register_fd_lists() */
+/* register fd lists for device */
+
+static int register_fd_lists(struct rsbac_device_list_item_t *device_p,
+			     kdev_t kdev)
+{
+	char *name;
+	int err = 0;
+	int tmperr;
+	struct rsbac_list_info_t *info_p;
+	u_int tmp_flags;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+	name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+	if (!name)
+		return -RSBAC_ENOMEM;
+	info_p = rsbac_kmalloc(sizeof(*info_p));
+	if (!info_p) {
+		rsbac_kfree(name);
+		return -RSBAC_ENOMEM;
+	}
+	if (rsbac_device_type_writable(device_p)) {
+		tmp_flags = RSBAC_LIST_PERSIST;
+		device_p->persist = TRUE;
+	} else {
+		tmp_flags = 0;
+		device_p->persist = FALSE;
+	}
+
+	/* register general lists */
+	{
+		info_p->version = RSBAC_GEN_FD_ACI_VERSION;
+		info_p->key = RSBAC_GEN_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_gen_fd_aci_t);
+		info_p->max_age = 0;
+		gen_nr_fd_hash_bits = RSBAC_GEN_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.gen,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     gen_fd_get_conv,
+					     &def_gen_fd_aci,
+					     RSBAC_GEN_FD_NAME,
+					     kdev,
+					     gen_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_GEN_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering general list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_GEN_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		/* register MAC lists */
+		info_p->version = RSBAC_MAC_FD_ACI_VERSION;
+		info_p->key = RSBAC_MAC_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_mac_fd_aci_t);
+		info_p->max_age = 0;
+		mac_nr_fd_hash_bits = RSBAC_MAC_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.mac,
+					     info_p,
+					     tmp_flags | RSBAC_LIST_OWN_SLAB |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     mac_fd_get_conv,
+					     &def_mac_fd_aci,
+					     RSBAC_MAC_FD_NAME,
+					     kdev,
+					     mac_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_MAC_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering MAC list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_MAC_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+	{
+		struct rsbac_daz_fd_aci_t def_daz_fd_aci =
+		    DEFAULT_DAZ_FD_ACI;
+		/* register DAZ lists */
+		info_p->version = RSBAC_DAZ_FD_ACI_VERSION;
+		info_p->key = RSBAC_DAZ_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_daz_fd_aci_t);
+		info_p->max_age = 0;
+		daz_nr_fd_hash_bits = RSBAC_DAZ_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.daz,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA |
+					     RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     daz_fd_get_conv,
+					     &def_daz_fd_aci,
+					     RSBAC_DAZ_FD_NAME, kdev,
+					     daz_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_DAZ_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering DAZ list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_DAZ_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	{
+		rsbac_daz_scanned_t def_daz_scanned_fd_aci =
+		    DEFAULT_DAZ_FD_SCANNED;
+
+		info_p->version = RSBAC_DAZ_SCANNED_FD_ACI_VERSION;
+		info_p->key = RSBAC_DAZ_FD_ACI_KEY;
+#ifdef CONFIG_RSBAC_DAZ_PERSIST
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+#else
+		info_p->desc_size = sizeof(rsbac_inode_nr_t);
+#endif
+		info_p->data_size = sizeof(rsbac_daz_scanned_t);
+		info_p->max_age = 0;
+		daz_scanned_nr_fd_hash_bits = RSBAC_DAZ_SCANNED_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.dazs,
+					     info_p,
+#ifdef CONFIG_RSBAC_DAZ_PERSIST
+					     tmp_flags |
+#endif
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB |
+					     RSBAC_LIST_AUTO_HASH_RESIZE |
+					     RSBAC_LIST_NO_MAX,
+					     NULL,
+					     NULL,
+					     &def_daz_scanned_fd_aci,
+					     RSBAC_DAZ_SCANNED_FD_NAME, kdev,
+					     daz_scanned_nr_fd_hash_bits,
+#ifdef CONFIG_RSBAC_DAZ_PERSIST
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+#else
+					     rsbac_list_hash_fd,
+#endif
+					     RSBAC_DAZ_SCANNED_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering DAZ scanned list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_DAZ_SCANNED_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+	{
+		rsbac_ff_flags_t def_ff_fd_aci = RSBAC_FF_DEF;
+
+		info_p->version = RSBAC_FF_FD_ACI_VERSION;
+		info_p->key = RSBAC_FF_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size = sizeof(rsbac_ff_flags_t);
+		info_p->max_age = 0;
+		ff_nr_fd_hash_bits = RSBAC_FF_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.ff,
+					     info_p,
+					     tmp_flags | RSBAC_LIST_OWN_SLAB |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     NULL, &def_ff_fd_aci,
+					     RSBAC_FF_FD_NAME, kdev,
+					     ff_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_FF_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering FF list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_FF_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	{
+		info_p->version = RSBAC_RC_FD_ACI_VERSION;
+		info_p->key = RSBAC_RC_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_rc_fd_aci_t);
+		info_p->max_age = 0;
+		rc_nr_fd_hash_bits = RSBAC_RC_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.rc,
+					     info_p,
+					     tmp_flags | RSBAC_LIST_OWN_SLAB |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     NULL, &def_rc_fd_aci,
+					     RSBAC_RC_FD_NAME, kdev,
+					     rc_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_RC_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering RC list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_RC_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+	{
+		struct rsbac_auth_fd_aci_t def_auth_fd_aci =
+		    DEFAULT_AUTH_FD_ACI;
+
+		info_p->version = RSBAC_AUTH_FD_ACI_VERSION;
+		info_p->key = RSBAC_AUTH_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_auth_fd_aci_t);
+		info_p->max_age = 0;
+		auth_nr_fd_hash_bits = RSBAC_AUTH_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.auth,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     auth_fd_get_conv,
+					     &def_auth_fd_aci,
+					     RSBAC_AUTH_FD_NAME, kdev,
+					     auth_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_AUTH_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering AUTH list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_AUTH_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+	{
+		struct rsbac_cap_fd_aci_t def_cap_fd_aci = DEFAULT_CAP_FD_ACI;
+
+		info_p->version = RSBAC_CAP_FD_ACI_VERSION;
+		info_p->key = RSBAC_CAP_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_cap_fd_aci_t);
+		info_p->max_age = 0;
+		cap_nr_fd_hash_bits = RSBAC_CAP_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.cap,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     cap_fd_get_conv, 
+					     &def_cap_fd_aci,
+					     RSBAC_CAP_FD_NAME, kdev,
+					     cap_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_CAP_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering CAP list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_CAP_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+	{
+		rsbac_pax_flags_t def_pax_fd_aci;
+
+#ifdef CONFIG_RSBAC_PAX_DEFAULT
+		def_pax_fd_aci = 0;
+#ifdef CONFIG_RSBAC_PAX_PAGEEXEC
+		def_pax_fd_aci |= PF_PAX_PAGEEXEC;
+#endif
+#ifdef CONFIG_RSBAC_PAX_EMUTRAMP
+		def_pax_fd_aci |= PF_PAX_EMUTRAMP;
+#endif
+#ifdef CONFIG_RSBAC_PAX_MPROTECT
+		def_pax_fd_aci |= PF_PAX_MPROTECT;
+#endif
+#ifdef CONFIG_RSBAC_PAX_RANDMMAP
+		def_pax_fd_aci |= PF_PAX_RANDMMAP;
+#endif
+#ifdef CONFIG_RSBAC_PAX_RANDEXEC
+		def_pax_fd_aci |= PF_PAX_RANDEXEC;
+#endif
+#ifdef CONFIG_RSBAC_PAX_SEGMEXEC
+		def_pax_fd_aci |= PF_PAX_SEGMEXEC;
+#endif
+
+#else
+		def_pax_fd_aci = RSBAC_PAX_DEF_FLAGS;
+#endif
+
+		info_p->version = RSBAC_PAX_FD_ACI_VERSION;
+		info_p->key = RSBAC_PAX_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size = sizeof(rsbac_pax_flags_t);
+		info_p->max_age = 0;
+		pax_nr_fd_hash_bits = RSBAC_PAX_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.pax,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     NULL, &def_pax_fd_aci,
+					     RSBAC_PAX_FD_NAME, kdev,
+					     pax_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_PAX_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering PAX list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_PAX_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+	{
+		info_p->version = RSBAC_RES_FD_ACI_VERSION;
+		info_p->key = RSBAC_RES_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_res_fd_aci_t);
+		info_p->max_age = 0;
+		res_nr_fd_hash_bits = RSBAC_RES_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.res,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     NULL, &def_res_fd_aci,
+					     RSBAC_RES_FD_NAME, kdev,
+					     res_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     RSBAC_RES_OLD_FD_NAME);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering RES list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_RES_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+	{
+		struct rsbac_udf_fd_aci_t def_udf_fd_aci =
+		    DEFAULT_UDF_FD_ACI;
+		/* register UDF lists */
+		info_p->version = RSBAC_UDF_FD_ACI_VERSION;
+		info_p->key = RSBAC_UDF_FD_ACI_KEY;
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+		info_p->data_size =
+		    sizeof(struct rsbac_udf_fd_aci_t);
+		info_p->max_age = 0;
+		udf_nr_fd_hash_bits = RSBAC_UDF_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.udf,
+					     info_p,
+					     tmp_flags |
+					     RSBAC_LIST_DEF_DATA |
+					     RSBAC_LIST_AUTO_HASH_RESIZE,
+					     NULL,
+					     NULL,
+					     &def_udf_fd_aci,
+					     RSBAC_UDF_FD_NAME, kdev,
+					     udf_nr_fd_hash_bits,
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+					     NULL);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering UDF list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_UDF_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	{
+		rsbac_udf_checked_t def_udf_checked_fd_aci =
+		    DEFAULT_UDF_FD_CHECKED;
+
+		info_p->version = RSBAC_UDF_CHECKED_FD_ACI_VERSION;
+		info_p->key = RSBAC_UDF_FD_ACI_KEY;
+#ifdef CONFIG_RSBAC_UDF_PERSIST
+		info_p->desc_size = tmp_flags ? sizeof(rsbac_old_inode_nr_t) : sizeof(rsbac_inode_nr_t);
+#else
+		info_p->desc_size = sizeof(rsbac_inode_nr_t);
+#endif
+		info_p->data_size = sizeof(rsbac_udf_checked_t);
+		info_p->max_age = 0;
+		udf_checked_nr_fd_hash_bits = RSBAC_UDF_CHECKED_NR_FD_LIST_HASH_BITS;
+		tmperr = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					     &device_p->handles.udfc,
+					     info_p,
+#ifdef CONFIG_RSBAC_UDF_PERSIST
+					     tmp_flags |
+#endif
+					     RSBAC_LIST_DEF_DATA | (RSBAC_MAJOR(kdev) ? RSBAC_LIST_OWN_SLAB : 0) |
+					     RSBAC_LIST_AUTO_HASH_RESIZE |
+					     RSBAC_LIST_NO_MAX,
+					     NULL,
+					     NULL,
+					     &def_udf_checked_fd_aci,
+					     RSBAC_UDF_CHECKED_FD_NAME, kdev,
+					     udf_checked_nr_fd_hash_bits,
+#ifdef CONFIG_RSBAC_UDF_PERSIST
+					     tmp_flags ? rsbac_list_hash_old_fd : rsbac_list_hash_fd,
+#else
+					     rsbac_list_hash_fd,
+#endif
+					     NULL);
+		if (tmperr) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "register_fd_lists(): registering UDF checked list %s for device %02u:%02u failed with error %s!\n",
+					     RSBAC_UDF_CHECKED_FD_NAME,
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     get_error_name(tmp,
+							    tmperr));
+				rsbac_kfree(tmp);
+			}
+			err = tmperr;
+		}
+	}
+#endif
+#endif
+
+	rsbac_kfree(name);
+	rsbac_kfree(info_p);
+	return err;
+}
+
+/* aci_detach_fd_lists() */
+/* detach from fd lists for device */
+
+static int aci_detach_fd_lists(struct rsbac_device_list_item_t *device_p)
+{
+	int err = 0;
+	int tmperr;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	/* detach all general lists */
+	tmperr = rsbac_list_detach(&device_p->handles.gen,
+					   RSBAC_GEN_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from general list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_GEN_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+
+#if defined(CONFIG_RSBAC_MAC)
+	/* detach all MAC lists */
+	tmperr = rsbac_list_detach(&device_p->handles.mac,
+				   RSBAC_MAC_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from MAC list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_MAC_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+	/* detach all DAZ lists */
+	tmperr = rsbac_list_detach(&device_p->handles.daz,
+				   RSBAC_DAZ_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from DAZ list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_DAZ_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	/* detach all DAZ scanned lists */
+	tmperr = rsbac_list_detach(&device_p->handles.dazs,
+				      RSBAC_DAZ_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from DAZ scanned list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_DAZ_SCANNED_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+	/* detach all FF lists */
+	tmperr = rsbac_list_detach(&device_p->handles.ff,
+				   RSBAC_FF_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from FF list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_FF_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	/* detach all RC lists */
+	tmperr = rsbac_list_detach(&device_p->handles.rc,
+				   RSBAC_RC_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from RC list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_RC_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+	/* detach all AUTH lists */
+	tmperr = rsbac_list_detach(&device_p->handles.auth,
+			      RSBAC_AUTH_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from AUTH list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+	/* detach all CAP lists */
+	tmperr = rsbac_list_detach(&device_p->handles.cap,
+				   RSBAC_CAP_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from CAP list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_CAP_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+	/* detach all PAX lists */
+	tmperr = rsbac_list_detach(&device_p->handles.pax,
+				   RSBAC_PAX_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from PAX list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_PAX_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+	/* detach all RES lists */
+	tmperr = rsbac_list_detach(&device_p->handles.res,
+				   RSBAC_RES_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from RES list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_RES_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+	/* detach all UDF lists */
+	tmperr = rsbac_list_detach(&device_p->handles.udf,
+				   RSBAC_UDF_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from UDF list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_UDF_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	/* detach all UDF checked lists */
+	tmperr = rsbac_list_detach(&device_p->handles.udfc,
+				      RSBAC_UDF_FD_ACI_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "detach_fd_lists(): detaching from UDF checked list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_UDF_CHECKED_FD_NAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+#endif
+
+	return err;
+}
+
+static void registration_error(int err, char *listname)
+{
+	if (err < 0) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): Registering %s list failed with error %s\n",
+				     listname, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+}
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+static int register_fd_cache_lists(struct rsbac_device_list_item_t *device_p)
+{
+	int err = 0;
+	struct rsbac_list_lol_info_t *list_info_p;
+	char * tmp;
+
+	if (device_p->fd_cache_handle[SW_GEN]) {
+		rsbac_printk(KERN_WARNING "register_fd_cache_lists(): GEN list for device %02u:%02u already registered, refusing device!\n",
+			RSBAC_MAJOR(device_p->id),
+			RSBAC_MINOR(device_p->id));
+		return -RSBAC_EINVALIDDEV;
+	}
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+	if (!tmp) {
+		rsbac_kfree(list_info_p);
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(fdcache, "registering FD Cache lists for device %02u:%02u\n",
+			RSBAC_MAJOR(device_p->id),
+			RSBAC_MINOR(device_p->id));
+	list_info_p->version = RSBAC_FD_CACHE_VERSION;
+	list_info_p->key = RSBAC_FD_CACHE_KEY;
+	list_info_p->desc_size = sizeof(rsbac_inode_nr_t);
+	list_info_p->data_size = 0;
+	list_info_p->subdesc_size = sizeof(rsbac_enum_t);
+	list_info_p->subdata_size =
+	    sizeof(union rsbac_attribute_value_cache_t);
+	list_info_p->max_age = 0;
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+	sprintf(tmp, "%sGEN", RSBAC_FD_CACHE_NAME);
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				  &(device_p->fd_cache_handle[SW_GEN]), list_info_p,
+				  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | \
+				    RSBAC_LIST_AUTO_HASH_RESIZE | \
+				    RSBAC_LIST_NO_MAX_WARN,
+				  NULL,
+				  NULL, /* subcompare */
+				  NULL, NULL, /* get_conv */
+				  NULL, NULL, /* def data */
+				  tmp,
+				  device_p->id,
+				  RSBAC_LIST_MIN_MAX_HASH_BITS,
+				  rsbac_list_hash_fd,
+				  NULL);
+	if (err) {
+		char *tmp2;
+
+		tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp2) {
+			rsbac_printk(KERN_WARNING "register_fd_cache_lists(): registering GEN list %s for device %02u:%02u failed with error %s!\n",
+				     tmp,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp2, err));
+			rsbac_kfree(tmp2);
+		}
+	} else
+		rsbac_list_lol_max_items(device_p->fd_cache_handle[SW_GEN],
+			RSBAC_FD_CACHE_KEY,
+			CONFIG_RSBAC_FD_CACHE_MAX_ITEMS, A_none);
+#endif
+
+#if defined(CONFIG_RSBAC_MAC) && defined(CONFIG_RSBAC_MAC_DEF_INHERIT)
+	sprintf(tmp, "%sMAC", RSBAC_FD_CACHE_NAME);
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				  &(device_p->fd_cache_handle[SW_MAC]), list_info_p,
+				  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | \
+				    RSBAC_LIST_AUTO_HASH_RESIZE | \
+				    RSBAC_LIST_NO_MAX_WARN,
+				  NULL,
+				  NULL, /* subcompare */
+				  NULL, NULL, /* get_conv */
+				  NULL, NULL, /* def data */
+				  tmp,
+				  device_p->id,
+				  RSBAC_LIST_MIN_MAX_HASH_BITS,
+				  rsbac_list_hash_fd,
+				  NULL);
+	if (err) {
+		char *tmp2;
+
+		tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp2) {
+			rsbac_printk(KERN_WARNING "register_fd_cache_lists(): registering MAC list %s for device %02u:%02u failed with error %s!\n",
+				     tmp,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp2, err));
+			rsbac_kfree(tmp2);
+		}
+	} else
+		rsbac_list_lol_max_items(device_p->fd_cache_handle[SW_MAC],
+			RSBAC_FD_CACHE_KEY,
+			CONFIG_RSBAC_FD_CACHE_MAX_ITEMS, A_none);
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	sprintf(tmp, "%sFF", RSBAC_FD_CACHE_NAME);
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				  &(device_p->fd_cache_handle[SW_FF]), list_info_p,
+				  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | \
+				    RSBAC_LIST_AUTO_HASH_RESIZE | \
+				    RSBAC_LIST_NO_MAX_WARN,
+				  NULL,
+				  NULL, /* subcompare */
+				  NULL, NULL, /* get_conv */
+				  NULL, NULL, /* def data */
+				  tmp,
+				  device_p->id,
+				  RSBAC_LIST_MIN_MAX_HASH_BITS,
+				  rsbac_list_hash_fd,
+				  NULL);
+	if (err) {
+		char *tmp2;
+
+		tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp2) {
+			rsbac_printk(KERN_WARNING "register_fd_cache_lists(): registering FF list %s for device %02u:%02u failed with error %s!\n",
+				     tmp,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp2, err));
+			rsbac_kfree(tmp2);
+		}
+	} else
+		rsbac_list_lol_max_items(device_p->fd_cache_handle[SW_FF],
+			RSBAC_FD_CACHE_KEY,
+			CONFIG_RSBAC_FD_CACHE_MAX_ITEMS, A_none);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	sprintf(tmp, "%sRC", RSBAC_FD_CACHE_NAME);
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				  &(device_p->fd_cache_handle[SW_RC]), list_info_p,
+				  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | \
+				    RSBAC_LIST_AUTO_HASH_RESIZE | \
+				    RSBAC_LIST_NO_MAX_WARN,
+				  NULL,
+				  NULL, /* subcompare */
+				  NULL, NULL, /* get_conv */
+				  NULL, NULL, /* def data */
+				  tmp,
+				  device_p->id,
+				  RSBAC_LIST_MIN_MAX_HASH_BITS,
+				  rsbac_list_hash_fd,
+				  NULL);
+	if (err) {
+		char *tmp2;
+
+		tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp2) {
+			rsbac_printk(KERN_WARNING "register_fd_cache_lists(): registering RC list %s for device %02u:%02u failed with error %s!\n",
+				     tmp,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp2, err));
+			rsbac_kfree(tmp2);
+		}
+	} else
+		rsbac_list_lol_max_items(device_p->fd_cache_handle[SW_RC],
+			RSBAC_FD_CACHE_KEY,
+			CONFIG_RSBAC_FD_CACHE_MAX_ITEMS, A_none);
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	sprintf(tmp, "%sDAZ", RSBAC_FD_CACHE_NAME);
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				  &(device_p->fd_cache_handle[SW_DAZ]), list_info_p,
+				  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | \
+				    RSBAC_LIST_AUTO_HASH_RESIZE | \
+				    RSBAC_LIST_NO_MAX_WARN,
+				  NULL,
+				  NULL, /* subcompare */
+				  NULL, NULL, /* get_conv */
+				  NULL, NULL, /* def data */
+				  tmp,
+				  device_p->id,
+				  RSBAC_LIST_MIN_MAX_HASH_BITS,
+				  rsbac_list_hash_fd,
+				  NULL);
+	if (err) {
+		char *tmp2;
+
+		tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp2) {
+			rsbac_printk(KERN_WARNING "register_fd_cache_lists(): registering DAZ list %s for device %02u:%02u failed with error %s!\n",
+				     tmp,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp2, err));
+			rsbac_kfree(tmp2);
+		}
+	} else
+		rsbac_list_lol_max_items(device_p->fd_cache_handle[SW_DAZ],
+			RSBAC_FD_CACHE_KEY,
+			CONFIG_RSBAC_FD_CACHE_MAX_ITEMS,
+			A_none);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	sprintf(tmp, "%sUDF", RSBAC_FD_CACHE_NAME);
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				  &(device_p->fd_cache_handle[SW_UDF]), list_info_p,
+				  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | \
+				    RSBAC_LIST_AUTO_HASH_RESIZE | \
+				    RSBAC_LIST_NO_MAX_WARN,
+				  NULL,
+				  NULL, /* subcompare */
+				  NULL, NULL, /* get_conv */
+				  NULL, NULL, /* def data */
+				  tmp,
+				  device_p->id,
+				  RSBAC_LIST_MIN_MAX_HASH_BITS,
+				  rsbac_list_hash_fd,
+				  NULL);
+	if (err) {
+		char *tmp2;
+
+		tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp2) {
+			rsbac_printk(KERN_WARNING "register_fd_cache_lists(): registering UDF list %s for device %02u:%02u failed with error %s!\n",
+				     tmp,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp2, err));
+			rsbac_kfree(tmp2);
+		}
+	} else
+		rsbac_list_lol_max_items(device_p->fd_cache_handle[SW_UDF],
+			RSBAC_FD_CACHE_KEY,
+			CONFIG_RSBAC_FD_CACHE_MAX_ITEMS,
+			A_none);
+#endif
+
+	rsbac_kfree(list_info_p);
+	rsbac_kfree(tmp);
+	return err;
+}
+
+static int unregister_fd_cache_lists(struct rsbac_device_list_item_t *device_p)
+{
+	u_int i;
+	int err;
+
+	rsbac_pr_debug(fdcache, "unregistering FD Cache lists for device %02u:%02u\n",
+			RSBAC_MAJOR(device_p->id),
+			RSBAC_MINOR(device_p->id));
+	for (i = 0; i < SW_NONE; i++) {
+		if (device_p->fd_cache_handle[i]) {
+			err = rsbac_list_lol_detach(&(device_p->fd_cache_handle[i]), RSBAC_FD_CACHE_KEY);
+			device_p->fd_cache_handle[i] = NULL;
+			if (err) {
+				char *tmp2;
+
+				tmp2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+				if (tmp2) {
+					rsbac_printk(KERN_WARNING "unregister_fd_cache_lists(): unregistering list for device %02u:%02u, module %u failed with error %s!\n",
+						     RSBAC_MAJOR(device_p->id),
+						     RSBAC_MINOR(device_p->id),
+						     i,
+						     get_error_name(tmp2, err));
+					rsbac_kfree(tmp2);
+				}
+			}
+		}
+	}
+	return 0;
+}
+#endif
+
+
+/* Create a device item without adding to list. No locking needed. */
+static struct rsbac_device_list_item_t
+*create_device_item(struct vfsmount *vfsmount_p)
+{
+	struct rsbac_device_list_item_t *new_item_p;
+
+	if (!vfsmount_p)
+		return NULL;
+	/* allocate memory for new device, return NULL, if failed */
+	if (!(new_item_p = rsbac_smalloc_clear_unlocked(device_item_slab)))
+		return NULL;
+
+	new_item_p->id = vfsmount_p->mnt_sb->s_dev;
+	new_item_p->vfsmount_p = vfsmount_p;
+	new_item_p->mount_count = 1;
+	new_item_p->persist = FALSE;
+
+	return new_item_p;
+}
+
+/* Add an existing device item to list. Locking needed. */
+static struct rsbac_device_list_item_t
+*add_device_item(struct rsbac_device_list_item_t *device_p)
+{
+	struct rsbac_device_list_head_t * new_p;
+	struct rsbac_device_list_head_t * old_p;
+	u_int hash;
+
+	if (!device_p)
+		return NULL;
+
+	hash = device_hash(device_p->id);
+	spin_lock(&device_list_locks[hash]);
+	old_p = device_head_p[hash];
+	new_p = rsbac_kmalloc(sizeof(*new_p));
+	*new_p = *old_p;
+	/* add new device to device list */
+	if (!new_p->head) {	/* first device */
+		new_p->head = device_p;
+		new_p->tail = device_p;
+		new_p->curr = device_p;
+		new_p->count = 1;
+		device_p->prev = NULL;
+		device_p->next = NULL;
+	} else {		/* there is another device -> hang to tail */
+		device_p->prev = new_p->tail;
+		device_p->next = NULL;
+		new_p->tail->next = device_p;
+		new_p->tail = device_p;
+		new_p->curr = device_p;
+		new_p->count++;
+	}
+	rcu_assign_pointer(device_head_p[hash], new_p);
+	spin_unlock(&device_list_locks[hash]);
+	synchronize_srcu(&device_list_srcu[hash]);
+	rsbac_kfree(old_p);
+	return device_p;
+}
+
+/************************************************************************** */
+/* The remove_item() functions remove an item from the list. If this item   */
+/* is head, tail or curr, these pointers are set accordingly.               */
+/* To speed up removing several subsequent items, curr is set to the next   */
+/* item, if possible.                                                       */
+/* If the item is not found, nothing is done.                               */
+
+static void clear_device_item(struct rsbac_device_list_item_t *item_p)
+{
+	if (!item_p)
+		return;
+
+	/* dput() rsbac_dir_dentry_p, if set */
+	if (item_p->rsbac_dir_dentry_p) {
+		dput(item_p->rsbac_dir_dentry_p);
+	}
+
+	/* OK, lets remove the device item itself */
+	rsbac_sfree(device_item_slab, item_p);
+}
+
+/* remove_device_item unlocks device_list_locks[hash]! */
+static void remove_device_item(kdev_t kdev)
+{
+	struct rsbac_device_list_item_t *item_p;
+	u_int hash;
+               
+	hash = device_hash(kdev);
+	if ((item_p = lookup_device_locked(kdev, hash))) {
+		struct rsbac_device_list_head_t * new_p;
+		struct rsbac_device_list_head_t * old_p;
+
+		old_p = device_head_p[hash];
+		new_p = rsbac_kmalloc(sizeof(*new_p));
+		if (!new_p) {
+			/* Ouch! */
+			spin_unlock(&device_list_locks[hash]);
+			return;
+		}
+		*new_p = *old_p;
+		if (new_p->head == item_p) {	/* item is head */
+			if (new_p->tail == item_p) {	/* item is head and tail = only item -> list will be empty */
+				new_p->head = NULL;
+				new_p->tail = NULL;
+			} else {	/* item is head, but not tail -> next item becomes head */
+				item_p->next->prev = NULL;
+				new_p->head = item_p->next;
+			}
+		} else {	/* item is not head */
+			if (new_p->tail == item_p) {	/*item is not head, but tail -> previous item becomes tail */
+				item_p->prev->next = NULL;
+				new_p->tail = item_p->prev;
+			} else {	/* item is neither head nor tail -> item is cut out */
+				item_p->prev->next = item_p->next;
+				item_p->next->prev = item_p->prev;
+			}
+		}
+
+		/* curr is no longer valid -> reset.                              */
+		new_p->curr = NULL;
+		/* adjust counter */
+		new_p->count--;
+		rcu_assign_pointer(device_head_p[hash], new_p);
+		spin_unlock(&device_list_locks[hash]);
+		synchronize_srcu(&device_list_srcu[hash]);
+		rsbac_kfree(old_p);
+	} else {
+		spin_unlock(&device_list_locks[hash]);
+	}
+}
+
+/**************************************************/
+/*       Externally visible help functions        */
+/**************************************************/
+
+/* helper, copied from open.d/do_truncate() */
+static int rsbac_clear_file(struct dentry *dentry)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+	struct iattr newattrs;
+
+	mutex_lock(&inode->i_mutex);
+	newattrs.ia_size = 0;
+	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
+	error = notify_change(dentry, &newattrs, NULL);
+	mutex_unlock(&inode->i_mutex);
+	return error;
+}
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_check_device);
+#endif
+
+int rsbac_check_device(kdev_t kdev)
+{
+	struct rsbac_device_list_item_t *device_p;
+	u_int hash;
+	int srcu_idx;
+
+	hash = device_hash(kdev);
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(kdev, hash);
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	if (device_p)
+		return 0;
+	else
+		return -RSBAC_ENOTFOUND;
+}
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_get_vfsmount);
+#endif
+struct vfsmount *rsbac_get_vfsmount(kdev_t kdev)
+{
+	struct rsbac_device_list_item_t *device_p;
+	struct vfsmount *vfsmount_p;
+	u_int hash;
+	int srcu_idx;
+
+	if (RSBAC_IS_AUTO_DEV(kdev))
+		return NULL;
+
+	hash = device_hash(kdev);
+	/* get super_block-pointer */
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(kdev, hash);
+	if (!device_p) {
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			rsbac_printk(KERN_WARNING "rsbac_get_vfsmount(): unknown device %02u:%02u\n",
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev));
+			return NULL;
+	}
+	vfsmount_p = device_p->vfsmount_p;
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	return vfsmount_p;
+}
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_read_open);
+#endif
+int rsbac_read_open(char *name, struct file **file_pi, kdev_t kdev)
+{
+	struct dentry *dir_dentry_p;
+	struct dentry *file_dentry_p;
+	struct file *file_p;
+	struct path path;
+	int err = 0;
+	struct vfsmount *vfsmount_p;
+
+	if (!name || !file_pi) {
+		rsbac_pr_debug(ds, "called with NULL pointer!");
+		return -RSBAC_EINVALIDPOINTER;
+	}
+
+	vfsmount_p = rsbac_get_vfsmount(kdev);
+	if (!vfsmount_p) {
+		rsbac_printk(KERN_WARNING "rsbac_read_open(): invalid device %02u:%02u\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+		return -RSBAC_EINVALIDDEV;
+	}
+
+	/* lookup dentry of ACI_PATH on root device, lock is released there */
+	if ((err =
+	     lookup_aci_path_dentry(vfsmount_p, &dir_dentry_p, FALSE, kdev))) {
+		goto out;
+	}
+
+	mutex_lock(&dir_dentry_p->d_inode->i_mutex);
+	/* open file for reading - this must be done 'by hand', because     */
+	/* standard system calls are now extended by rsbac decision calls.  */
+	file_dentry_p =
+	    rsbac_lookup_one_len(name, dir_dentry_p, strlen(name));
+	mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+
+	if (!file_dentry_p || IS_ERR(file_dentry_p)) {	/* error in lookup */
+		err = -RSBAC_EREADFAILED;
+		goto out;
+	}
+	if (!file_dentry_p->d_inode || !file_dentry_p->d_inode->i_size) {
+		/* file not found or empty: trying backup */
+		char *bname;
+		int name_len = strlen(name);
+
+		dput(file_dentry_p);
+		bname = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (!bname) {
+			err = -RSBAC_ENOMEM;
+			goto out;
+		}
+
+		strcpy(bname, name);
+		bname[name_len] = 'b';
+		name_len++;
+		bname[name_len] = (char) 0;
+		rsbac_pr_debug(ds, "could not lookup file %s, trying backup %s\n",
+			     name, bname);
+
+		mutex_lock(&dir_dentry_p->d_inode->i_mutex);
+		file_dentry_p =
+		    rsbac_lookup_one_len(bname, dir_dentry_p,
+					 strlen(bname));
+		mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+		rsbac_kfree(bname);
+		if (!file_dentry_p || IS_ERR(file_dentry_p)) {	/* error in lookup */
+			return -RSBAC_EREADFAILED;
+		}
+		if (!file_dentry_p->d_inode || !file_dentry_p->d_inode->i_size) {
+			/* backup file also not found: return error */
+			rsbac_pr_debug(ds, "backup file %sb not found or empty\n",
+				       name);
+			dput(file_dentry_p);
+			err = -RSBAC_ENOTFOUND;
+			goto out;
+		}
+	}
+	if (!(S_ISREG(file_dentry_p->d_inode->i_mode))) {	/* this is not a file! -> error! */
+		rsbac_printk(KERN_WARNING "rsbac_read_open(): expected file is not a file!\n");
+		mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+		dput(file_dentry_p);
+		err = -RSBAC_EREADFAILED;
+		goto out;
+	}
+
+	/* Now we fill the file structure and */
+	/* if there is an open func for this file, use it, otherwise ignore */
+	path.dentry = file_dentry_p;
+	path.mnt = mntget(vfsmount_p);
+	file_p = alloc_file(&path, FMODE_READ, path.dentry->d_inode->i_fop);
+
+	if (!file_p) {
+		path_put(&path);
+		rsbac_printk(KERN_WARNING "rsbac_read_open(): could not open file '%s'!\n",
+			     name);
+		err = -RSBAC_EREADFAILED;
+		goto out;
+	}
+
+	/* if there is no read func, we get a problem -> error */
+	if (!file_p->f_op) {
+		rsbac_printk(KERN_WARNING "rsbac_read_open(): no f_op for file '%s'!\n",
+			     name);
+		path_put(&path);
+		err = -RSBAC_EREADFAILED;
+		goto out;
+	}
+	if (!file_p->f_op->read && !file_p->f_op->read_iter) {
+		rsbac_printk(KERN_WARNING "rsbac_read_open(): no read function for file '%s'!\n",
+			     name);
+		path_put(&path);
+		err = -RSBAC_EREADFAILED;
+		goto out;
+	}
+
+	*file_pi = file_p;
+
+	if (file_p->f_op->open)
+		err = file_p->f_path.dentry->d_inode->i_fop->open(path.dentry->d_inode, file_p);
+
+out:
+	return err;
+}
+
+#ifndef check_parent
+#define check_parent(dir, dentry) \
+	((dir) == (dentry)->d_parent && !list_empty(&dentry->d_bucket))
+#endif
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_write_open);
+#endif
+int rsbac_write_open(char *name, struct file **file_pi, kdev_t kdev)
+{
+	struct dentry *dir_dentry_p = NULL;
+	struct dentry *ldir_dentry_p = NULL;
+	struct dentry *file_dentry_p = NULL;
+	struct file * file_p;
+	struct path path;
+	int err = 0;
+	int tmperr = 0;
+	struct vfsmount *vfsmount_p;
+
+	if (!file_pi || !name) {
+		rsbac_pr_debug(write, "called with NULL pointer!\n");
+		return -RSBAC_EINVALIDPOINTER;
+	}
+
+	/* get super_block-pointer */
+	vfsmount_p = rsbac_get_vfsmount(kdev);
+	if (!vfsmount_p) {
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): invalid device %02u:%02u\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+		return -RSBAC_EINVALIDDEV;
+	}
+	if (!rsbac_writable(vfsmount_p->mnt_sb)) {
+		rsbac_pr_debug(write, "called for non-writable device\n");
+		return -RSBAC_ENOTWRITABLE;
+	}
+
+	err = mnt_want_write(vfsmount_p);
+	if (err)
+		return err;
+
+	/* lookup dentry of ACI_PATH on this device (create, if needed and possible),
+	 * returns errorcode, if failed */
+	if ((tmperr = lookup_aci_path_dentry(vfsmount_p, &dir_dentry_p, TRUE,
+					     kdev))) {
+		err = tmperr;
+		goto out;
+	}
+
+	mutex_lock(&dir_dentry_p->d_inode->i_mutex);
+	/* open file for reading - this must be done 'by hand', because     */
+	/* standard system calls are now extended by rsbac decision calls.  */
+	file_dentry_p =
+	    rsbac_lookup_one_len(name, dir_dentry_p, strlen(name));
+	mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+	if (!file_dentry_p || IS_ERR(file_dentry_p)) {
+		rsbac_pr_debug(write, "lookup of %s returned error %li\n",
+			     name, PTR_ERR(file_dentry_p));
+		err = -RSBAC_EWRITEFAILED;
+		goto out;
+	}
+#if 1
+	if (file_dentry_p->d_inode) {	/* file was found: try to rename it as backup file */
+		if (!dir_dentry_p->d_inode->i_op
+		    || (   !dir_dentry_p->d_inode->i_op->rename
+		        && !dir_dentry_p->d_inode->i_op->rename2
+		       )
+		   ) {
+			rsbac_printk(KERN_WARNING "rsbac_write_open(): File system supports no rename - no backup of %s made!",
+				     name);
+		} else {
+			char *bname;
+			int name_len = strlen(name);
+			struct dentry *new_file_dentry_p = NULL;
+			struct dentry *old_dir_p, *new_dir_p;
+
+			bname = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (!bname) {
+				err = -RSBAC_ENOMEM;
+				goto out_dput;
+			}
+			strcpy(bname, name);
+			bname[name_len] = 'b';
+			bname[name_len + 1] = (char) 0;
+			mutex_lock(&dir_dentry_p->d_inode->i_mutex);
+			new_file_dentry_p =
+			    rsbac_lookup_one_len(bname, dir_dentry_p,
+						 strlen(bname));
+			mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+			if (new_file_dentry_p
+			    && !IS_ERR(new_file_dentry_p)) {
+				/* lock parent == rsbac-dir for rest of rename */
+				old_dir_p = dget(file_dentry_p->d_parent);
+				new_dir_p =
+				    dget(new_file_dentry_p->d_parent);
+				double_lock(new_dir_p, old_dir_p);
+				dquot_initialize(old_dir_p->d_inode);
+				dquot_initialize(new_dir_p->d_inode);
+				/* try to rename file in rsbac dir */
+				/* rsbac_pr_debug(write, "calling rename function\n"); */
+				if (dir_dentry_p->d_inode->i_op->rename2)
+					err = dir_dentry_p->d_inode->i_op->rename2(old_dir_p->d_inode,
+						file_dentry_p,
+						new_dir_p->d_inode,
+						new_file_dentry_p,
+						0);
+				else
+					err = dir_dentry_p->d_inode->i_op->rename(old_dir_p->d_inode,
+						file_dentry_p,
+						new_dir_p->d_inode,
+						new_file_dentry_p);
+				/* unlock dir (dputs both dentries) */
+				double_unlock(new_dir_p, old_dir_p);
+				if (err) {
+					rsbac_printk(KERN_WARNING "rsbac_write_open(): could not rename %s to %s on dev %02u:%02u, error %i - no backup!\n",
+						     name, bname,
+						     RSBAC_MAJOR(kdev),
+						     RSBAC_MINOR(kdev),
+						     err);
+				} else {
+					/* The following d_move() should become unconditional */
+					if (!
+					    (vfsmount_p->mnt_sb->s_type->
+					     fs_flags
+					      & FS_RENAME_DOES_D_MOVE
+					    ))
+						d_move(file_dentry_p,
+						       new_file_dentry_p);
+					fsnotify_create(old_dir_p->d_inode,
+							new_file_dentry_p);
+				}
+				dput(new_file_dentry_p);
+				dput(file_dentry_p);
+				/* re-init dentry structure */
+				mutex_lock(&dir_dentry_p->d_inode->i_mutex);
+				file_dentry_p =
+				    rsbac_lookup_one_len(name,
+							 dir_dentry_p,
+							 strlen(name));
+				mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+				if (!file_dentry_p
+				    || IS_ERR(file_dentry_p)) {
+					rsbac_pr_debug(write, "relookup of %s "
+						       "returned error %li\n",
+						       name,
+						       PTR_ERR(file_dentry_p));
+					err = -RSBAC_EWRITEFAILED;
+					goto out;
+				}
+				if (file_dentry_p->d_inode) {
+					rsbac_printk(KERN_WARNING "rsbac_write_open(): relookup of %s returned dentry with existing inode %li, trying unlink\n",
+						     name,
+						     file_dentry_p->
+						     d_inode->i_ino);
+					/* file was found: try to delete it */
+					if (!dir_dentry_p->d_inode->i_op
+					    || !dir_dentry_p->d_inode->
+					    i_op->unlink) {
+						rsbac_printk(KERN_WARNING "rsbac_write_open(): File system supports no unlink - %s not deleted!",
+							     name);
+						rsbac_kfree(bname);
+						err = -RSBAC_EWRITEFAILED;
+						goto out_dput;
+					} else {
+						old_dir_p =
+						    lock_parent
+						    (file_dentry_p);
+						dquot_initialize(old_dir_p->d_inode);
+						err = -ENOENT;
+							err =
+							    dir_dentry_p->
+							    d_inode->i_op->
+							    unlink
+							    (old_dir_p->
+							     d_inode,
+							     file_dentry_p);
+						/* unlock parent dir */
+						unlock_dir(old_dir_p);
+						/* free file dentry */
+						dput(file_dentry_p);
+						if (err) {
+							rsbac_printk
+							    (KERN_WARNING
+							     "rsbac_write_open(): could not unlink %s on dev %02u:%02u, error %i!\n",
+							     name,
+							     RSBAC_MAJOR
+							     (kdev),
+							     RSBAC_MINOR
+							     (kdev), err);
+						}
+						/* re-init dentry structure */
+						mutex_lock(&dir_dentry_p->d_inode->i_mutex);
+						file_dentry_p =
+						    rsbac_lookup_one_len
+						    (name, dir_dentry_p,
+						     strlen(name));
+						mutex_unlock(&dir_dentry_p->d_inode->i_mutex);
+						if (!file_dentry_p
+						    ||
+						    IS_ERR(file_dentry_p)) {
+							rsbac_pr_debug(write, "relookup of %s returned error %li\n",
+								       name,
+								       PTR_ERR(file_dentry_p));
+							rsbac_kfree(bname);
+							err =
+							    -RSBAC_EWRITEFAILED;
+							goto out;
+						}
+						if (file_dentry_p->d_inode) {
+							rsbac_printk
+							    (KERN_WARNING
+							     "rsbac_write_open(): relookup of %s returned dentry with existing inode %li\n",
+							     name,
+							     file_dentry_p->
+							     d_inode->
+							     i_ino);
+							rsbac_kfree(bname);
+							err =
+							    -RSBAC_EWRITEFAILED;
+							goto out_dput;
+						}
+					}
+				}
+			} else {
+				rsbac_printk(KERN_WARNING "rsbac_write_open(): rsbac_lookup_(dentry|one) for backup file %s on dev %02u:%02u failed with error %li - no backup!\n",
+					     bname, RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev),
+					     PTR_ERR(new_file_dentry_p));
+			}
+			rsbac_kfree(bname);
+		}
+	}
+#endif				/* backup part */
+
+	if (!file_dentry_p->d_inode) {
+		/* file not found or renamed away: try to create a new one */
+		if (!dir_dentry_p->d_inode->i_op
+		    || !dir_dentry_p->d_inode->i_op->create) {
+			rsbac_printk(KERN_WARNING "%s\n",
+				     "rsbac_write_open(): File system supports no create!");
+			err = -RSBAC_EWRITEFAILED;
+			goto out_dput;
+		}
+
+		/* lock parent == rsbac-dir for create */
+		ldir_dentry_p = lock_parent(file_dentry_p);
+		if (IS_ERR(ldir_dentry_p)) {
+			rsbac_pr_debug(write, "lock_parent of %s returned "
+				       "error %li\n", name,
+				       PTR_ERR(ldir_dentry_p));
+			err = -RSBAC_EWRITEFAILED;
+			goto out_dput;
+		}
+		/* try to create file in rsbac dir */
+		/* rsbac_pr_debug(write, "calling create function\n"); */
+		dquot_initialize(ldir_dentry_p->d_inode);
+		err =
+		    dir_dentry_p->d_inode->i_op->create(ldir_dentry_p->
+							d_inode,
+							file_dentry_p,
+							RSBAC_ACI_FILE_MODE,
+							NULL);
+		unlock_dir(ldir_dentry_p);
+
+		if (err) {
+			goto out_dput;
+		}
+		/* create was successful */
+	}
+
+	if (!(S_ISREG(file_dentry_p->d_inode->i_mode))) {	/* this is not a file! -> error! */
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): expected file is not a file, mode is %o!\n",
+			     file_dentry_p->d_inode->i_mode);
+		err = -RSBAC_EWRITEFAILED;
+		goto out_dput;
+	}
+	/* Without a write function we get into troubles -> error */
+	if (!file_dentry_p->d_inode->i_fop) {
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): file f_op missing!\n");
+		err = -RSBAC_EWRITEFAILED;
+		goto out_dput;
+	}
+	if (!file_dentry_p->d_inode->i_fop->write && !file_dentry_p->d_inode->i_fop->write_iter) {
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): file write function missing!\n");
+		err = -RSBAC_EWRITEFAILED;
+		goto out_dput;
+	}
+
+	/* alloc_file() will call mnt_want_write */
+	mnt_drop_write(vfsmount_p);
+
+	if ((tmperr = get_write_access(file_dentry_p->d_inode))) {
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): could not get write access on file!\n");
+		dput(file_dentry_p);
+		return -RSBAC_EWRITEFAILED;
+	}
+
+	/* Now we fill the file structure, file_take_write, mnt_want_write */
+	path.dentry = file_dentry_p;
+	path.mnt = mntget(vfsmount_p);
+	file_p = alloc_file(&path, FMODE_WRITE, path.dentry->d_inode->i_fop);
+	if (!file_p) {
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): could not init file!\n");
+		put_write_access(file_p->f_path.dentry->d_inode);
+		path_put(&path);
+		return -RSBAC_EWRITEFAILED;
+	}
+
+	/* truncating */
+	if (rsbac_clear_file(file_dentry_p)) {
+		if (file_p->f_op->release)
+			file_p->f_op->release(file_dentry_p->d_inode,
+					      file_p);
+		rsbac_printk(KERN_WARNING "rsbac_write_open(): could not truncate!\n");
+		err = -RSBAC_EWRITEFAILED;
+		put_write_access(file_p->f_path.dentry->d_inode);
+		goto out_dput;
+	}
+	/* set synchronous mode for this file */
+	file_p->f_flags |= O_SYNC;
+	*file_pi = file_p;
+
+out:
+	if (err)
+		mnt_drop_write(vfsmount_p);
+	return err;
+
+out_dput:
+	dput(file_dentry_p);
+	goto out;
+}
+
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_read_close);
+#endif
+void rsbac_read_close(struct file *file_p)
+{
+	/* cleanup copied from __fput */
+	if (file_p->f_op && file_p->f_op->release)
+		file_p->f_op->release(file_p->f_path.dentry->d_inode, file_p);
+	path_put(&file_p->f_path);
+	put_filp(file_p);
+}
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_write_close);
+#endif
+void rsbac_write_close(struct file *file_p)
+{
+	put_write_access(file_p->f_path.dentry->d_inode);
+//	mnt_drop_write(file_p->f_path.mnt);
+	rsbac_read_close(file_p);
+}
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_lookup_full_path);
+#endif
+int rsbac_lookup_full_path(struct dentry *dentry_p, char path[], int maxlen, int pseudonymize)
+{
+	int len = 0;
+	char *i_path;
+	int tmplen = 0;
+#ifdef CONFIG_RSBAC_LOG_PSEUDO_FS
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val;
+#endif
+	int srcu_idx;
+
+	if (!dentry_p || !path)
+		return -RSBAC_EINVALIDPOINTER;
+	if (maxlen <= 0)
+		return -RSBAC_EINVALIDVALUE;
+	i_path = rsbac_kmalloc(maxlen + RSBAC_MAXNAMELEN);
+	if (!i_path)
+		return -RSBAC_ENOMEM;
+
+	path[0] = 0;
+
+	while (dentry_p && (len < maxlen) && dentry_p->d_name.len
+	       && dentry_p->d_name.name) {
+#ifdef CONFIG_RSBAC_LOG_PSEUDO_FS
+		if (   pseudonymize
+		    && dentry_p->d_inode
+		    && dentry_p->d_parent
+		    && dentry_p->d_parent->d_inode
+		    && (i_tid.user = __kuid_val(dentry_p->d_inode->i_uid))
+		    && (__kuid_val(dentry_p->d_inode->i_uid) !=
+			__kuid_val(dentry_p->d_parent->d_inode->i_uid))
+		    && !rsbac_get_attr(SW_GEN, T_USER, i_tid, A_pseudo,
+				       &i_attr_val, FALSE)
+		    && i_attr_val.pseudo) {	/* Max len of 32 Bit value in decimal print is 11 */
+			if ((maxlen - len) < 12) {
+				rsbac_kfree(i_path);
+				return len;
+			}
+			tmplen =
+			    snprintf(i_path, 11, "%u", i_attr_val.pseudo);
+		} else
+#endif
+		{
+			tmplen = dentry_p->d_name.len;
+			if ((tmplen + 1) > (maxlen - len)) {
+				rsbac_kfree(i_path);
+				return len;
+			}
+			strncpy(i_path, dentry_p->d_name.name, tmplen);
+		}
+		/* Skip double / on multi mounts.
+		 * Last / is appended at the end of the function */
+		if((i_path[tmplen-1] != '/') && (tmplen != 1)) {
+			if(len && (i_path[tmplen-1] != '/')) {
+				i_path[tmplen] = '/';
+				tmplen++;
+			}
+			i_path[tmplen]=0;
+			strcat(i_path, path);
+			strcpy(path, i_path);
+			len += tmplen;
+		}
+		if (dentry_p->d_parent && (dentry_p->d_parent != dentry_p)
+		    && (dentry_p->d_sb->s_root != dentry_p)
+		    )
+			dentry_p = dentry_p->d_parent;
+		else {
+			struct rsbac_device_list_item_t *device_p;
+			u_int hash;
+
+			if (dentry_p->d_sb->s_dev == rsbac_root_dev) {
+				break;
+			}
+			hash = device_hash(dentry_p->d_sb->s_dev);
+			srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+			device_p = lookup_device(dentry_p->d_sb->s_dev, hash);
+			if (   device_p
+			    && device_p->vfsmount_p
+			    && real_mount(device_p->vfsmount_p)->mnt_mountpoint
+			    && real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb
+		            && (real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb->s_dev != dentry_p->d_sb->s_dev)
+			   ) {
+				dentry_p = real_mount(device_p->vfsmount_p)->mnt_mountpoint;
+				srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			} else {
+				srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+				break;
+			}
+		}
+	}
+	
+	i_path[tmplen]=0;
+	strcat(i_path, path);
+	strcpy(path, i_path);
+	
+	rsbac_kfree(i_path);
+	return len;
+}
+
+/************************************************* */
+/*               proc fs functions                 */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC)
+static int
+devices_proc_show(struct seq_file *m, void *v)
+{
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	u_int count = 0;
+	u_int i;
+	int srcu_idx;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++)
+		count += device_head_p[i]->count;
+	seq_printf(m, "%u RSBAC Devices\n---------------\nHash size is %u\n",
+		       count, RSBAC_NR_DEVICE_LISTS);
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		for (device_p = srcu_dereference(head_p->head, &device_list_srcu[i]); device_p;
+		     device_p = srcu_dereference(device_p->next, &device_list_srcu[i])) {
+			if (device_p->vfsmount_p && device_p->vfsmount_p->mnt_sb
+			    && device_p->vfsmount_p->mnt_sb->s_type
+			    && device_p->vfsmount_p->mnt_sb->s_type->name
+			    && real_mount(device_p->vfsmount_p)->mnt_mountpoint) {
+				seq_printf(m,
+					    "%02u:%02u mount_count %u, fs_type %s (%lx), mountpoint %s, parent %02u:%02u, persist %u\n",
+					    RSBAC_MAJOR(device_p->id),
+					    RSBAC_MINOR(device_p->id),
+					    device_p->mount_count,
+					    device_p->vfsmount_p->mnt_sb->s_type->name,
+					    device_p->vfsmount_p->mnt_sb->s_magic,
+					    real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_name.name,
+					    RSBAC_MAJOR(real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb->s_dev),
+					    RSBAC_MINOR(real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb->s_dev),
+					    device_p->persist);
+			} else
+				    seq_printf(m,
+					    "%02u:%02u mount_count %u, no vfsmount_p, persist %u\n",
+					    RSBAC_MAJOR(device_p->id),
+					    RSBAC_MINOR(device_p->id),
+					    device_p->mount_count,
+					    device_p->persist);
+		}
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+	return 0;
+}
+
+static int devices_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, devices_proc_show, NULL);
+}
+
+static const struct file_operations devices_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = devices_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *devices;
+
+static int
+stats_proc_show(struct seq_file *m, void *v)
+{
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	long fd_count, fd_dev_count;
+	u_long fd_sum = 0;
+	u_long sum = 0;
+	u_long total_sum = 0;
+	long tmp_count;
+	int i;
+	int srcu_idx;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+	seq_printf(m,
+		    "RSBAC Status\n------------\nRSBAC Version: %s\nCompiled Modules:%s\n",
+		    RSBAC_VERSION, compiled_modules);
+#ifdef CONFIG_RSBAC_SWITCH
+	{
+		char *active_modules;
+
+		active_modules = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (active_modules) {
+			active_modules[0] = (char) 0;
+#ifdef CONFIG_RSBAC_REG
+			strcat(active_modules, " REG");
+#endif
+#ifdef CONFIG_RSBAC_MAC
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+			if (rsbac_switch_mac)
+#endif
+#ifdef CONFIG_RSBAC_MAC_LIGHT
+				strcat(active_modules, " MAC-L");
+#else
+				strcat(active_modules, " MAC");
+#endif
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+			if (rsbac_switch_daz)
+#endif
+				strcat(active_modules, " DAZ");
+#endif
+#ifdef CONFIG_RSBAC_FF
+#ifdef CONFIG_RSBAC_SWITCH_FF
+			if (rsbac_switch_ff)
+#endif
+				strcat(active_modules, " FF");
+#endif
+#ifdef CONFIG_RSBAC_RC
+#ifdef CONFIG_RSBAC_SWITCH_RC
+			if (rsbac_switch_rc)
+#endif
+				strcat(active_modules, " RC");
+#endif
+#ifdef CONFIG_RSBAC_AUTH
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+			if (rsbac_switch_auth)
+#endif
+				strcat(active_modules, " AUTH");
+#endif
+#ifdef CONFIG_RSBAC_ACL
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+			if (rsbac_switch_acl)
+#endif
+				strcat(active_modules, " ACL");
+#endif
+#ifdef CONFIG_RSBAC_CAP
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+			if (rsbac_switch_cap)
+#endif
+				strcat(active_modules, " CAP");
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+			if (rsbac_switch_jail)
+#endif
+				strcat(active_modules, " JAIL");
+#endif
+#ifdef CONFIG_RSBAC_RES
+#ifdef CONFIG_RSBAC_SWITCH_RES
+			if (rsbac_switch_res)
+#endif
+				strcat(active_modules, " RES");
+#endif
+#ifdef CONFIG_RSBAC_PAX
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+			if (rsbac_switch_pax)
+#endif
+				strcat(active_modules, " PAX");
+#endif
+#ifdef CONFIG_RSBAC_UDF
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+			if (rsbac_switch_udf)
+#endif
+				strcat(active_modules, " UDF");
+#endif
+			seq_printf(m, "Active Modules:  %s\n",
+				    active_modules);
+			rsbac_kfree(active_modules);
+		}
+	}
+#else
+	seq_printf(m, "All modules active (no switching)\n");
+#endif
+
+#ifdef CONFIG_RSBAC_SOFTMODE
+	if (rsbac_softmode) {
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+		seq_printf(m, "Global softmode is enabled\n");
+#else
+		seq_printf(m, "Softmode is enabled\n");
+#endif
+	} else {
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+		seq_printf(m, "Global softmode is disabled\n");
+#else
+		seq_printf(m, "Softmode is disabled\n");
+#endif
+	}
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	{
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			  seq_printf(m,
+				    "Individual softmode enabled for:");
+			for (i = 0; i <= RSBAC_MAX_MOD; i++)
+				if (rsbac_ind_softmode[i])
+					 seq_printf(m, " %s",
+						    get_switch_target_name
+						    (tmp, i));
+			rsbac_kfree(tmp);
+			seq_printf(m, "\n");
+		}
+	}
+#endif
+#endif
+
+	seq_printf(m, "\n");
+
+	tmp_count = 0;
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+		if (device_p)
+			seq_printf(m, "FD items:\n");
+		while (device_p) {
+			fd_dev_count = 0;
+			fd_count = rsbac_list_count(device_p->handles.gen);
+			if (fd_count >= 0) {
+				seq_printf(m, "Dev %02u:%02u: %lu GEN",
+						RSBAC_MAJOR(device_p->id),
+						RSBAC_MINOR(device_p->id),
+						fd_count);
+				fd_dev_count += fd_count;
+			}
+
+#if defined(CONFIG_RSBAC_MAC)
+			fd_count = rsbac_list_count(device_p->handles.mac);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu MAC", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+			fd_count = rsbac_list_count(device_p->handles.daz);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu DAZ", fd_count);
+				fd_dev_count += fd_count;
+			}
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+			fd_count = rsbac_list_count(device_p->handles.dazs);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu DAZ SCANNED", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+			fd_count = rsbac_list_count(device_p->handles.ff);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu FF", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+			fd_count = rsbac_list_count(device_p->handles.rc);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu RC", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+			fd_count = rsbac_list_count(device_p->handles.auth);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu AUTH", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+			fd_count = rsbac_list_count(device_p->handles.cap);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu CAP", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+			fd_count = rsbac_list_count(device_p->handles.res);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu RES", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+			fd_count = rsbac_list_count(device_p->handles.pax);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu PAX", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+			fd_count = rsbac_list_count(device_p->handles.udf);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu UDF", fd_count);
+				fd_dev_count += fd_count;
+			}
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+			fd_count = rsbac_list_count(device_p->handles.udfc);
+			if (fd_count >= 0) {
+				seq_printf(m, ", %lu UDF CHECKED", fd_count);
+				fd_dev_count += fd_count;
+			}
+#endif
+#endif
+
+			seq_printf(m, ", %lu total\n",
+				       fd_dev_count);
+			fd_sum += fd_dev_count;
+			device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+		}
+		tmp_count += device_head_p[i]->count;
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+	seq_printf(m,
+		    "Sum of %lu Devices with %lu fd-items\n\n",
+		    tmp_count, fd_sum);
+	total_sum += fd_sum;
+	/* dev lists */
+	sum = 0;
+	tmp_count = rsbac_list_count(dev_handles.gen);
+	seq_printf(m, "DEV: %lu GEN", tmp_count);
+	sum += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(dev_handles.mac);
+	seq_printf(m, ", %lu MAC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(dev_major_handles.rc);
+	seq_printf(m, ", %lu major RC", tmp_count);
+	sum += tmp_count;
+	tmp_count = rsbac_list_count(dev_handles.rc);
+	seq_printf(m, ", %lu RC", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, ", %lu total\n", sum);
+	total_sum += sum;
+	/* ipc lists */
+	sum = 0;
+	seq_printf(m, "IPC: 0 GEN");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(ipc_handles.mac);
+	seq_printf(m, ", %lu MAC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(ipc_handles.rc);
+	seq_printf(m, ", %lu RC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_list_count(ipc_handles.jail);
+	seq_printf(m, ", %lu JAIL", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, ", %lu total\n", sum);
+	total_sum += sum;
+	/* user lists */
+	sum = 0;
+	tmp_count = rsbac_list_count(user_handles.gen);
+	seq_printf(m, "USER: %lu GEN", tmp_count);
+	sum += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(user_handles.mac);
+	seq_printf(m, ", %lu MAC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	tmp_count = rsbac_list_count(user_handles.daz);
+	seq_printf(m, ", %lu DAZ", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	tmp_count = rsbac_list_count(user_handles.ff);
+	seq_printf(m, ", %lu FF", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(user_handles.rc);
+	seq_printf(m, ", %lu RC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	tmp_count = rsbac_list_count(user_handles.auth);
+	seq_printf(m, ", %lu AUTH", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	tmp_count = rsbac_list_count(user_handles.cap);
+	seq_printf(m, ", %lu CAP", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_list_count(user_handles.jail);
+	seq_printf(m, ", %lu JAIL", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	tmp_count = rsbac_list_count(user_handles.res);
+	seq_printf(m, ", %lu RES", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	tmp_count = rsbac_list_count(user_handles.pax);
+	seq_printf(m, ", %lu PAX", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	tmp_count = rsbac_list_count(user_handles.udf);
+	seq_printf(m, ", %lu UDF", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, ", %lu total\n", sum);
+	total_sum += sum;
+	/* process lists */
+	sum = 0;
+	tmp_count = rsbac_list_count(process_handles.gen);
+	seq_printf(m, "PROCESS: %lu GEN", tmp_count);
+	sum += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(process_handles.mac);
+	seq_printf(m, ", %lu MAC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	tmp_count = rsbac_list_count(process_handles.daz);
+	seq_printf(m, ", %lu DAZ", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(process_handles.rc);
+	seq_printf(m, ", %lu RC", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	tmp_count = rsbac_list_count(process_handles.auth);
+	seq_printf(m, ", %lu AUTH", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	tmp_count = rsbac_list_count(process_handles.cap);
+	seq_printf(m, ", %lu CAP", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_list_count(process_handles.jail);
+	seq_printf(m, ", %lu JAIL", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	tmp_count = rsbac_list_count(process_handles.udf);
+	seq_printf(m, ", %lu UDF", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, ", %lu total\n", sum);
+	total_sum += sum;
+#if defined(CONFIG_RSBAC_UM)
+	/* group lists */
+	sum = 0;
+	seq_printf(m, "GROUP:");
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	tmp_count = rsbac_list_count(group_handles.rc);
+	seq_printf(m, " %lu RC,", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, " %lu total\n", sum);
+	total_sum += sum;
+#endif
+
+#if defined(CONFIG_RSBAC_NET_DEV)
+	/* netdev lists */
+	sum = 0;
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	tmp_count = rsbac_list_count(netdev_handles.gen);
+	seq_printf(m, "NETDEV: %lu GEN, ", tmp_count);
+	sum += tmp_count;
+#else
+	seq_printf(m, "NETDEV: ");
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(netdev_handles.rc);
+	seq_printf(m, "%lu RC, ", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, "%lu total\n", sum);
+	total_sum += sum;
+#endif
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	/* net template list */
+	tmp_count = rsbac_list_count(net_temp_handle);
+	seq_printf(m, "%lu Network Templates\n", tmp_count);
+	/* nettemp lists */
+	sum = 0;
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+	tmp_count = rsbac_list_count(nettemp_handles.gen);
+	seq_printf(m, "NETTEMP: %lu GEN, ", tmp_count);
+	sum += tmp_count;
+#else
+	seq_printf(m, "NETTEMP: ");
+#endif
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(nettemp_handles.mac);
+	seq_printf(m, "%lu MAC, ", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(nettemp_handles.rc);
+	seq_printf(m, "%lu RC, ", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, "%lu total\n", sum);
+	total_sum += sum;
+	/* local netobj lists */
+	sum = 0;
+	seq_printf(m, "LNETOBJ: ");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(lnetobj_handles.mac);
+	seq_printf(m, "%lu MAC, ", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(lnetobj_handles.rc);
+	seq_printf(m, "%lu RC, ", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, "%lu total\n", sum);
+	total_sum += sum;
+	/* remote netobj lists */
+	sum = 0;
+	seq_printf(m, "RNETOBJ: ");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(rnetobj_handles.mac);
+	seq_printf(m, "%lu MAC, ", tmp_count);
+	sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(rnetobj_handles.rc);
+	seq_printf(m, "%lu RC, ", tmp_count);
+	sum += tmp_count;
+#endif
+	seq_printf(m, "%lu total\n", sum);
+	total_sum += sum;
+#endif				/* NET_OBJ */
+
+	seq_printf(m,
+		       "Total sum of %lu registered rsbac-items\n",
+		       total_sum);
+	seq_printf(m,
+		       "\nadf_request calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu, total: %llu\n",
+		       rsbac_adf_request_count[T_FILE],
+		       rsbac_adf_request_count[T_DIR],
+		       rsbac_adf_request_count[T_FIFO],
+		       rsbac_adf_request_count[T_SYMLINK],
+		       rsbac_adf_request_count[T_DEV],
+		       rsbac_adf_request_count[T_IPC],
+		       rsbac_adf_request_count[T_SCD],
+		       rsbac_adf_request_count[T_USER],
+		       rsbac_adf_request_count[T_PROCESS],
+		       rsbac_adf_request_count[T_NETDEV],
+		       rsbac_adf_request_count[T_NETTEMP],
+		       rsbac_adf_request_count[T_NETOBJ],
+		       rsbac_adf_request_count[T_GROUP],
+		       rsbac_adf_request_count[T_UNIXSOCK],
+		       rsbac_adf_request_count[T_FILE]+rsbac_adf_request_count[T_DIR]+rsbac_adf_request_count[T_FIFO]+rsbac_adf_request_count[T_SYMLINK]+rsbac_adf_request_count[T_DEV]+rsbac_adf_request_count[T_IPC]+rsbac_adf_request_count[T_SCD]+rsbac_adf_request_count[T_USER]+rsbac_adf_request_count[T_PROCESS]+rsbac_adf_request_count[T_NETDEV]+rsbac_adf_request_count[T_NETTEMP]+rsbac_adf_request_count[T_NETOBJ]+rsbac_adf_request_count[T_GROUP]+rsbac_adf_request_count[T_UNIXSOCK]);
+	seq_printf(m,
+		       "adf_set_attr calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu, total: %llu\n",
+		       rsbac_adf_set_attr_count[T_FILE],
+		       rsbac_adf_set_attr_count[T_DIR],
+		       rsbac_adf_set_attr_count[T_FIFO],
+		       rsbac_adf_set_attr_count[T_SYMLINK],
+		       rsbac_adf_set_attr_count[T_DEV],
+		       rsbac_adf_set_attr_count[T_IPC],
+		       rsbac_adf_set_attr_count[T_SCD],
+		       rsbac_adf_set_attr_count[T_USER],
+		       rsbac_adf_set_attr_count[T_PROCESS],
+		       rsbac_adf_set_attr_count[T_NETDEV],
+		       rsbac_adf_set_attr_count[T_NETTEMP],
+		       rsbac_adf_set_attr_count[T_NETOBJ],
+		       rsbac_adf_set_attr_count[T_GROUP],
+		       rsbac_adf_set_attr_count[T_UNIXSOCK],
+		       rsbac_adf_set_attr_count[T_FILE]+rsbac_adf_set_attr_count[T_DIR]+rsbac_adf_set_attr_count[T_FIFO]+rsbac_adf_set_attr_count[T_SYMLINK]+rsbac_adf_set_attr_count[T_DEV]+rsbac_adf_set_attr_count[T_IPC]+rsbac_adf_set_attr_count[T_SCD]+rsbac_adf_set_attr_count[T_USER]+rsbac_adf_set_attr_count[T_PROCESS]+rsbac_adf_set_attr_count[T_NETDEV]+rsbac_adf_set_attr_count[T_NETTEMP]+rsbac_adf_set_attr_count[T_NETOBJ]+rsbac_adf_set_attr_count[T_GROUP]+rsbac_adf_set_attr_count[T_UNIXSOCK]);
+	return 0;
+}
+
+static int stats_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_proc_show, NULL);
+}
+
+static const struct file_operations stats_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = stats_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *stats;
+
+static int
+active_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "Version: %s\n", RSBAC_VERSION);
+#ifdef CONFIG_RSBAC_SOFTMODE
+	if (rsbac_softmode)
+		seq_printf(m, "Mode: SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Mode: Secure\n");
+#ifdef CONFIG_RSBAC_SOFTMODE
+	seq_printf(m, "Softmode: available\n");
+#else
+	seq_printf(m, "Softmode: unavailable\n");
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	seq_printf(m, "Ind-Soft: available\n");
+#else
+	seq_printf(m, "Ind-Soft: unavailable\n");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH
+	seq_printf(m, "Switching off: available for");
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+#ifndef CONFIG_RSBAC_SWITCH_ON
+	if (rsbac_switch_mac)
+#endif
+		seq_printf(m, " MAC");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+	seq_printf(m, " DAZ");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_FF
+	seq_printf(m, " FF");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_RC
+#ifndef CONFIG_RSBAC_SWITCH_ON
+	if (rsbac_switch_rc)
+#endif
+		seq_printf(m, " RC");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+	seq_printf(m, " AUTH");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+	seq_printf(m, " ACL");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+	seq_printf(m, " CAP");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+	seq_printf(m, " JAIL");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_RES
+	seq_printf(m, " RES");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+	seq_printf(m, " PAX");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+	seq_printf(m, " UDF");
+#endif
+	seq_printf(m, "\n");
+	seq_printf(m, "Switching on: available for");
+#ifdef CONFIG_RSBAC_SWITCH_ON
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+	seq_printf(m, " MAC");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_RC
+	seq_printf(m, " RC");
+#endif
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+	seq_printf(m, " DAZ");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_FF
+	seq_printf(m, " FF");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+	seq_printf(m, " AUTH");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+	seq_printf(m, " ACL");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+	seq_printf(m, " CAP");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+	seq_printf(m, " JAIL");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_RES
+	seq_printf(m, " RES");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+	seq_printf(m, " PAX");
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+	seq_printf(m, " UDF");
+#endif
+	seq_printf(m, "\n");
+#else
+	seq_printf(m, "Switching off: unavailable\n");
+	seq_printf(m, "Switching on: unavailable\n");
+#endif
+#endif
+#ifdef CONFIG_RSBAC_REG
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_REG])
+		seq_printf(m, "Module: REG  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: REG  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_MAC
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+	if (!rsbac_switch_mac)
+		seq_printf(m, "Module: MAC  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_MAC])
+		seq_printf(m, "Module: MAC  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: MAC  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_DAZ
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+	if (!rsbac_switch_daz)
+		seq_printf(m, "Module: DAZ  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_DAZ])
+		seq_printf(m, "Module: DAZ  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: DAZ  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_FF
+#ifdef CONFIG_RSBAC_SWITCH_FF
+	if (!rsbac_switch_ff)
+		seq_printf(m, "Module: FF   OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_FF])
+		seq_printf(m, "Module: FF   SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: FF   on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_RC
+#ifdef CONFIG_RSBAC_SWITCH_RC
+	if (!rsbac_switch_rc)
+		seq_printf(m, "Module: RC   OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_RC])
+		seq_printf(m, "Module: RC   SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: RC   on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+	if (!rsbac_switch_auth)
+		seq_printf(m, "Module: AUTH OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_AUTH])
+		seq_printf(m, "Module: AUTH SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: AUTH on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_ACL
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+	if (!rsbac_switch_acl)
+		seq_printf(m, "Module: ACL  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_ACL])
+		seq_printf(m, "Module: ACL  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: ACL  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_CAP
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+	if (!rsbac_switch_cap)
+		seq_printf(m, "Module: CAP  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_CAP])
+		seq_printf(m, "Module: CAP  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: CAP  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_JAIL
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+	if (!rsbac_switch_jail)
+		seq_printf(m, "Module: JAIL OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_JAIL])
+		seq_printf(m, "Module: JAIL SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: JAIL on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_RES
+#ifdef CONFIG_RSBAC_SWITCH_RES
+	if (!rsbac_switch_res)
+		seq_printf(m, "Module: RES  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_RES])
+		seq_printf(m, "Module: RES  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: RES  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_PAX
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+	if (!rsbac_switch_pax)
+		seq_printf(m, "Module: PAX  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_PAX])
+		seq_printf(m, "Module: PAX  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: PAX  on\n");
+#endif
+
+#ifdef CONFIG_RSBAC_UDF
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+	if (!rsbac_switch_udf)
+		seq_printf(m, "Module: UDF  OFF\n");
+	else
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if (rsbac_ind_softmode[SW_UDF])
+		seq_printf(m, "Module: UDF  SOFTMODE\n");
+	else
+#endif
+		seq_printf(m, "Module: UDF  on\n");
+#endif
+
+	return 0;
+}
+
+static int active_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, active_proc_show, NULL);
+}
+
+static const struct file_operations active_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = active_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *active;
+
+#ifdef CONFIG_RSBAC_XSTATS
+static int
+xstats_proc_show(struct seq_file *m, void *v)
+{
+	int i, j;
+	char name[80];
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+#ifdef CONFIG_RSBAC_FD_CACHE
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	int srcu_idx;
+	int header_shown;
+#endif
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		       "RSBAC ADF call Statistics\n-------------------------\nadf_request table:\n");
+	seq_printf(m,
+		    "Request /\tFILE\tDIR\tFIFO\tSYMLINK\tDEV\tIPC\tSCD\tUSER\tPROCESS\tNETDEV\tNETTEMP\tNETOBJ\tGROUP\tUNIXSOCK NONE");
+
+	for (i = 0; i < R_NONE; i++) {
+		get_request_name(name, i);
+		name[15] = 0;
+		seq_printf(m, "\n%-14s\t", name);
+		for (j = 0; j <= T_NONE; j++) {
+			if ((j == T_NETTEMP_NT)
+			    || (j == T_FD)
+			    )
+				continue;
+			seq_printf(m, "%llu\t",
+				       rsbac_adf_request_xcount[j][i]);
+		}
+	}
+
+	seq_printf(m,
+		       "\n\nadf_request calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu, none: %llu, total: %llu\n",
+		       rsbac_adf_request_count[T_FILE],
+		       rsbac_adf_request_count[T_DIR],
+		       rsbac_adf_request_count[T_FIFO],
+		       rsbac_adf_request_count[T_SYMLINK],
+		       rsbac_adf_request_count[T_DEV],
+		       rsbac_adf_request_count[T_IPC],
+		       rsbac_adf_request_count[T_SCD],
+		       rsbac_adf_request_count[T_USER],
+		       rsbac_adf_request_count[T_PROCESS],
+		       rsbac_adf_request_count[T_NETDEV],
+		       rsbac_adf_request_count[T_NETTEMP],
+		       rsbac_adf_request_count[T_NETOBJ],
+		       rsbac_adf_request_count[T_GROUP],
+		       rsbac_adf_request_count[T_UNIXSOCK],
+		       rsbac_adf_request_count[T_NONE],
+		       rsbac_adf_request_count[T_FILE]+rsbac_adf_request_count[T_DIR]+rsbac_adf_request_count[T_FIFO]+rsbac_adf_request_count[T_SYMLINK]+rsbac_adf_request_count[T_DEV]+rsbac_adf_request_count[T_IPC]+rsbac_adf_request_count[T_SCD]+rsbac_adf_request_count[T_USER]+rsbac_adf_request_count[T_PROCESS]+rsbac_adf_request_count[T_NETDEV]+rsbac_adf_request_count[T_NETTEMP]+rsbac_adf_request_count[T_NETOBJ]+rsbac_adf_request_count[T_GROUP]+rsbac_adf_request_count[T_UNIXSOCK]+rsbac_adf_request_count[T_NONE]);
+	seq_printf(m,
+		       "\n\nadf_set_attr table:\nRequest /\tFILE\tDIR\tFIFO\tSYMLINK\tDEV\tIPC\tSCD\tUSER\tPROCESS\tNETDEV\tNETTEMP\tNETOBJ\tGROUP\tUNIXSOCK NONE");
+	for (i = 0; i < R_NONE; i++) {
+		get_request_name(name, i);
+		name[15] = 0;
+		seq_printf(m, "\n%-14s\t", name);
+		for (j = 0; j <= T_NONE; j++) {
+			if ((j == T_NETTEMP_NT)
+			    || (j == T_FD)
+			    )
+				continue;
+			seq_printf(m, "%llu\t",
+				       rsbac_adf_set_attr_xcount[j][i]);
+		}
+	}
+
+	seq_printf(m,
+		       "\n\nadf_set_attr calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu, none: %llu, total: %llu\n",
+		       rsbac_adf_set_attr_count[T_FILE],
+		       rsbac_adf_set_attr_count[T_DIR],
+		       rsbac_adf_set_attr_count[T_FIFO],
+		       rsbac_adf_set_attr_count[T_SYMLINK],
+		       rsbac_adf_set_attr_count[T_DEV],
+		       rsbac_adf_set_attr_count[T_IPC],
+		       rsbac_adf_set_attr_count[T_SCD],
+		       rsbac_adf_set_attr_count[T_USER],
+		       rsbac_adf_set_attr_count[T_PROCESS],
+		       rsbac_adf_set_attr_count[T_NETDEV],
+		       rsbac_adf_set_attr_count[T_NETTEMP],
+		       rsbac_adf_set_attr_count[T_NETOBJ],
+		       rsbac_adf_set_attr_count[T_GROUP],
+		       rsbac_adf_set_attr_count[T_UNIXSOCK],
+		       rsbac_adf_set_attr_count[T_NONE],
+		       rsbac_adf_set_attr_count[T_FILE]+rsbac_adf_set_attr_count[T_DIR]+rsbac_adf_set_attr_count[T_FIFO]+rsbac_adf_set_attr_count[T_SYMLINK]+rsbac_adf_set_attr_count[T_DEV]+rsbac_adf_set_attr_count[T_IPC]+rsbac_adf_set_attr_count[T_SCD]+rsbac_adf_set_attr_count[T_USER]+rsbac_adf_set_attr_count[T_PROCESS]+rsbac_adf_set_attr_count[T_NETDEV]+rsbac_adf_set_attr_count[T_NETTEMP]+rsbac_adf_set_attr_count[T_NETOBJ]+rsbac_adf_set_attr_count[T_GROUP]+rsbac_adf_set_attr_count[T_UNIXSOCK]+rsbac_adf_set_attr_count[T_NONE]);
+	seq_printf(m,
+		    "\nSyscall counts\n-------------\n");
+
+	for (i = 0; i < RSYS_none; i++) {
+		get_syscall_name(name, i);
+		name[30] = 0;
+		seq_printf(m, "%-26s %llu\n",
+		               name, syscall_count[i]);
+	}
+
+	seq_printf(m,
+		       "\n\nData Structures:\nrsbac_get_attr calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu\n",
+		       get_attr_count[T_FILE],
+		       get_attr_count[T_DIR],
+		       get_attr_count[T_FIFO],
+		       get_attr_count[T_SYMLINK],
+		       get_attr_count[T_DEV],
+		       get_attr_count[T_IPC],
+		       get_attr_count[T_SCD],
+		       get_attr_count[T_USER],
+		       get_attr_count[T_PROCESS],
+		       get_attr_count[T_NETDEV],
+		       get_attr_count[T_NETTEMP],
+		       get_attr_count[T_NETOBJ],
+		       get_attr_count[T_GROUP],
+		       get_attr_count[T_UNIXSOCK]);
+
+	seq_printf(m,
+		       "\nrsbac_set_attr calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu\n",
+		       set_attr_count[T_FILE],
+		       set_attr_count[T_DIR],
+		       set_attr_count[T_FIFO],
+		       set_attr_count[T_SYMLINK],
+		       set_attr_count[T_DEV],
+		       set_attr_count[T_IPC],
+		       set_attr_count[T_SCD],
+		       set_attr_count[T_USER],
+		       set_attr_count[T_PROCESS],
+		       set_attr_count[T_NETDEV],
+		       set_attr_count[T_NETTEMP],
+		       set_attr_count[T_NETOBJ],
+		       set_attr_count[T_GROUP],
+		       set_attr_count[T_UNIXSOCK]);
+
+	seq_printf(m,
+		       "\nrsbac_remove_target calls:\nfile: %llu, dir: %llu, fifo: %llu, symlink: %llu, dev: %llu, ipc: %llu, scd: %llu, user: %llu, process: %llu, netdev: %llu, nettemp: %llu, netobj: %llu, group: %llu, unixsock: %llu\n",
+		       remove_count[T_FILE],
+		       remove_count[T_DIR],
+		       remove_count[T_FIFO],
+		       remove_count[T_SYMLINK],
+		       remove_count[T_DEV],
+		       remove_count[T_IPC],
+		       remove_count[T_SCD],
+		       remove_count[T_USER],
+		       remove_count[T_PROCESS],
+		       remove_count[T_NETDEV],
+		       remove_count[T_NETTEMP],
+		       remove_count[T_NETOBJ],
+		       remove_count[T_GROUP],
+		       remove_count[T_UNIXSOCK]);
+
+	seq_printf(m,
+		       "\nrsbac_get_parent calls: %llu\n",
+		       get_parent_count);
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+	seq_printf(m, "\nFD Caches:\n");
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+		while (device_p) {	/* for all sublists */
+			header_shown = 0;
+			for (j = 0; j < SW_NONE; j++) {
+				if (device_p->fd_cache_handle[j]) {
+					__u64 tmp_hits = device_p->fd_cache_hits[j];
+					__u64 tmp_misses = device_p->fd_cache_misses[j];
+
+					if (!header_shown) {
+						seq_printf(m,
+							"\n%02u:%02u    hits                 misses               items   subitem hm-ratio\n",
+							RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id));
+						header_shown = 1;
+					}
+					while ((tmp_hits > (__u32) -1) || (tmp_misses > (__u32) -1)) {
+						tmp_hits >>= 1;
+						tmp_misses >>= 1;
+					}
+					if (!tmp_misses)
+						tmp_misses = 1;
+					seq_printf(m, "%-8s %-20llu %-20llu %-7lu %-7lu %u\n",
+					       get_switch_target_name(name, j),
+					       device_p->fd_cache_hits[j], device_p->fd_cache_misses[j],
+					       rsbac_list_lol_count(device_p->fd_cache_handle[j]),
+					       rsbac_list_lol_all_subcount(device_p->fd_cache_handle[j]),
+					       ((__u32) tmp_hits)/((__u32) tmp_misses));
+				}
+			}
+			if (header_shown)
+				seq_printf(m, "%u fd_cache_invalidates, %u fd_cache_invalidate_alls\n",
+					device_p->fd_cache_invalidates, device_p->fd_cache_invalidate_alls);
+			device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+		}
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+#endif
+	return 0;
+}
+
+static int xstats_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, xstats_proc_show, NULL);
+}
+
+static const struct file_operations xstats_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = xstats_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *xstats;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+static int
+auto_write_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		    "RSBAC auto write settings\n-------------------------\n");
+	seq_printf(m,
+		    "auto interval %u jiffies (%i jiffies = 1 second)\n",
+		    auto_interval, HZ);
+
+#ifdef CONFIG_RSBAC_DEBUG
+	seq_printf(m, "debug level is %i\n",
+		       rsbac_debug_auto);
+#endif
+
+	return 0;
+}
+
+static int auto_write_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, auto_write_proc_show, NULL);
+}
+
+static ssize_t auto_write_proc_write(struct file *file,
+				 const char __user * buf, size_t count,
+				 loff_t *data)
+{
+	ssize_t err;
+	char *k_buf;
+	char *p;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (count > PROC_BLOCK_SIZE) {
+		return -EOVERFLOW;
+	}
+
+	if (!(k_buf = (char *) __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	err = copy_from_user(k_buf, buf, count);
+	if (err < 0)
+		return err;
+
+	err = count;
+	if (count < 13 || strncmp("auto", k_buf, 4)) {
+		goto out;
+	}
+	if (!rsbac_initialized) {
+		err = -ENOSYS;
+		goto out;
+	}
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		err = -EPERM;
+		goto out;
+	}
+
+	/*
+	 * Usage: echo "auto interval #N" > /proc/rsbac_info/auto_write
+	 *   to set auto_interval to given value
+	 */
+	if (!strncmp("interval", k_buf + 5, 8)) {
+		unsigned int interval;
+
+		p = k_buf + 5 + 9;
+
+		if (*p == '\0')
+			goto out;
+
+		interval = simple_strtoul(p, NULL, 0);
+		/* only accept minimum of 1 second */
+		if (interval >= HZ) {
+			rsbac_printk(KERN_INFO "auto_write_proc_write(): setting auto write interval to %u\n",
+				     interval);
+			auto_interval = interval;
+			err = count;
+			goto out;
+		} else {
+			rsbac_printk(KERN_INFO "auto_write_proc_write(): rejecting too short auto write interval %u (min. %i)\n",
+				     interval, HZ);
+			goto out;
+		}
+	}
+#ifdef CONFIG_RSBAC_DEBUG
+	/*
+	 * Usage: echo "auto debug #N" > /proc/rsbac_info/auto_write
+	 *   to set rsbac_debug_auto to given value
+	 */
+	if (!strncmp("debug", k_buf + 5, 5)) {
+		unsigned int debug_level;
+
+		p = k_buf + 5 + 6;
+
+		if (*p == '\0')
+			goto out;
+
+		debug_level = simple_strtoul(p, NULL, 0);
+		/* only accept 0 or 1 */
+		if (!debug_level || (debug_level == 1)) {
+			rsbac_printk(KERN_INFO "auto_write_proc_write(): setting rsbac_debug_auto to %u\n",
+				     debug_level);
+			rsbac_debug_auto = debug_level;
+			err = count;
+		} else {
+			rsbac_printk(KERN_INFO "auto_write_proc_write(): rejecting invalid debug level (should be 0 or 1)\n");
+		}
+	}
+#endif
+
+      out:
+	free_page((ulong) k_buf);
+	return err;
+}
+
+static const struct file_operations auto_write_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = auto_write_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = auto_write_proc_write,
+};
+
+static struct proc_dir_entry *auto_write;
+#endif				/* CONFIG_RSBAC_AUTO_WRITE > 0 */
+
+static int
+versions_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		      "RSBAC version settings (%s)\n----------------------\n",
+		      RSBAC_VERSION);
+	seq_printf(m,
+		    "Device list head size is %u, hash size is %u\n",
+		    (int) sizeof(struct rsbac_device_list_item_t),
+		    RSBAC_NR_DEVICE_LISTS);
+	seq_printf(m,
+		    "FD lists:\nGEN  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_GEN_FD_ACI_VERSION,
+		    sizeof(struct rsbac_gen_fd_aci_t),
+		    1 << gen_nr_fd_hash_bits);
+#if defined(CONFIG_RSBAC_MAC)
+	seq_printf(m,
+		    "MAC  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_MAC_FD_ACI_VERSION,
+		    sizeof(struct rsbac_mac_fd_aci_t),
+		    1 << mac_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	seq_printf(m,
+		    "DAZ  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_DAZ_FD_ACI_VERSION,
+		    sizeof(struct rsbac_daz_fd_aci_t),
+		    1 << daz_nr_fd_hash_bits);
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	seq_printf(m,
+		    "DAZS aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_DAZ_SCANNED_FD_ACI_VERSION,
+		    sizeof(rsbac_daz_scanned_t),
+		    1 << daz_scanned_nr_fd_hash_bits);
+#endif
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	seq_printf(m,
+		    "FF   aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_FF_FD_ACI_VERSION, sizeof(rsbac_ff_flags_t),
+		    1 << ff_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_RC_FD_ACI_VERSION,
+		    sizeof(struct rsbac_rc_fd_aci_t),
+		    1 << rc_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	seq_printf(m,
+		    "AUTH aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_AUTH_FD_ACI_VERSION,
+		    sizeof(struct rsbac_auth_fd_aci_t),
+		    1 << auth_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	seq_printf(m,
+		    "CAP  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_CAP_FD_ACI_VERSION,
+		    sizeof(struct rsbac_cap_fd_aci_t),
+		    1 << cap_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	seq_printf(m,
+		    "PAX  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_PAX_FD_ACI_VERSION, sizeof(rsbac_pax_flags_t),
+		    1 << pax_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	seq_printf(m,
+		    "RES  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_RES_FD_ACI_VERSION,
+		    sizeof(struct rsbac_res_fd_aci_t),
+		    1 << res_nr_fd_hash_bits);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	seq_printf(m,
+		    "UDF  aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_UDF_FD_ACI_VERSION,
+		    sizeof(struct rsbac_udf_fd_aci_t),
+		    1 << udf_nr_fd_hash_bits);
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	seq_printf(m,
+		    "UDFC aci version is %u, aci entry size is %Zd, %u lists per device\n",
+		    RSBAC_UDF_CHECKED_FD_ACI_VERSION,
+		    sizeof(rsbac_udf_checked_t),
+		    1 << udf_checked_nr_fd_hash_bits);
+#endif
+#endif
+	seq_printf(m,
+		    "\nDEV lists:\nGEN  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_GEN_DEV_ACI_VERSION,
+		    sizeof(struct rsbac_gen_dev_aci_t));
+#if defined(CONFIG_RSBAC_MAC)
+	seq_printf(m,
+		    "MAC  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_MAC_DEV_ACI_VERSION,
+		    sizeof(struct rsbac_mac_dev_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_RC_DEV_ACI_VERSION, sizeof(rsbac_rc_type_id_t));
+#endif
+	seq_printf(m, "\nIPC lists:\n");
+#if defined(CONFIG_RSBAC_MAC)
+	seq_printf(m,
+		    "MAC  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_MAC_IPC_ACI_VERSION,
+		    sizeof(struct rsbac_mac_ipc_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_RC_IPC_ACI_VERSION, sizeof(rsbac_rc_type_id_t));
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	seq_printf(m,
+		    "JAIL aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_JAIL_IPC_ACI_VERSION, sizeof(rsbac_jail_id_t));
+#endif
+	seq_printf(m,
+		    "\nUSER lists:\nGEN  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_GEN_USER_ACI_VERSION,
+		    sizeof(struct rsbac_gen_user_aci_t));
+#if defined(CONFIG_RSBAC_MAC)
+	seq_printf(m,
+		    "MAC  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_MAC_USER_ACI_VERSION,
+		    sizeof(struct rsbac_mac_user_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	seq_printf(m,
+		    "DAZ  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_DAZ_USER_ACI_VERSION,
+		    sizeof(rsbac_system_role_int_t));
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_RC_USER_ACI_VERSION, sizeof(rsbac_rc_role_id_t));
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	seq_printf(m,
+		    "AUTH aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_AUTH_USER_ACI_VERSION,
+		    sizeof(rsbac_system_role_int_t));
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	seq_printf(m,
+		    "CAP  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_CAP_USER_ACI_VERSION,
+		    sizeof(struct rsbac_cap_user_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	seq_printf(m,
+		    "JAIL aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_JAIL_USER_ACI_VERSION,
+		    sizeof(rsbac_system_role_int_t));
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	seq_printf(m,
+		    "PAX  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_PAX_USER_ACI_VERSION,
+		    sizeof(rsbac_system_role_int_t));
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	seq_printf(m,
+		    "RES aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_RES_USER_ACI_VERSION,
+		    sizeof(struct rsbac_res_user_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	seq_printf(m,
+		    "UDF  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_UDF_USER_ACI_VERSION,
+		    sizeof(rsbac_system_role_int_t));
+#endif
+	seq_printf(m,
+		    "\nPROCESS lists:\nGEN  aci version is %i, aci entry size is %Zd, default number of lists is %u\n",
+		    RSBAC_GEN_PROCESS_ACI_VERSION,
+		    sizeof(rsbac_request_vector_t),
+		    1 << RSBAC_P_LIST_HASH_BITS);
+#if defined(CONFIG_RSBAC_MAC)
+	seq_printf(m,
+		    "MAC  aci version is %u, aci entry size is %Zd, default number of lists is %u\n",
+		    RSBAC_MAC_PROCESS_ACI_VERSION,
+		    sizeof(struct rsbac_mac_process_aci_t),
+		    1 << RSBAC_P_LIST_HASH_BITS);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd, default number of lists is %u\n",
+		    RSBAC_RC_PROCESS_ACI_VERSION,
+		    sizeof(struct rsbac_rc_process_aci_t),
+		    1 << RSBAC_P_LIST_HASH_BITS);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	seq_printf(m,
+		    "AUTH aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_AUTH_PROCESS_ACI_VERSION,
+		    sizeof(struct rsbac_auth_process_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	seq_printf(m,
+		    "CAP aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_CAP_PROCESS_ACI_VERSION,
+		    sizeof(struct rsbac_cap_process_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	seq_printf(m,
+		    "JAIL aci version is %u, aci entry size is %Zd, number of lists is %u\n",
+		    RSBAC_JAIL_PROCESS_ACI_VERSION,
+		    sizeof(struct rsbac_jail_process_aci_t),
+		    1 << RSBAC_P_LIST_HASH_BITS);
+#endif
+
+#if defined(CONFIG_RSBAC_NET_DEV)
+	seq_printf(m, "\nNETDEV lists:\n");
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	seq_printf(m,
+		    "GEN  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_GEN_NETDEV_ACI_VERSION,
+		    sizeof(struct rsbac_gen_netdev_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_RC_NETDEV_ACI_VERSION,
+		    sizeof(rsbac_rc_type_id_t));
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	seq_printf(m,
+		    "\nNetwork Template list: version is %u, data size is %Zd\n",
+		    RSBAC_NET_TEMP_VERSION,
+		    sizeof(struct rsbac_net_temp_data_t));
+	seq_printf(m,
+		    "\nNETOBJ lists:\nGEN  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_GEN_NETOBJ_ACI_VERSION,
+		    sizeof(struct rsbac_gen_netobj_aci_t));
+#if defined(CONFIG_RSBAC_MAC)
+	seq_printf(m,
+		    "MAC  aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_MAC_NETOBJ_ACI_VERSION,
+		    sizeof(struct rsbac_mac_netobj_aci_t));
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	seq_printf(m,
+		    "RC   aci version is %u, aci entry size is %Zd\n",
+		    RSBAC_RC_NETOBJ_ACI_VERSION,
+		    sizeof(rsbac_rc_type_id_t));
+#endif
+#endif
+	seq_printf(m,
+		    "\nlog_levels array: version is %u, array size is %Zd\n",
+		    RSBAC_LOG_LEVEL_VERSION,
+		    R_NONE * (T_NONE + 1) * sizeof(rsbac_enum_t));
+	seq_printf(m,
+		    "\nattribute value union size is %u\n",
+		    (int) sizeof(union rsbac_attribute_value_t));
+#ifdef CONFIG_RSBAC_FD_CACHE
+	seq_printf(m,
+		    "fd cache attribute value union size is %u\n",
+		    (int) sizeof(union rsbac_attribute_value_cache_t));
+#endif
+	return 0;
+}
+
+static int versions_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, versions_proc_show, NULL);
+}
+
+static const struct file_operations versions_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = versions_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *versions;
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+static int
+net_temp_proc_show(struct seq_file *m, void *v)
+{
+	rsbac_net_temp_id_t *temp_array;
+	long count;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "Network Templates\n-----------------\n");
+	count =
+	    rsbac_list_get_all_desc(net_temp_handle,
+				    (void **) &temp_array);
+	if (count > 0) {
+		__u32 i;
+		struct rsbac_net_temp_data_t data;
+
+		for (i = 0; i < count; i++) {
+			if (!rsbac_list_get_data
+			    (net_temp_handle, &temp_array[i], &data)) {
+				seq_printf(m, "%10u  %s\n",
+					    temp_array[i], data.name);
+				}
+			}
+		rsbac_kfree(temp_array);
+	}
+	seq_printf(m, "%lu templates\n", count);
+	return 0;
+}
+
+static int net_temp_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, net_temp_proc_show, NULL);
+}
+
+static const struct file_operations net_temp_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = net_temp_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *net_temp;
+#endif				/* NET_OBJ */
+
+#ifdef CONFIG_RSBAC_JAIL
+static int
+jails_proc_show(struct seq_file *m, void *v)
+{
+	rsbac_pid_t *pid_array;
+	struct rsbac_ipc_t *ipc_array;
+	u_long count = 0;
+	u_int i;
+	struct rsbac_jail_process_aci_t data;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		    "Syslog-Jail is %u\n\nJAILed Processes\n----------------\nPID    Jail-ID    Flags   Max Caps   SCD get    SCD modify IP\n",
+		    rsbac_jail_syslog_jail_id);
+
+	count = rsbac_list_get_all_desc(process_handles.jail,
+					(void **) &pid_array);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			if (!rsbac_list_get_data
+			    (process_handles.jail,
+			     &pid_array[i], &data)) {
+				seq_printf(m,
+					    "%-5u  %-10u %-7u %-10i%-10u %-10u %-10u %u.%u.%u.%u\n",
+					    pid_nr(pid_array[i]), data.id,
+					    data.flags,
+					    data.max_caps.cap[1],
+					    data.max_caps.cap[0],
+					    data.scd_get,
+					    data.scd_modify,
+					    NIPQUAD(data.ip));
+			}
+		}
+		rsbac_kfree(pid_array);
+	}
+	seq_printf(m, "%lu jailed processes\n", count);
+	seq_printf(m,
+		    "\nJAIL IPCs\n---------\nType        IPC-ID     Jail-ID\n");
+
+	count =
+	    rsbac_list_get_all_desc(ipc_handles.jail,
+				    (void **) &ipc_array);
+	if (count > 0) {
+		__u32 i;
+		rsbac_jail_id_t data;
+		char tmp[RSBAC_MAXNAMELEN];
+
+		for (i = 0; i < count; i++) {
+			if (!rsbac_list_get_data
+			    (ipc_handles.jail, &ipc_array[i], &data)) {
+				seq_printf(m,
+					    "%-10s  %-10lu %-10u\n",
+					    get_ipc_target_name(tmp,
+								ipc_array
+								[i].type),
+					    ipc_array[i].id.id_nr, data);
+			}
+		}
+		rsbac_kfree(ipc_array);
+	}
+	seq_printf(m, "%lu JAIL IPCs\n", count);
+	return 0;
+}
+
+static int jails_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, jails_proc_show, NULL);
+}
+
+static const struct file_operations jails_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = jails_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *jails;
+
+#endif				/* JAIL */
+
+#ifdef CONFIG_RSBAC_PAX
+static int
+pax_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_initialized)
+		return -ENOSYS;
+
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+	seq_puts(m, "RSBAC PaX module\n----------------\n");
+	seq_printf(m, "%li user list items.\n", rsbac_list_count(user_handles.pax));
+	return 0;
+}
+
+static int pax_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, pax_proc_show, NULL);
+}
+
+static const struct file_operations pax_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pax_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *pax;
+#endif
+
+static int register_all_rsbac_proc(void)
+{
+	proc_rsbac_root_p = proc_mkdir_mode("rsbac-info",
+					      S_IFDIR | S_IRUGO | S_IXUGO,
+					      NULL);
+	if (!proc_rsbac_root_p)
+		return -RSBAC_ECOULDNOTADDITEM;
+
+	proc_rsbac_backup_p = proc_mkdir_mode("backup",
+						S_IFDIR | S_IRUGO |
+						S_IXUGO,
+						proc_rsbac_root_p);
+	if (!proc_rsbac_backup_p)
+		return -RSBAC_ECOULDNOTADDITEM;
+
+	devices = proc_create("devices",  S_IFREG | S_IRUGO, proc_rsbac_root_p, &devices_proc_fops);
+	stats = proc_create("stats", S_IFREG | S_IRUGO, proc_rsbac_root_p, &stats_proc_fops);
+	active = proc_create("active", S_IFREG | S_IRUGO, proc_rsbac_root_p, &active_proc_fops);
+#ifdef CONFIG_RSBAC_XSTATS
+	xstats = proc_create("xstats", S_IFREG | S_IRUGO, proc_rsbac_root_p, &xstats_proc_fops);
+#endif
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+	auto_write = proc_create("auto_write", S_IFREG | S_IRUGO | S_IWUGO, proc_rsbac_root_p, &auto_write_proc_fops);
+#endif
+	versions = proc_create("versions", S_IFREG | S_IRUGO, proc_rsbac_root_p, &versions_proc_fops);
+#ifdef CONFIG_RSBAC_NET_OBJ
+	net_temp = proc_create("net_temp", S_IFREG | S_IRUGO, proc_rsbac_root_p, &net_temp_proc_fops);
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+	jails = proc_create("jails", S_IFREG | S_IRUGO, proc_rsbac_root_p, &jails_proc_fops);
+#endif
+#ifdef CONFIG_RSBAC_PAX
+	pax = proc_create("pax", S_IFREG | S_IRUGO, proc_rsbac_root_p, &pax_proc_fops);
+#endif
+
+	return 0;
+}
+
+
+/************************************************* */
+/*               RSBAC daemon                      */
+/************************************************* */
+
+/************************************************************************** */
+/* Initialization, including ACI restoration for root device from disk.     */
+/* After this call, all ACI is kept in memory for performance reasons,      */
+/* but user and file/dir object ACI are written to disk on every change.    */
+
+/* Since there can be no access to aci data structures before init,         */
+/* rsbac_do_init() will initialize all rw-spinlocks to unlocked.               */
+
+/* DAZ init prototype */
+#if defined(CONFIG_RSBAC_DAZ)
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_daz(void);
+#else
+int __init rsbac_init_daz(void);
+#endif
+#endif
+
+/* UDF init prototype */
+#if defined(CONFIG_RSBAC_UDF)
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_udf(void);
+#else
+int __init rsbac_init_udf(void);
+#endif
+#endif
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_dev_lists(void)
+#else
+static int __init register_dev_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering DEV lists\n");
+	{
+		struct rsbac_gen_dev_aci_t def_aci = DEFAULT_GEN_DEV_ACI;
+
+		list_info_p->version = RSBAC_GEN_DEV_ACI_VERSION;
+		list_info_p->key = RSBAC_GEN_DEV_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_dev_desc_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_gen_dev_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &dev_handles.gen, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  dev_compare,
+					  gen_dev_get_conv, &def_aci,
+					  RSBAC_GEN_ACI_DEV_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_dev,
+					  NULL);
+		if (err) {
+			registration_error(err, "DEV General");
+		}
+	}
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_dev_aci_t def_aci = DEFAULT_MAC_DEV_ACI;
+
+		list_info_p->version = RSBAC_MAC_DEV_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_DEV_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_dev_desc_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_dev_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &dev_handles.mac, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  dev_compare,
+					  mac_dev_get_conv, &def_aci,
+					  RSBAC_MAC_ACI_DEV_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_dev,
+					  NULL);
+		if (err) {
+			registration_error(err, "DEV MAC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		rsbac_rc_type_id_t def_major_aci = RSBAC_RC_GENERAL_TYPE;
+		rsbac_rc_type_id_t def_aci = RC_type_inherit_parent;
+
+		list_info_p->version = RSBAC_RC_DEV_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_DEV_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_dev_desc_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &dev_major_handles.rc,
+					  list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  dev_major_compare,
+					  rc_dev_get_conv, &def_major_aci,
+					  RSBAC_RC_ACI_DEV_MAJOR_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_dev,
+					  NULL);
+		if (err) {
+			registration_error(err, "DEV major RC");
+		}
+		list_info_p->version = RSBAC_RC_DEV_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_DEV_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_dev_desc_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &dev_handles.rc, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  dev_compare,
+					  rc_dev_get_conv, &def_aci,
+					  RSBAC_RC_ACI_DEV_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_dev,
+					  NULL);
+		if (err) {
+			registration_error(err, "DEV RC");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_ipc_lists(void)
+#else
+static int __init register_ipc_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering IPC lists\n");
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_ipc_aci_t def_aci = DEFAULT_MAC_IPC_ACI;
+
+		list_info_p->version = RSBAC_MAC_IPC_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_IPC_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_ipc_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_ipc_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &ipc_handles.mac,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  ipc_compare,
+					  NULL,
+					  &def_aci,
+					  RSBAC_MAC_ACI_IPC_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_ipc,
+					  NULL);
+		if (err) {
+			registration_error(err, "IPC MAC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;
+
+		list_info_p->version = RSBAC_RC_IPC_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_IPC_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_ipc_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &ipc_handles.rc,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  ipc_compare,
+					  NULL,
+					  &def_aci,
+					  RSBAC_RC_ACI_IPC_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_ipc,
+					  NULL);
+		if (err) {
+			registration_error(err, "IPC RC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	{
+		rsbac_jail_id_t def_aci = RSBAC_JAIL_DEF_ID;
+
+		list_info_p->version = RSBAC_JAIL_IPC_ACI_VERSION;
+		list_info_p->key = RSBAC_JAIL_IPC_ACI_KEY;
+		list_info_p->desc_size = sizeof(struct rsbac_ipc_t);
+		list_info_p->data_size = sizeof(rsbac_jail_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &ipc_handles.jail,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_OWN_SLAB | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  ipc_compare,
+					  NULL,
+					  &def_aci,
+					  RSBAC_JAIL_ACI_IPC_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_ipc,
+					  NULL);
+		if (err) {
+			registration_error(err, "IPC JAIL");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_user_lists1(void)
+#else
+static int __init register_user_lists1(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering USER lists\n");
+	{
+		struct rsbac_gen_user_aci_t def_aci = DEFAULT_GEN_U_ACI;
+
+		list_info_p->version = RSBAC_GEN_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_GEN_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_gen_user_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &user_handles.gen, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  gen_user_get_conv,
+					  &def_aci,
+					  RSBAC_GEN_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_uid,
+					  NULL);
+		if (err) {
+			registration_error(err, "USER General");
+		}
+	}
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_user_aci_t def_aci = DEFAULT_MAC_U_ACI;
+
+		list_info_p->version = RSBAC_MAC_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_user_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &user_handles.mac, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  mac_user_get_conv, &def_aci,
+					  RSBAC_MAC_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_uid,
+					  NULL);
+		if (err) {
+			registration_error(err, "USER MAC");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.mac)) {
+			struct rsbac_mac_user_aci_t sysadm_aci =
+			    DEFAULT_MAC_U_SYSADM_ACI;
+			struct rsbac_mac_user_aci_t secoff_aci =
+			    DEFAULT_MAC_U_SECOFF_ACI;
+			struct rsbac_mac_user_aci_t auditor_aci =
+			    DEFAULT_MAC_U_AUDITOR_ACI;
+			rsbac_uid_t user;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER MAC ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			if (rsbac_list_add
+			    (user_handles.mac, &user, &sysadm_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER MAC entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			if (rsbac_list_add
+			    (user_handles.mac, &user, &secoff_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER MAC entry could not be added!\n");
+			user = RSBAC_AUDITOR_UID;
+			if (rsbac_list_add
+			    (user_handles.mac, &user, &auditor_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): AUDITOR USER MAC entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	{
+		rsbac_system_role_int_t def_aci = SR_user;
+
+		list_info_p->version = RSBAC_DAZ_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_DAZ_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size = sizeof(rsbac_system_role_int_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.daz, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
+					  NULL,
+					  daz_user_get_conv,
+					  &def_aci,
+					  RSBAC_DAZ_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER DAZ");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.daz)) {
+			rsbac_uid_t user;
+			rsbac_system_role_int_t role;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER DAZ ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			role = SR_administrator;
+			if (rsbac_list_add(user_handles.daz, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER DAZ entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			role = SR_security_officer;
+			if (rsbac_list_add(user_handles.daz, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER DAZ entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	{
+		rsbac_system_role_int_t def_aci = SR_user;
+
+		list_info_p->version = RSBAC_FF_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_FF_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size = sizeof(rsbac_system_role_int_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.ff, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
+					  NULL,
+					  ff_user_get_conv,
+					  &def_aci, RSBAC_FF_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER FF");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.ff)) {
+			rsbac_uid_t user;
+			rsbac_system_role_int_t role;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER FF ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			role = SR_administrator;
+			if (rsbac_list_add(user_handles.ff, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER FF entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			role = SR_security_officer;
+			if (rsbac_list_add(user_handles.ff, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER FF entry could not be added!\n");
+			user = RSBAC_AUDITOR_UID;
+			role = SR_auditor;
+			if (rsbac_list_add(user_handles.ff, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): AUDITOR USER FF entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	{
+		struct rsbac_cap_user_aci_t def_aci = DEFAULT_CAP_U_ACI;
+
+		list_info_p->version = RSBAC_CAP_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_CAP_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_cap_user_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &user_handles.cap, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST |
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL, 
+					  cap_user_get_conv,
+					  &def_aci,
+					  RSBAC_CAP_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_uid,
+					  NULL);
+		if (err) {
+			registration_error(err, "USER CAP");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.cap)) {
+			struct rsbac_cap_user_aci_t sysadm_aci =
+			    DEFAULT_CAP_U_SYSADM_ACI;
+			struct rsbac_cap_user_aci_t secoff_aci =
+			    DEFAULT_CAP_U_SECOFF_ACI;
+			struct rsbac_cap_user_aci_t auditor_aci =
+			    DEFAULT_CAP_U_AUDITOR_ACI;
+			rsbac_uid_t user;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER CAP ACI could not be read - generating standard entries!\n");
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER CAP ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			if (rsbac_list_add
+			    (user_handles.cap, &user, &sysadm_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER CAP entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			if (rsbac_list_add
+			    (user_handles.cap, &user, &secoff_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER CAP entry could not be added!\n");
+			user = RSBAC_AUDITOR_UID;
+			if (rsbac_list_add
+			    (user_handles.cap, &user, &auditor_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): AUDITOR USER CAP entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	{
+		rsbac_system_role_int_t def_aci = SR_user;
+
+		list_info_p->version = RSBAC_UDF_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_UDF_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size = sizeof(rsbac_system_role_int_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.udf, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_UDF_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER UDF");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.udf)) {
+			rsbac_uid_t user;
+			rsbac_system_role_int_t role;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER UDF ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			role = SR_administrator;
+			if (rsbac_list_add(user_handles.udf, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER UDF entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			role = SR_security_officer;
+			if (rsbac_list_add(user_handles.udf, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER UDF entry could not be added!\n");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_user_lists2(void)
+#else
+static int __init register_user_lists2(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+
+#if defined(CONFIG_RSBAC_RC)
+	{
+		struct rsbac_rc_user_aci_t def_aci = DEFAULT_RC_U_ACI;
+
+		list_info_p->version = RSBAC_RC_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_rc_user_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &user_handles.rc, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  rc_user_get_conv, &def_aci,
+					  RSBAC_RC_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_uid,
+					  NULL);
+		if (err) {
+			registration_error(err, "USER RC");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.rc)) {
+			rsbac_uid_t user;
+			struct rsbac_rc_user_aci_t sysadm_aci =
+			    DEFAULT_RC_U_SYSADM_ACI;
+			struct rsbac_rc_user_aci_t secoff_aci =
+			    DEFAULT_RC_U_SECOFF_ACI;
+			struct rsbac_rc_user_aci_t auditor_aci =
+			    DEFAULT_RC_U_AUDITOR_ACI;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER RC ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			if (rsbac_list_add
+			    (user_handles.rc, &user, &sysadm_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER RC entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			if (rsbac_list_add
+			    (user_handles.rc, &user, &secoff_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER RC entry could not be added!\n");
+			user = RSBAC_AUDITOR_UID;
+			if (rsbac_list_add
+			    (user_handles.rc, &user, &auditor_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): AUDITOR USER RC entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	{
+		rsbac_system_role_int_t def_aci = SR_user;
+
+		list_info_p->version = RSBAC_AUTH_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_AUTH_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size = sizeof(rsbac_system_role_int_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.auth, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_PERSIST,
+					  NULL,
+					  auth_user_get_conv,
+					  &def_aci,
+					  RSBAC_AUTH_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER AUTH");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.auth)) {
+			rsbac_uid_t user;
+			rsbac_system_role_int_t role;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER AUTH ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			role = SR_administrator;
+			if (rsbac_list_add
+			    (user_handles.auth, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER AUTH entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			role = SR_security_officer;
+			if (rsbac_list_add
+			    (user_handles.auth, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER AUTH entry could not be added!\n");
+			user = RSBAC_AUDITOR_UID;
+			role = SR_auditor;
+			if (rsbac_list_add
+			    (user_handles.auth, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): AUDITOR USER AUTH entry could not be added!\n");
+		}
+	}
+#endif				/* AUTH */
+#if defined(CONFIG_RSBAC_JAIL)
+	{
+		rsbac_system_role_int_t def_aci = SR_user;
+
+		list_info_p->version = RSBAC_JAIL_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_JAIL_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size = sizeof(rsbac_system_role_int_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.jail, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_PERSIST,
+					  NULL,
+					  jail_user_get_conv,
+					  &def_aci,
+					  RSBAC_JAIL_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER JAIL");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.jail)) {
+			rsbac_uid_t user;
+			rsbac_system_role_int_t role;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER JAIL ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			role = SR_administrator;
+			if (rsbac_list_add
+			    (user_handles.jail, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER JAIL entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			role = SR_security_officer;
+			if (rsbac_list_add
+			    (user_handles.jail, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER JAIL entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	{
+		list_info_p->version = RSBAC_RES_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_RES_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_res_user_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.res, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST,
+					  NULL,
+					  res_user_get_conv,
+					  NULL,
+					  RSBAC_RES_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER RES");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.res)) {
+			struct rsbac_res_user_aci_t sysadm_aci =
+			    DEFAULT_RES_U_SYSADM_ACI;
+			struct rsbac_res_user_aci_t secoff_aci =
+			    DEFAULT_RES_U_SECOFF_ACI;
+			rsbac_uid_t user;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER RES ACI could not be read - generating standard entries!\n");
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER RES ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			if (rsbac_list_add
+			    (user_handles.res, &user, &sysadm_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER RES entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			if (rsbac_list_add
+			    (user_handles.res, &user, &secoff_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER RES entry could not be added!\n");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	{
+		rsbac_system_role_int_t def_aci = SR_user;
+
+		list_info_p->version = RSBAC_PAX_USER_ACI_VERSION;
+		list_info_p->key = RSBAC_PAX_USER_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_uid_t);
+		list_info_p->data_size = sizeof(rsbac_system_role_int_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &user_handles.pax, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_PERSIST,
+					  NULL,
+					  pax_user_get_conv,
+					  &def_aci,
+					  RSBAC_PAX_ACI_USER_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "USER PAX");
+		} else
+		    if (!rsbac_no_defaults
+			&& !rsbac_list_count(user_handles.pax)) {
+			rsbac_uid_t user;
+			rsbac_system_role_int_t role;
+
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): USER PAX ACI could not be read - generating standard entries!\n");
+			user = RSBAC_SYSADM_UID;
+			role = SR_administrator;
+			if (rsbac_list_add(user_handles.pax, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SYSADM USER PAX entry could not be added!\n");
+			user = RSBAC_SECOFF_UID;
+			role = SR_security_officer;
+			if (rsbac_list_add(user_handles.pax, &user, &role))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): SECOFF USER PAX entry could not be added!\n");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_process_lists(void)
+#else
+static int __init register_process_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering PROCESS lists\n");
+	{
+		struct rsbac_gen_process_aci_t def_aci = DEFAULT_GEN_P_ACI;
+
+		list_info_p->version = RSBAC_GEN_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_GEN_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_gen_process_aci_t);
+		list_info_p->max_age = 0;
+		gen_nr_p_hash_bits = RSBAC_P_LIST_HASH_BITS;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+						&process_handles.gen,
+						list_info_p,
+						RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+						NULL,
+						NULL, &def_aci,
+						RSBAC_GEN_ACI_PROCESS_NAME,
+						RSBAC_AUTO_DEV,
+						gen_nr_p_hash_bits,
+						rsbac_list_hash_pid,
+						NULL);
+		if (err) {
+			registration_error(err, "PROCESS GEN");
+		}
+	}
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_process_aci_t def_aci = DEFAULT_MAC_P_ACI;
+
+		list_info_p->version = RSBAC_MAC_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_process_aci_t);
+		list_info_p->max_age = 0;
+		mac_nr_p_hash_bits = RSBAC_P_LIST_HASH_BITS;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+						&process_handles.mac,
+						list_info_p,
+						RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+						NULL,
+						NULL, &def_aci,
+						RSBAC_MAC_ACI_PROCESS_NAME,
+						RSBAC_AUTO_DEV,
+						mac_nr_p_hash_bits,
+						rsbac_list_hash_pid,
+						NULL);
+		if (err) {
+			registration_error(err, "PROCESS MAC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	{
+		struct rsbac_daz_process_aci_t def_aci = DEFAULT_DAZ_P_ACI;
+
+		list_info_p->version = RSBAC_DAZ_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_DAZ_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_daz_process_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &process_handles.daz,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_DAZ_ACI_PROCESS_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_pid,
+					  NULL);
+		if (err) {
+			registration_error(err, "PROCESS DAZ");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		struct rsbac_rc_process_aci_t def_aci = DEFAULT_RC_P_ACI;
+
+		list_info_p->version = RSBAC_RC_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_rc_process_aci_t);
+		list_info_p->max_age = 0;
+		rc_nr_p_hash_bits = RSBAC_P_LIST_HASH_BITS;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+						&process_handles.rc,
+						list_info_p,
+						RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+						NULL,
+						NULL, &def_aci,
+						RSBAC_RC_ACI_PROCESS_NAME,
+						RSBAC_AUTO_DEV,
+						rc_nr_p_hash_bits,
+						rsbac_list_hash_pid,
+						NULL);
+		if (err) {
+			registration_error(err, "PROCESS RC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	{
+		struct rsbac_auth_process_aci_t def_aci = DEFAULT_AUTH_P_ACI;
+
+		list_info_p->version = RSBAC_AUTH_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_AUTH_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_auth_process_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &process_handles.auth,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_AUTH_ACI_PROCESS_NAME,
+					  RSBAC_AUTO_DEV,
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+					  RSBAC_LIST_MIN_MAX_HASH_BITS,
+#else
+					  1,
+#endif
+					  rsbac_list_hash_pid,
+					  NULL);
+		if (err) {
+			registration_error(err, "PROCESS AUTH");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	{
+		struct rsbac_cap_process_aci_t def_aci = DEFAULT_CAP_P_ACI;
+
+#if defined(CONFIG_RSBAC_CAP_PROC_HIDE)
+		if (rsbac_cap_process_hiding)
+			def_aci.cap_process_hiding = PH_from_other_users;
+#endif
+		list_info_p->version = RSBAC_CAP_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_CAP_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_cap_process_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &process_handles.cap,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_CAP_ACI_PROCESS_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_pid,
+					  NULL);
+		if (err) {
+			registration_error(err, "PROCESS CAP");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	{
+		struct rsbac_jail_process_aci_t def_aci =
+		    DEFAULT_JAIL_P_ACI;
+
+		list_info_p->version = RSBAC_JAIL_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_JAIL_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_jail_process_aci_t);
+		list_info_p->max_age = 0;
+		jail_nr_p_hash_bits = RSBAC_P_LIST_HASH_BITS;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+						&process_handles.jail,
+						list_info_p,
+						RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+						NULL,
+						NULL, &def_aci,
+						RSBAC_JAIL_ACI_PROCESS_NAME,
+						RSBAC_AUTO_DEV,
+						jail_nr_p_hash_bits,
+						rsbac_list_hash_pid,
+						NULL);
+		if (err) {
+			registration_error(err, "PROCESS JAIL");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	{
+		struct rsbac_udf_process_aci_t def_aci = DEFAULT_UDF_P_ACI;
+
+		list_info_p->version = RSBAC_UDF_PROCESS_ACI_VERSION;
+		list_info_p->key = RSBAC_UDF_PROCESS_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_pid_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_udf_process_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &process_handles.udf,
+					  list_info_p,
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_UDF_ACI_PROCESS_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_pid,
+					  NULL);
+		if (err) {
+			registration_error(err, "PROCESS UDF");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_UM
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_group_lists(void)
+#else
+static int __init register_group_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering GROUP lists\n");
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	{
+		rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;
+
+		list_info_p->version = RSBAC_RC_GROUP_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_GROUP_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_gid_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &group_handles.rc, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+					  RSBAC_LIST_BACKUP |
+#endif
+					  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+#ifndef CONFIG_RSBAC_UM_VIRTUAL
+					  RSBAC_LIST_DEF_DATA |
+#endif
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL, NULL,
+					  &def_aci,
+					  RSBAC_RC_ACI_GROUP_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_gid,
+					  NULL);
+		if (err) {
+			registration_error(err, "GROUP RC");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+#endif				/* UM */
+
+#ifdef CONFIG_RSBAC_NET_DEV
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_netdev_lists(void)
+#else
+static int __init register_netdev_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering NETDEV lists\n");
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	{
+		struct rsbac_gen_netdev_aci_t def_aci =
+		    DEFAULT_GEN_NETDEV_ACI;
+
+		list_info_p->version = RSBAC_GEN_NETDEV_ACI_VERSION;
+		list_info_p->key = RSBAC_GEN_NETDEV_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_netdev_id_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_gen_netdev_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &netdev_handles.gen,
+					  list_info_p,
+					  RSBAC_LIST_BACKUP |
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA,
+					  netdev_compare, NULL, &def_aci,
+					  RSBAC_GEN_ACI_NETDEV_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "NETDEV General");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;
+
+		list_info_p->version = RSBAC_RC_NETDEV_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_NETDEV_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_netdev_id_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register(RSBAC_LIST_VERSION,
+					  &netdev_handles.rc,
+					  list_info_p,
+					  RSBAC_LIST_BACKUP |
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA,
+					  netdev_compare, NULL, &def_aci,
+					  RSBAC_RC_ACI_NETDEV_NAME,
+					  RSBAC_AUTO_DEV);
+		if (err) {
+			registration_error(err, "NETDEV RC");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+#endif				/* NET_DEV */
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static void fill_default_nettemp(void)
+#else
+static void __init fill_default_nettemp(void)
+#endif
+{
+	rsbac_net_temp_id_t id;
+	struct rsbac_net_temp_data_t data;
+
+	id = RSBAC_NET_TEMP_LNET_ID;
+	memset(&data, 0, sizeof(data));
+	data.address_family = AF_INET;
+	data.type = RSBAC_NET_ANY;
+	data.protocol = RSBAC_NET_ANY;
+	strcpy(data.name, "Localnet");
+	data.address.inet.nr_addr = 1;
+	data.address.inet.valid_bits[0] = 8;
+	rsbac_net_str_to_inet(RSBAC_NET_TEMP_LNET_ADDRESS,
+			      &data.address.inet.addr[0]);
+	data.ports.nr_ports = 0;
+	rsbac_list_add(net_temp_handle, &id, &data);
+
+	id = RSBAC_NET_TEMP_LAN_ID;
+	memset(&data, 0, sizeof(data));
+	data.address_family = AF_INET;
+	data.type = RSBAC_NET_ANY;
+	data.protocol = RSBAC_NET_ANY;
+	strcpy(data.name, "Internal LAN");
+	data.address.inet.nr_addr = 1;
+	data.address.inet.valid_bits[0] = 16;
+	rsbac_net_str_to_inet(RSBAC_NET_TEMP_LAN_ADDRESS,
+			      &data.address.inet.addr[0]);
+	data.ports.nr_ports = 0;
+	rsbac_list_add(net_temp_handle, &id, &data);
+
+	id = RSBAC_NET_TEMP_AUTO_ID;
+	memset(&data, 0, sizeof(data));
+	data.address_family = AF_INET;
+	data.type = RSBAC_NET_ANY;
+	data.protocol = RSBAC_NET_ANY;
+	strcpy(data.name, "Auto-IPv4");
+	data.address.inet.nr_addr = 1;
+	data.address.inet.valid_bits[0] = 32;
+	data.ports.nr_ports = 0;
+	rsbac_list_add(net_temp_handle, &id, &data);
+
+	id = RSBAC_NET_TEMP_INET_ID;
+	memset(&data, 0, sizeof(data));
+	data.address_family = AF_INET;
+	data.type = RSBAC_NET_ANY;
+	data.protocol = RSBAC_NET_ANY;
+	strcpy(data.name, "AF_INET");
+	data.address.inet.nr_addr = 1;
+	data.address.inet.valid_bits[0] = 0;
+	data.ports.nr_ports = 0;
+	rsbac_list_add(net_temp_handle, &id, &data);
+
+	id = RSBAC_NET_TEMP_INET_ID;
+	memset(&data, 0, sizeof(data));
+	data.address_family = RSBAC_NET_ANY;
+	data.type = RSBAC_NET_ANY;
+	data.protocol = RSBAC_NET_ANY;
+	strcpy(data.name, "ALL");
+	data.ports.nr_ports = 0;
+	rsbac_list_add(net_temp_handle, &id, &data);
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_nettemp_list(void)
+#else
+static int __init register_nettemp_list(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering network template list\n");
+	list_info_p->version = RSBAC_NET_TEMP_VERSION;
+	list_info_p->key = RSBAC_NET_TEMP_KEY;
+	list_info_p->desc_size = sizeof(rsbac_net_temp_id_t);
+	list_info_p->data_size = sizeof(struct rsbac_net_temp_data_t);
+	list_info_p->max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &net_temp_handle,
+				  list_info_p,
+				  RSBAC_LIST_BACKUP |
+				  RSBAC_LIST_PERSIST,
+				  rsbac_list_compare_u32,
+				  net_temp_get_conv,
+				  NULL,
+				  RSBAC_NET_TEMP_NAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "Network Template");
+	} else
+	    if (!rsbac_no_defaults && !rsbac_list_count(net_temp_handle)) {
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): Network Templates could not be read - generating standard entries!\n");
+		fill_default_nettemp();
+	}
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_nettemp_aci_lists(void)
+#else
+static int __init register_nettemp_aci_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering NETTEMP lists\n");
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+	{
+		list_info_p->version = RSBAC_GEN_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_GEN_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_temp_id_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_gen_netobj_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &nettemp_handles.gen,
+					  list_info_p,
+					  RSBAC_LIST_BACKUP |
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL, NULL,
+					  &def_gen_netobj_aci,
+					  RSBAC_GEN_ACI_NETTEMP_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_nettemp,
+					  NULL);
+		if (err) {
+			registration_error(err, "NETTEMP GEN");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_netobj_aci_t def_aci =
+		    DEFAULT_MAC_NETOBJ_ACI;
+
+		list_info_p->version = RSBAC_MAC_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_temp_id_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_netobj_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &nettemp_handles.mac,
+					  list_info_p,
+					  RSBAC_LIST_BACKUP |
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL, NULL,
+					  &def_aci,
+					  RSBAC_MAC_ACI_NETTEMP_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_nettemp,
+					  NULL);
+		if (err) {
+			registration_error(err, "NETTEMP MAC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		struct rsbac_rc_nettemp_aci_t def_aci =
+		    DEFAULT_RC_NETTEMP_ACI;
+
+		list_info_p->version = RSBAC_RC_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_temp_id_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_rc_nettemp_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &nettemp_handles.rc,
+					  list_info_p,
+					  RSBAC_LIST_BACKUP |
+					  RSBAC_LIST_PERSIST |
+					  RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL, NULL,
+					  &def_aci,
+					  RSBAC_RC_ACI_NETTEMP_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_nettemp,
+					  NULL);
+		if (err) {
+			registration_error(err, "NETTEMP RC");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int register_netobj_lists(void)
+#else
+static int __init register_netobj_lists(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	rsbac_pr_debug(ds, "registering local NETOBJ lists\n");
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_netobj_aci_t def_aci =
+		    DEFAULT_MAC_NETOBJ_ACI;
+
+		list_info_p->version = RSBAC_MAC_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_obj_id_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_netobj_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &lnetobj_handles.mac,
+					  list_info_p,
+					  RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_MAC_ACI_LNETOBJ_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_netobj,
+					  NULL);
+		if (err) {
+			registration_error(err, "LNETOBJ MAC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;
+
+		list_info_p->version = RSBAC_RC_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_obj_id_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &lnetobj_handles.rc,
+					  list_info_p,
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_RC_ACI_LNETOBJ_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_netobj,
+					  NULL);
+		if (err) {
+			registration_error(err, "LNETOBJ RC");
+		}
+	}
+#endif
+	rsbac_pr_debug(ds, "registering remote NETOBJ lists\n");
+#if defined(CONFIG_RSBAC_MAC)
+	{
+		struct rsbac_mac_netobj_aci_t def_aci =
+		    DEFAULT_MAC_NETOBJ_ACI;
+
+		list_info_p->version = RSBAC_MAC_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_MAC_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_obj_id_t);
+		list_info_p->data_size =
+		    sizeof(struct rsbac_mac_netobj_aci_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &rnetobj_handles.mac,
+					  list_info_p,
+					  RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_MAC_ACI_RNETOBJ_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_netobj,
+					  NULL);
+		if (err) {
+			registration_error(err, "RNETOBJ MAC");
+		}
+	}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	{
+		rsbac_rc_type_id_t def_aci = RSBAC_RC_GENERAL_TYPE;
+
+		list_info_p->version = RSBAC_RC_NETOBJ_ACI_VERSION;
+		list_info_p->key = RSBAC_RC_NETOBJ_ACI_KEY;
+		list_info_p->desc_size = sizeof(rsbac_net_obj_id_t);
+		list_info_p->data_size = sizeof(rsbac_rc_type_id_t);
+		list_info_p->max_age = 0;
+		err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+					  &rnetobj_handles.rc,
+					  list_info_p,
+					  RSBAC_LIST_AUTO_HASH_RESIZE,
+					  NULL,
+					  NULL,
+					  &def_aci,
+					  RSBAC_RC_ACI_RNETOBJ_NAME,
+					  RSBAC_AUTO_DEV,
+					  1,
+					  rsbac_list_hash_netobj,
+					  NULL);
+		if (err) {
+			registration_error(err, "RNETOBJ RC");
+		}
+	}
+#endif
+
+	rsbac_kfree(list_info_p);
+	return err;
+}
+#endif				/* NET_OBJ */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int rsbac_do_init(void)
+#else
+static int __init rsbac_do_init(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_device_list_item_t *device_p;
+	struct rsbac_device_list_item_t *new_device_p;
+	struct rsbac_list_info_t *list_info_p;
+	struct vfsmount *vfsmount_p;
+	u_int i;
+
+	rsbac_pr_debug(stack, "free stack: %lu\n", rsbac_stack_free_space());
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+#ifdef CONFIG_RSBAC_INIT_DELAY
+	if (rsbac_root_vfsmount_p)
+		vfsmount_p = rsbac_root_vfsmount_p;
+	else
+#endif
+	{
+		spin_lock(&current->fs->lock);
+		vfsmount_p = mntget(current->fs->root.mnt);
+		spin_unlock(&current->fs->lock);
+	}
+	compiled_modules[0] = (char) 0;
+#ifdef CONFIG_RSBAC_REG
+	strcat(compiled_modules, " REG");
+#endif
+#ifdef CONFIG_RSBAC_MAC
+#ifdef CONFIG_RSBAC_MAC_LIGHT
+	strcat(compiled_modules, " MAC-L");
+#else
+	strcat(compiled_modules, " MAC");
+#endif
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+	strcat(compiled_modules, " DAZ");
+#endif
+#ifdef CONFIG_RSBAC_FF
+	strcat(compiled_modules, " FF");
+#endif
+#ifdef CONFIG_RSBAC_RC
+	strcat(compiled_modules, " RC");
+#endif
+#ifdef CONFIG_RSBAC_AUTH
+	strcat(compiled_modules, " AUTH");
+#endif
+#ifdef CONFIG_RSBAC_ACL
+	strcat(compiled_modules, " ACL");
+#endif
+#ifdef CONFIG_RSBAC_CAP
+	strcat(compiled_modules, " CAP");
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+	strcat(compiled_modules, " JAIL");
+#endif
+#ifdef CONFIG_RSBAC_RES
+	strcat(compiled_modules, " RES");
+#endif
+#ifdef CONFIG_RSBAC_PAX
+	strcat(compiled_modules, " PAX");
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+	strcat(compiled_modules, " UDF");
+#endif
+	rsbac_printk(KERN_INFO "rsbac_do_init(): Initializing RSBAC %s on device %02u:%02u\n",
+		     RSBAC_VERSION,
+		     RSBAC_MAJOR(vfsmount_p->mnt_sb->s_dev),
+		     RSBAC_MINOR(vfsmount_p->mnt_sb->s_dev));
+	/* Print banner we are initializing */
+#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+	if (rsbac_nosyslog)
+#endif
+		printk(KERN_INFO
+		       "rsbac_do_init(): Initializing RSBAC %s\n",
+		       RSBAC_VERSION);
+
+	rsbac_printk(KERN_INFO "rsbac_do_init(): compiled modules:%s\n",
+		     compiled_modules);
+
+	device_item_slab = rsbac_slab_create_rcu("rsbac_device_item",
+			sizeof(struct rsbac_device_list_item_t));
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		device_head_p[i] = rsbac_kmalloc_clear_unlocked(sizeof(*device_head_p[i]));
+		if (!device_head_p[i]) {
+			rsbac_printk(KERN_WARNING
+				"rsbac_do_init(): Failed to allocate device_list_heads[%s]\n", i);
+			return -ENOMEM;
+		}
+		spin_lock_init(&device_list_locks[i]);
+		init_srcu_struct(&device_list_srcu[i]);
+		lockdep_set_class(&device_list_locks[i], &device_list_lock_class);
+	}
+
+#if defined(CONFIG_RSBAC_PROC)
+	rsbac_pr_debug(stack, "free stack before registering proc dir: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_printk(KERN_INFO "rsbac_do_init(): Registering RSBAC proc dir\n");
+	register_all_rsbac_proc();
+#endif
+	rsbac_pr_debug(stack, "free stack before get_super: %lu\n",
+		       rsbac_stack_free_space());
+	/* read fd aci from root device */
+	rsbac_pr_debug(ds, "reading aci from device "
+		       "number %02u:%02u\n",
+		       RSBAC_MAJOR(rsbac_root_dev),
+		       RSBAC_MINOR(rsbac_root_dev));
+	/* create a private device item */
+	new_device_p = create_device_item(vfsmount_p);
+	if (!new_device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_do_init(): Could not alloc device item!\n");
+		err = -RSBAC_ECOULDNOTADDDEVICE;
+		goto out;
+	}
+	/* Add new_device_p to device list */
+	/* OK, go on */
+	device_p = add_device_item(new_device_p);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_do_init(): Could not add device!\n");
+		clear_device_item(new_device_p);
+		err = -RSBAC_ECOULDNOTADDDEVICE;
+		goto out;
+	}
+
+	/* init lists - we need the root device_p to be initialized, but no generic list registered */
+	rsbac_printk(KERN_INFO "rsbac_do_init(): Initializing generic lists\n");
+	rsbac_list_init();
+
+	rsbac_pr_debug(stack, "free stack before init_debug: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_debug();
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+	if (rsbac_want_cache(device_p))
+		register_fd_cache_lists(device_p);
+#endif
+
+	rsbac_printk(KERN_INFO "rsbac_do_init(): reading FD attributes from root dev\n");
+	rsbac_pr_debug(stack, "free stack before reading FD lists: %lu\n",
+		       rsbac_stack_free_space());
+
+	/* no locking needed, device_p is known and there can be no parallel init! */
+	if ((err = register_fd_lists(device_p, rsbac_root_dev))) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): File/Dir lists registration failed for dev %02u:%02u, err %s!\n",
+				     RSBAC_MAJOR(rsbac_root_dev),
+				     RSBAC_MINOR(rsbac_root_dev),
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+	rsbac_pr_debug(stack, "free stack before DEV lists registration: %lu\n",
+		       rsbac_stack_free_space());
+	register_dev_lists();
+	rsbac_pr_debug(stack, "free stack before registering IPC lists: %lu\n",
+		       rsbac_stack_free_space());
+	register_ipc_lists();
+	rsbac_pr_debug(stack, "free stack before registering USER lists 1: %lu\n",
+		       rsbac_stack_free_space());
+	register_user_lists1();
+	rsbac_pr_debug(stack, "free stack before registering USER lists 2: %lu\n",
+		       rsbac_stack_free_space());
+	register_user_lists2();
+	rsbac_pr_debug(stack, "free stack before registering PROCESS aci: %lu\n",
+		       rsbac_stack_free_space());
+	register_process_lists();
+
+
+#ifdef CONFIG_RSBAC_UM
+	rsbac_pr_debug(stack, "free stack before GROUP lists registration: %lu\n",
+		       rsbac_stack_free_space());
+	register_group_lists();
+#endif				/* CONFIG_RSBAC_UM */
+
+#ifdef CONFIG_RSBAC_NET_DEV
+	register_netdev_lists();
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+	register_nettemp_list();
+	register_nettemp_aci_lists();
+	register_netobj_lists();
+#endif				/* NET_OBJ */
+
+/* Call other init functions */
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_pr_debug(stack, "free stack before init_mac: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_mac();
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+	rsbac_pr_debug(stack, "free stack before init_daz: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_daz();
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_pr_debug(stack, "free stack before init_rc: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_rc();
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_pr_debug(stack, "free stack before init_auth: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_auth();
+	if (rsbac_auth_enable_login) {
+		struct dentry *t_dentry;
+		struct dentry *dir_dentry = NULL;
+		struct rsbac_auth_fd_aci_t auth_fd_aci =
+		    DEFAULT_AUTH_FD_ACI;
+		rsbac_old_inode_nr_t inode_nr;
+		void * inode_nr_p;
+
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): auth_enable_login is set: setting auth_may_setuid for %s\n",
+			     RSBAC_AUTH_LOGIN_PATH);
+
+		/* lookup filename */
+		if (vfsmount_p) {
+			mutex_lock(&vfsmount_p->mnt_sb->s_root->d_inode->i_mutex);
+			dir_dentry =
+			    rsbac_lookup_one_len(RSBAC_AUTH_LOGIN_PATH_DIR,
+						 vfsmount_p->mnt_sb->s_root,
+						 strlen
+						 (RSBAC_AUTH_LOGIN_PATH_DIR));
+			mutex_unlock(&vfsmount_p->mnt_sb->s_root->d_inode->i_mutex);
+		}
+		if (!dir_dentry) {
+			err = -RSBAC_ENOTFOUND;
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s failed\n",
+				     RSBAC_AUTH_LOGIN_PATH_DIR);
+			goto auth_out;
+		}
+		if (IS_ERR(dir_dentry)) {
+			err = PTR_ERR(dir_dentry);
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s returned %i\n",
+				     RSBAC_AUTH_LOGIN_PATH_DIR, err);
+			goto auth_out;
+		}
+		if (!dir_dentry->d_inode) {
+			err = -RSBAC_ENOTFOUND;
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s failed\n",
+				     RSBAC_AUTH_LOGIN_PATH_DIR);
+			dput(dir_dentry);
+			goto auth_out;
+		}
+
+		mutex_lock(&dir_dentry->d_inode->i_mutex);
+		t_dentry = rsbac_lookup_one_len(RSBAC_AUTH_LOGIN_PATH_FILE,
+						dir_dentry,
+						strlen
+						(RSBAC_AUTH_LOGIN_PATH_FILE));
+		mutex_unlock(&dir_dentry->d_inode->i_mutex);
+
+		if (!t_dentry) {
+			err = -RSBAC_ENOTFOUND;
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s/%s failed\n",
+				     RSBAC_AUTH_LOGIN_PATH_DIR,
+				     RSBAC_AUTH_LOGIN_PATH_FILE);
+			goto auth_out;
+		}
+		if (IS_ERR(t_dentry)) {
+			err = PTR_ERR(t_dentry);
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s/%s returned %i\n",
+				     RSBAC_AUTH_LOGIN_PATH_DIR,
+				     RSBAC_AUTH_LOGIN_PATH_FILE, err);
+			goto auth_out;
+		}
+		if (!t_dentry->d_inode) {
+			err = -RSBAC_ENOTFOUND;
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): call to rsbac_lookup_one_len for /%s/%s failed\n",
+				     RSBAC_AUTH_LOGIN_PATH_DIR,
+				     RSBAC_AUTH_LOGIN_PATH_FILE);
+			dput(t_dentry);
+			goto auth_out;
+		}
+
+		if (!t_dentry->d_inode) {
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): file %s not found\n",
+				     RSBAC_AUTH_LOGIN_PATH);
+			err = -RSBAC_EINVALIDTARGET;
+			goto auth_out_dput;
+		}
+		/* is inode of type file? */
+		if (!S_ISREG(t_dentry->d_inode->i_mode)) {
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): %s is no file\n",
+				     RSBAC_AUTH_LOGIN_PATH);
+			err = -RSBAC_EINVALIDTARGET;
+			goto auth_out_dput;
+		}
+		if (device_p->persist) {
+			inode_nr = t_dentry->d_inode->i_ino;
+			inode_nr_p = &inode_nr;
+		} else
+			inode_nr_p = &t_dentry->d_inode->i_ino;
+		rsbac_list_get_data(device_p->handles.auth,
+				    inode_nr_p,
+				    &auth_fd_aci);
+		auth_fd_aci.auth_may_setuid = TRUE;
+		if (rsbac_list_add(device_p->handles.auth, inode_nr_p, &auth_fd_aci)) {	/* Adding failed! */
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): Could not add AUTH file/dir item!\n");
+			err = -RSBAC_ECOULDNOTADDITEM;
+		}
+
+	      auth_out_dput:
+	      auth_out:
+		{
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_ACL)
+	rsbac_pr_debug(stack, "free stack before init_acl: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_acl();
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+	rsbac_pr_debug(stack, "free stack before init_udf: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_udf();
+#endif
+
+#if defined(CONFIG_RSBAC_UM)
+	rsbac_pr_debug(stack, "free stack before init_um: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_um();
+#endif
+	rsbac_pr_debug(stack, "free stack before init_adf: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_init_adf();
+
+#if defined(CONFIG_RSBAC_PAX) && defined(CONFIG_PAX_HOOK_ACL_FLAGS)
+	pax_set_initial_flags_func = rsbac_pax_set_flags_func;
+#endif
+
+/* Tell that rsbac is initialized                                       */
+	rsbac_allow_mounts = TRUE;
+
+/* Add initrd mount */
+#if 0 && defined(CONFIG_BLK_DEV_INITRD)
+	if (initrd_start) {
+		sb_p = user_get_super(MKDEV(RAMDISK_MAJOR, 0));
+		if (sb_p) {
+			rsbac_mount(sb_p, NULL);
+			drop_super(sb_p);
+		}
+		sb_p = user_get_super(MKDEV(RAMDISK_MAJOR, INITRD_MINOR));
+		if (sb_p) {
+			rsbac_mount(sb_p, NULL);
+			drop_super(sb_p);
+		}
+	}
+#endif
+
+/* Add delayed mounts */
+	if (rsbac_mount_list) {
+		u_int hash;
+		int srcu_idx;
+		struct rsbac_mount_list_t * mount_p = rsbac_mount_list;
+
+		while (mount_p) {
+			/* skip root dev */
+			hash = device_hash(mount_p->vfsmount_p->mnt_sb->s_dev);
+			srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+			device_p = lookup_device(mount_p->vfsmount_p->mnt_sb->s_dev, hash);
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			if(!device_p) {
+				rsbac_printk(KERN_INFO "rsbac_do_init(): mounting delayed device %02u:%02u, fs-type %s\n",
+					MAJOR(mount_p->vfsmount_p->mnt_sb->s_dev),
+					MINOR(mount_p->vfsmount_p->mnt_sb->s_dev),
+					mount_p->vfsmount_p->mnt_sb->s_type->name);
+				rsbac_mount(mount_p->vfsmount_p);
+			} else {
+				mntput(mount_p->vfsmount_p);
+			}
+			rsbac_mount_list = mount_p;
+			mount_p = mount_p->next;
+			kfree(rsbac_mount_list);
+		}
+		rsbac_mount_list = NULL;
+	}
+
+/* Tell that rsbac is initialized                                       */
+	rsbac_initialized = TRUE;
+
+/* Force a check, if configured */
+#ifdef CONFIG_RSBAC_INIT_CHECK
+	rsbac_pr_debug(stack, "free stack before rsbac_check: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_printk(KERN_INFO "rsbac_do_init(): Forcing consistency check.\n");
+	rsbac_check_lists(1);
+#if defined(CONFIG_RSBAC_ACL)
+	rsbac_check_acl(1);
+#endif
+#endif
+
+	if (!current->fs) {
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): current->fs is invalid!\n");
+		err = -RSBAC_EINVALIDPOINTER;
+	} else {
+		err = 0;
+	}
+
+out:
+	/* We are up and running */
+	rsbac_printk(KERN_INFO "rsbac_do_init(): Ready.\n");
+
+	kfree(list_info_p);
+	return err;
+}
+
+
+#ifdef CONFIG_RSBAC_INIT_THREAD
+/* rsbac kernel daemon for init */
+static int rsbac_initd(void *dummy)
+{
+	rsbac_printk(KERN_INFO "rsbac_initd(): Initializing.\n");
+
+/* Dead loop for timeout testing */
+/*    while(1) { } */
+
+	rsbac_pr_debug(stack, "free stack before rsbac_do_init(): %lu\n",
+		       rsbac_stack_free_space());
+	/* init RSBAC */
+	rsbac_do_init();
+
+	rsbac_pr_debug(stack, "free stack after rsbac_do_init(): %lu\n",
+		       rsbac_stack_free_space());
+	/* wake up init process */
+	wake_up(&rsbacd_wait);
+	/* ready */
+	rsbac_printk(KERN_INFO "rsbac_initd(): Exiting.\n");
+	do_exit(0);
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+/* rsbac kernel daemon for auto-write */
+static int rsbacd(void *dummy)
+{
+	struct task_struct *tsk = current;
+	char *name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+	unsigned long list_check_time = jiffies + HZ * rsbac_list_check_interval;
+
+	rsbac_printk(KERN_INFO "rsbacd(): Initializing.\n");
+
+	sys_close(0);
+	sys_close(1);
+	sys_close(2);
+
+	rsbac_pr_debug(auto, "rsbacd(): wake up every %us\n", auto_interval / HZ);
+	rsbac_pr_debug(stack, "free stack: %lu\n", rsbac_stack_free_space());
+	ignore_signals(tsk);
+	wait_event_interruptible_timeout(rsbacd_wait, 0, auto_interval);
+	for (;;) {
+		wait_event_interruptible_timeout(rsbacd_wait, 0, auto_interval);
+#ifdef CONFIG_PM
+		if (try_to_freeze())
+		    continue;
+#endif
+
+		/* Cleanup lists regularly */
+		if (time_after_eq(jiffies, list_check_time)) {
+			list_check_time = jiffies + HZ * rsbac_list_check_interval;
+			rsbac_pr_debug(auto, "cleaning up lists\n");
+			rsbac_check_lists(1);
+		}
+		/* Write lists */
+		if (rsbac_initialized && !rsbac_debug_no_write) {
+			int err = 0;
+			/* rsbac_pr_debug(auto, "calling rsbac_write()\n"); */
+			down(&rsbac_write_sem);
+			if (!rsbac_debug_no_write) {
+				up(&rsbac_write_sem);
+				err = rsbac_write();
+			} else
+				up(&rsbac_write_sem);
+			if (err < 0) {
+				if (name)
+					rsbac_printk(KERN_WARNING "rsbacd(): rsbac_write returned error %s!\n",
+						     get_error_name(name,
+								    err));
+				else
+					rsbac_printk(KERN_WARNING "rsbacd(): rsbac_write returned error %i!\n",
+						     err);
+			} else if (err > 0)
+				rsbac_pr_debug(auto, "rsbac_write() wrote %i "
+					       "lists\n", err);
+		}
+	}
+	return 0;
+}
+#endif
+
+/************************************************* */
+/*               Init function                     */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac_error.h.                 */
+
+struct rsbac_kthread_t {
+	struct list_head list;
+	rsbac_pid_t pid;
+};
+struct rsbac_kthread_t * rsbac_kthread;
+int rsbac_kthread_size_t;
+
+int rsbac_kthreads_init(void)
+{
+	rsbac_kthread_size_t = sizeof(struct rsbac_kthread_t);
+	rsbac_kthread = kmalloc(rsbac_kthread_size_t, GFP_ATOMIC);
+	INIT_LIST_HEAD(&rsbac_kthread->list);
+	return 0;
+}
+
+int rsbac_mark_kthread(rsbac_pid_t pid)
+{
+	struct rsbac_kthread_t * rsbac_kthread_new;
+
+	if (rsbac_initialized)
+		return 0;
+	rsbac_kthread_new = kmalloc(rsbac_kthread_size_t, GFP_ATOMIC);
+	rsbac_kthread_new->pid = pid;
+	list_add(&rsbac_kthread_new->list, &rsbac_kthread->list);
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init(kdev_t root_dev)
+#else
+int __init rsbac_init(kdev_t root_dev)
+#endif
+{
+#ifdef CONFIG_RSBAC_RC
+	struct rsbac_rc_process_aci_t rc_init_p_aci = DEFAULT_RC_P_INIT_ACI;
+#endif
+#ifdef CONFIG_RSBAC_INIT_THREAD
+	struct task_struct * rsbac_init_thread;
+#endif
+	struct task_struct * rsbacd_thread;
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC)
+	rsbac_pid_t init_pid;
+	struct rsbac_kthread_t * rsbac_kthread_entry;
+	struct list_head * p;
+#endif
+
+#if  defined(CONFIG_RSBAC_AUTO_WRITE) \
+   || defined(CONFIG_RSBAC_INIT_THREAD) || defined(CONFIG_RSBAC_NO_WRITE)
+	rsbac_pid_t rsbacd_pid;
+#endif
+
+	if (rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_init(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+	if (!current->fs) {
+		rsbac_printk(KERN_WARNING "rsbac_init(): current->fs is invalid!\n");
+		return -RSBAC_EINVALIDPOINTER;
+	}
+
+	rsbac_root_dev = root_dev;
+
+#if  (defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)) \
+   || defined(CONFIG_RSBAC_INIT_THREAD)
+	/* init the rsbacd wait queue head */
+	init_waitqueue_head(&rsbacd_wait);
+#endif
+
+#ifdef CONFIG_RSBAC_INIT_THREAD
+/* trigger dependency */
+#ifdef CONFIG_RSBAC_MAX_INIT_TIME
+#endif
+	rsbac_printk(KERN_INFO "rsbac_init(): Setting init timeout to %u seconds (%u jiffies).\n",
+		     RSBAC_MAX_INIT_TIME, RSBAC_MAX_INIT_TIME * HZ);
+
+/* Start rsbac thread for init */
+	rsbac_init_thread = kthread_create(rsbac_initd, NULL, "rsbac_initd");
+	if (IS_ERR(rsbac_init_thread))
+		goto panic;
+	rsbacd_pid = task_pid(rsbac_init_thread);
+	wake_up_process(rsbac_init_thread);
+	rsbac_printk(KERN_INFO "rsbac_init(): Started rsbac_initd thread with pid %u\n",
+		     pid_nr(rsbacd_pid));
+
+	if (!wait_event_interruptible_timeout(rsbacd_wait, rsbac_initialized, RSBAC_MAX_INIT_TIME * HZ)) {
+		rsbac_printk(KERN_ERR
+			     "rsbac_init(): *** RSBAC init timed out - RSBAC not correctly initialized! ***\n");
+		rsbac_printk(KERN_ERR
+			     "rsbac_init(): *** Killing rsbac_initd! ***\n");
+		sys_kill(pid_nr(rsbacd_pid), SIGKILL);
+		rsbac_initialized = FALSE;
+	}
+#else
+	rsbac_do_init();
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+	if (rsbac_initialized) {
+		/* Start rsbacd thread for auto write */
+		rsbacd_thread = kthread_create(rsbacd, NULL, "rsbacd");
+		if (IS_ERR(rsbacd_thread)) {
+			rsbac_printk(KERN_ERR
+				     "rsbac_init(): *** Starting rsbacd thread failed with error %i! ***\n",
+				     PTR_ERR(rsbacd_thread));
+		} else {
+			rsbacd_pid = task_pid(rsbacd_thread);
+			wake_up_process(rsbacd_thread);
+			rsbac_printk(KERN_INFO "rsbac_init(): Started rsbacd thread with pid %u\n",
+				     pid_nr(rsbacd_pid));
+		}
+	}
+#endif
+
+/* Ready. */
+/*    schedule(); */
+#ifdef CONFIG_RSBAC_INIT_THREAD
+	sys_wait4(-1, NULL, WNOHANG, NULL);
+#endif
+
+/* Add all processes to list of processes as init processes */
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC)
+	{
+#ifdef CONFIG_RSBAC_MAC
+		struct rsbac_mac_user_aci_t * mac_u_aci_p;
+#endif
+#ifdef CONFIG_RSBAC_RC
+		struct rsbac_rc_user_aci_t * rc_u_aci_p;
+#endif
+		rsbac_uid_t user = RSBAC_SYSADM_UID;
+		rsbac_pid_t pid = find_pid_ns(1, &init_pid_ns);
+		struct task_struct *p;
+
+#ifdef CONFIG_RSBAC_RC
+		union rsbac_target_id_t k_tid;
+		union rsbac_attribute_value_t k_attr_val;
+#endif
+
+		rsbac_printk(KERN_INFO "rsbac_init(): Adjusting attributes of existing processes\n");
+/* Prepare entries: change standard values to root's values */
+#ifdef CONFIG_RSBAC_MAC
+		mac_u_aci_p = rsbac_kmalloc_unlocked(sizeof(*mac_u_aci_p));
+		if (mac_u_aci_p) {
+			if(!rsbac_list_get_data
+				(user_handles.mac, &user, mac_u_aci_p)) {
+				mac_init_p_aci.owner_sec_level =
+				    mac_u_aci_p->security_level;
+				mac_init_p_aci.owner_initial_sec_level =
+				    mac_u_aci_p->initial_security_level;
+				mac_init_p_aci.current_sec_level =
+				    mac_u_aci_p->initial_security_level;
+				mac_init_p_aci.owner_min_sec_level =
+				    mac_u_aci_p->min_security_level;
+				mac_init_p_aci.mac_owner_categories =
+				    mac_u_aci_p->mac_categories;
+				mac_init_p_aci.mac_owner_initial_categories =
+				    mac_u_aci_p->mac_initial_categories;
+				mac_init_p_aci.mac_curr_categories =
+				    mac_u_aci_p->mac_initial_categories;
+				mac_init_p_aci.mac_owner_min_categories =
+				    mac_u_aci_p->mac_min_categories;
+				mac_init_p_aci.min_write_open =
+				    mac_u_aci_p->security_level;
+				mac_init_p_aci.max_read_open =
+				    mac_u_aci_p->min_security_level;
+				mac_init_p_aci.min_write_categories =
+				    mac_u_aci_p->mac_categories;
+				mac_init_p_aci.max_read_categories =
+				    mac_u_aci_p->mac_min_categories;
+				mac_init_p_aci.mac_process_flags =
+				    (mac_u_aci_p->
+				     mac_user_flags & RSBAC_MAC_P_FLAGS) |
+				    RSBAC_MAC_DEF_INIT_P_FLAGS;
+			}
+			rsbac_kfree(mac_u_aci_p);
+		}
+#endif
+
+/* Set process aci - first init */
+#ifdef CONFIG_RSBAC_MAC
+		if (rsbac_list_add
+		    (process_handles.mac, &pid,
+		     &mac_init_p_aci))
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): MAC ACI for Init process 1 could not be added!");
+#endif
+#ifdef CONFIG_RSBAC_RC
+		/* Get boot role */
+		if (rsbac_rc_get_boot_role(&rc_init_p_aci.rc_role)) {	/* none: use root's role */
+			rc_u_aci_p = rsbac_kmalloc_unlocked(sizeof(*rc_u_aci_p));
+			if (rc_u_aci_p) {
+				if (!rsbac_list_get_data
+				    (user_handles.rc, &user, rc_u_aci_p)) {
+					rc_init_p_aci.rc_role = rc_u_aci_p->rc_role;
+				} else {	/* last resort: general role */
+					rsbac_ds_get_error("rsbac_do_init",
+							   A_rc_def_role);
+					rc_init_p_aci.rc_role =
+					    RSBAC_RC_GENERAL_ROLE;
+				}
+				rsbac_kfree(rc_u_aci_p);
+			}
+		}
+		rc_kernel_p_aci.rc_role = rc_init_p_aci.rc_role;
+		if (rsbac_list_add
+		    (process_handles.rc, &pid,
+		     &rc_init_p_aci))
+			rsbac_printk(KERN_WARNING "rsbac_do_init(): RC ACI for Init process 1 could not be added!");
+#endif
+		read_lock(&tasklist_lock);
+		for_each_process(p)
+		{
+			/* not for kernel and init though... */
+			if ((!p->pid) || (p->pid == 1))
+				continue;
+			pid = task_pid(p);
+			rsbac_pr_debug(ds, "setting aci for process %u (%s)\n", pid, p->comm);
+#ifdef CONFIG_RSBAC_MAC
+			if (rsbac_list_add
+			    (process_handles.mac, &pid,
+			     &mac_init_p_aci))
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): MAC ACI for Init process %u could not be added!\n",
+					     pid);
+#endif
+#ifdef CONFIG_RSBAC_RC
+			k_tid.process = pid;
+			if (rsbac_get_attr(SW_GEN, T_PROCESS,
+					k_tid,
+					A_kernel_thread,
+					&k_attr_val,
+					FALSE)) {
+				rsbac_printk(KERN_WARNING "rsbac_do_init(): RC ACI for Kernel thread %u could not be added!\n", pid);
+			}
+			if (k_attr_val.kernel_thread) {
+				if (rsbac_list_add
+				    (process_handles.rc,
+				     &pid, &rc_kernel_p_aci))
+					rsbac_printk(KERN_WARNING "rsbac_do_init(): RC ACI for Kernel thread %u could not be added!\n",
+					     pid);
+		}
+#endif
+		}
+		read_unlock(&tasklist_lock);
+	}
+	list_for_each(p, &rsbac_kthread->list) {
+		rsbac_kthread_entry = list_entry(p, 
+				struct rsbac_kthread_t, list);
+		if (pid_nr(rsbac_kthread_entry->pid) != 1 
+				&& rsbac_kthread_entry->pid != rsbacd_pid)
+		{
+			read_lock(&tasklist_lock);
+			if(pid_task(rsbac_kthread_entry->pid, PIDTYPE_PID)) {
+				read_unlock(&tasklist_lock);
+				rsbac_kthread_notify(rsbac_kthread_entry->pid);
+			}
+			else {
+				read_unlock(&tasklist_lock);
+				rsbac_pr_debug(ds, "rsbac_do_init(): skipping gone away pid %u\n",
+					pid_nr(rsbac_kthread_entry->pid));
+			}
+			/* kernel list implementation is for exclusive 
+			 * wizards use, let's not free it now till 
+			 * i know why it oops. consume about no 
+			 * memory anyway. michal.
+			 */
+			
+			/* list_del(&rsbac_kthread_entry->list);
+			 * kfree(rsbac_kthread_entry);*/
+		}
+	} /* explicitly mark init and rsbacd */
+	init_pid = find_pid_ns(1, &init_pid_ns);
+#ifdef CONFIG_RSBAC_MAC
+	if (rsbac_list_add(process_handles.mac, &init_pid, &mac_init_p_aci))
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): MAC ACI for \"init\" process could not be added!");
+        if (rsbac_list_add(process_handles.mac, &rsbacd_pid, &mac_init_p_aci))
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): MAC ACI for \"rsbacd\" process could not be added!");
+#endif
+#ifdef CONFIG_RSBAC_RC
+	if (rsbac_list_add(process_handles.rc, &init_pid, &rc_init_p_aci))
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): RC ACI for \"init\" process could not be added");
+        if (rsbac_list_add(process_handles.rc, &rsbacd_pid, &rc_kernel_p_aci))
+		rsbac_printk(KERN_WARNING "rsbac_do_init(): RC ACI for \"rsbacd\" process could not be added");
+#endif
+	
+	/*kfree(rsbac_kthread);*/
+#endif	/* MAC or RC */
+
+	rsbac_printk(KERN_INFO "rsbac_init(): Ready.\n");
+	return 0;
+
+#ifdef CONFIG_RSBAC_INIT_THREAD
+panic:
+	rsbac_printk(KERN_ERR "rsbac_init(): *** RSBAC init failed to start - RSBAC not correctly initialized! ***\n");
+	/* let's panic - but only when in secure mode, warn otherwise */
+#ifdef CONFIG_RSBAC_SOFTMODE
+	if (!rsbac_softmode)
+#endif
+		panic("RSBAC: rsbac_init(): *** Unable to initialize - PANIC ***\n");
+	return -RSBAC_EINVALIDVALUE;
+#endif
+}
+
+int rsbac_kthread_notify(rsbac_pid_t pid)
+{
+	if (!rsbac_initialized)
+		return 0;
+//	rsbac_printk(KERN_DEBUG "rsbac_kthread_notify: marking pid %u!\n",
+//		     pid);
+/* Set process aci */
+#ifdef CONFIG_RSBAC_MAC
+	if (rsbac_list_add
+	    (process_handles.mac, &pid, &mac_init_p_aci))
+		rsbac_printk(KERN_WARNING "rsbac_kthread_notify(): MAC ACI for kernel process %u could not be added!",
+			     pid_nr(pid));
+#endif
+#ifdef CONFIG_RSBAC_RC
+	if (rsbac_list_add
+	    (process_handles.rc, &pid, &rc_kernel_p_aci))
+		rsbac_printk(KERN_WARNING "rsbac_kthread_notify(): RC ACI for kernel process %u could not be added!",
+			     pid_nr(pid));
+#endif
+	return 0;
+}
+
+/* When mounting a device, its ACI must be read and added to the ACI lists. */
+
+EXPORT_SYMBOL(rsbac_mount);
+int rsbac_mount(struct vfsmount * vfsmount_p)
+{
+	int err = 0;
+	struct rsbac_device_list_item_t *device_p;
+	struct rsbac_device_list_item_t *new_device_p;
+	rsbac_boolean_t old_no_write;
+	u_int hash;
+	int srcu_idx;
+
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mount(): called from interrupt, process %u(%s)!\n",
+				current->pid, current->comm);
+		return -RSBAC_EFROMINTERRUPT;
+	}
+	if (!vfsmount_p || !vfsmount_p->mnt_sb) {
+		rsbac_printk(KERN_WARNING "rsbac_mount(): called with NULL pointer\n");
+		return -RSBAC_EINVALIDPOINTER;
+	}
+	if (!rsbac_allow_mounts) {
+		struct rsbac_mount_list_t * mount_p;
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+		if (!RSBAC_MAJOR(rsbac_delayed_root)
+		    && !RSBAC_MINOR(rsbac_delayed_root)
+		    && rsbac_delayed_root_str[0]
+		    ) {		/* translate string to kdev_t */
+			char *p = rsbac_delayed_root_str;
+			u_int major = 0;
+			u_int minor = 0;
+
+			major = simple_strtoul(p, NULL, 0);
+			while ((*p != ':') && (*p != '\0'))
+				p++;
+			if (*p) {
+				p++;
+				minor = simple_strtoul(p, NULL, 0);
+			}
+			rsbac_delayed_root = RSBAC_MKDEV(major, minor);
+		}
+		if (!rsbac_no_delay_init
+		    && ((!RSBAC_MAJOR(rsbac_delayed_root)
+			 && !RSBAC_MINOR(rsbac_delayed_root)
+			 && (MAJOR(vfsmount_p->mnt_sb->s_dev) > 1)
+			)
+			|| ((RSBAC_MAJOR(rsbac_delayed_root)
+			     || RSBAC_MINOR(rsbac_delayed_root)
+			    )
+			    &&
+			    ((MAJOR(vfsmount_p->mnt_sb->s_dev) ==
+			      RSBAC_MAJOR(rsbac_delayed_root))
+			     && (!RSBAC_MINOR(rsbac_delayed_root)
+				 || (MINOR(vfsmount_p->mnt_sb->s_dev) ==
+				     RSBAC_MINOR(rsbac_delayed_root))
+			     )
+			    )
+			)
+		    )
+		    ) {
+			if (RSBAC_MAJOR(rsbac_delayed_root)
+			    || RSBAC_MINOR(rsbac_delayed_root)) {
+				rsbac_printk(KERN_INFO "rsbac_mount(): forcing delayed RSBAC init on DEV %02u:%02u, matching %02u:%02u!\n",
+					     MAJOR(vfsmount_p->mnt_sb->s_dev),
+					     MINOR(vfsmount_p->mnt_sb->s_dev),
+					     RSBAC_MAJOR
+					     (rsbac_delayed_root),
+					     RSBAC_MINOR
+					     (rsbac_delayed_root));
+			} else {
+				rsbac_printk(KERN_INFO "rsbac_mount(): forcing delayed RSBAC init on DEV %02u:%02u!\n",
+					     MAJOR(vfsmount_p->mnt_sb->s_dev),
+					     MINOR(vfsmount_p->mnt_sb->s_dev));
+			}
+			rsbac_root_vfsmount_p = vfsmount_p;
+			rsbac_init(vfsmount_p->mnt_sb->s_dev);
+			return 0;
+		}
+#endif
+
+		rsbac_printk(KERN_WARNING "rsbac_mount(): RSBAC not initialized while mounting DEV %02u:%02u, fs-type %s, delaying\n",
+				MAJOR(vfsmount_p->mnt_sb->s_dev), MINOR(vfsmount_p->mnt_sb->s_dev),
+				vfsmount_p->mnt_sb->s_type->name);
+		mount_p = kmalloc(sizeof(*mount_p), GFP_KERNEL);
+		if (mount_p) {
+			mount_p->vfsmount_p = mntget(vfsmount_p);
+			mount_p->next = rsbac_mount_list;
+			rsbac_mount_list = mount_p;
+		}
+
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(ds, "mounting device %02u:%02u\n",
+		       MAJOR(vfsmount_p->mnt_sb->s_dev), MINOR(vfsmount_p->mnt_sb->s_dev));
+	rsbac_pr_debug(stack, "free stack: %lu\n", rsbac_stack_free_space());
+	down(&rsbac_write_sem);
+	old_no_write = rsbac_debug_no_write;
+	rsbac_debug_no_write = TRUE;
+	up(&rsbac_write_sem);
+	hash = device_hash(vfsmount_p->mnt_sb->s_dev);
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(vfsmount_p->mnt_sb->s_dev, hash);
+	/* repeated mount? */
+	if (device_p) {
+		rsbac_printk(KERN_INFO "rsbac_mount: repeated mount %u of device %02u:%02u\n",
+			     device_p->mount_count, MAJOR(vfsmount_p->mnt_sb->s_dev),
+			     MINOR(vfsmount_p->mnt_sb->s_dev));
+		device_p->mount_count++;
+		if (!device_p->vfsmount_p)
+			device_p->vfsmount_p = mntget(vfsmount_p);
+		else
+		        if (   real_mount(device_p->vfsmount_p)->mnt_mountpoint
+		            && (real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb->s_dev == device_p->vfsmount_p->mnt_sb->s_dev)
+		    	   ) {
+				mntput(device_p->vfsmount_p);
+				device_p->vfsmount_p = mntget(vfsmount_p);
+		        }
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	} else {
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		/* OK, go on */
+		new_device_p = create_device_item(vfsmount_p);
+		rsbac_pr_debug(stack, "after creating device item: free stack: %lu\n",
+			       rsbac_stack_free_space());
+		if (!new_device_p) {
+			rsbac_debug_no_write = old_no_write;
+			return -RSBAC_ECOULDNOTADDDEVICE;
+		}
+
+		srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+		/* make sure to only add, if this device item has not been added in the meantime */
+		device_p = lookup_device(vfsmount_p->mnt_sb->s_dev, hash);
+		if (device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_mount(): mount race for device %02u:%02u detected!\n",
+				     MAJOR(vfsmount_p->mnt_sb->s_dev),
+				     MINOR(vfsmount_p->mnt_sb->s_dev));
+			device_p->mount_count++;
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			clear_device_item(new_device_p);
+		} else {
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			device_p = add_device_item(new_device_p);
+			if (!device_p) {
+				rsbac_printk(KERN_WARNING "rsbac_mount: adding device %02u:%02u failed!\n",
+					     MAJOR(vfsmount_p->mnt_sb->s_dev),
+					     MINOR(vfsmount_p->mnt_sb->s_dev));
+				clear_device_item(new_device_p);
+				rsbac_debug_no_write = old_no_write;
+				return -RSBAC_ECOULDNOTADDDEVICE;
+			}
+
+			mntget(device_p->vfsmount_p);
+		}
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+		if (rsbac_want_cache(new_device_p))
+			register_fd_cache_lists(new_device_p);
+#endif
+
+		/* we do not lock device head - we know the device_p and hope for the best... */
+		/* also, we are within kernel mount sem */
+		if ((err = register_fd_lists(new_device_p, vfsmount_p->mnt_sb->s_dev))) {
+			char *tmp;
+
+			tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "rsbac_mount(): File/Dir ACI registration failed for dev %02u:%02u, err %s!\n",
+					     MAJOR(vfsmount_p->mnt_sb->s_dev),
+					     MINOR(vfsmount_p->mnt_sb->s_dev),
+					     get_error_name(tmp, err));
+				rsbac_kfree(tmp);
+			}
+		}
+		rsbac_pr_debug(stack, "after registering fd lists: free stack: %lu\n",
+			       rsbac_stack_free_space());
+	}
+
+/* call other mount functions */
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_mount_mac(vfsmount_p->mnt_sb->s_dev);
+	rsbac_pr_debug(stack, "after mount_mac: free stack: %lu\n",
+		       rsbac_stack_free_space());
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_mount_auth(vfsmount_p->mnt_sb->s_dev);
+	rsbac_pr_debug(stack, "after mount_auth: free stack: %lu\n",
+		       rsbac_stack_free_space());
+#endif
+#if defined(CONFIG_RSBAC_ACL)
+	rsbac_mount_acl(vfsmount_p->mnt_sb->s_dev);
+	rsbac_pr_debug(stack, "after mount_acl: free stack: %lu\n",
+		       rsbac_stack_free_space());
+#endif
+#if defined(CONFIG_RSBAC_REG)
+	rsbac_mount_reg(vfsmount_p->mnt_sb->s_dev);
+	rsbac_pr_debug(stack, "after mount_reg: free stack: %lu\n",
+		       rsbac_stack_free_space());
+#endif				/* REG */
+
+	rsbac_debug_no_write = old_no_write;
+	return err;
+}
+
+/* When umounting a device, its ACI must be removed from the ACI lists.     */
+/* Removing the device ACI should be no problem.                            */
+
+EXPORT_SYMBOL(rsbac_umount);
+int rsbac_umount(struct vfsmount *vfsmount_p)
+{
+	struct rsbac_device_list_item_t *device_p;
+	kdev_t kdev;
+	u_int hash;
+
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_umount(): called from interrupt, process %u(%s)!\n",
+				current->pid, current->comm);
+		return -RSBAC_EFROMINTERRUPT;
+	}
+	if (!vfsmount_p) {
+		rsbac_printk(KERN_WARNING "rsbac_umount(): called with NULL pointer\n");
+		return -RSBAC_EINVALIDPOINTER;
+	}
+	if (!rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_umount(): RSBAC not initialized\n");
+		if (rsbac_mount_list) {
+			struct rsbac_mount_list_t * mount_p;
+			struct rsbac_mount_list_t * prev_mount_p;
+
+			mount_p = rsbac_mount_list;
+			prev_mount_p = NULL;
+			while (mount_p) {
+				if (mount_p->vfsmount_p == vfsmount_p) {
+					mntput(vfsmount_p);
+					rsbac_printk(KERN_WARNING "rsbac_umount(): found delayed mount for device %02u:%02u, removing\n",
+							RSBAC_MAJOR(vfsmount_p->mnt_sb->s_dev), RSBAC_MINOR(vfsmount_p->mnt_sb->s_dev));
+					if (prev_mount_p) {
+						prev_mount_p->next = mount_p->next;
+						kfree (mount_p);
+						mount_p = prev_mount_p->next;
+					} else {
+						rsbac_mount_list = mount_p->next;
+						kfree (mount_p);
+						mount_p = rsbac_mount_list;
+					}
+				} else {
+					prev_mount_p = mount_p;
+					mount_p = mount_p->next;
+				}
+			}
+		}
+
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	kdev = vfsmount_p->mnt_sb->s_dev;
+	rsbac_pr_debug(ds, "umounting device %02u:%02u\n",
+		       MAJOR(kdev), MINOR(kdev));
+
+	/* sync attribute lists */
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+	if (!rsbac_debug_no_write) {
+		down(&rsbac_write_sem);
+		/* recheck no_write with lock - might have been set in between */
+		if (!rsbac_debug_no_write) {
+			up(&rsbac_write_sem);
+			rsbac_write();
+		} else
+			up(&rsbac_write_sem);
+	}
+#endif
+/* call other umount functions */
+#if defined(CONFIG_RSBAC_MAC)
+	rsbac_umount_mac(kdev);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_umount_auth(kdev);
+#endif
+#if defined(CONFIG_RSBAC_ACL)
+	rsbac_umount_acl(kdev);
+#endif
+#if defined(CONFIG_RSBAC_REG)
+	rsbac_umount_reg(kdev);
+#endif
+
+	hash = device_hash(kdev);
+	/* wait for write access to device_list_head */
+	spin_lock(&device_list_locks[hash]);
+	while (!RSBAC_IS_AUTO_DEV(umount_device_in_progress)) {
+		DECLARE_WAIT_QUEUE_HEAD(auto_wait);
+
+		spin_unlock(&device_list_locks[hash]);
+		wait_event_interruptible_timeout(auto_wait, !RSBAC_IS_AUTO_DEV(umount_device_in_progress), HZ);
+		spin_lock(&device_list_locks[hash]);
+	}
+	umount_device_in_progress = kdev;
+	device_p = lookup_device_locked(kdev, hash);
+	if (device_p) {
+		if (device_p->mount_count == 1) {
+			/* remove_device_item unlocks device_list_locks[hash]! */
+			remove_device_item(kdev);
+#ifdef CONFIG_RSBAC_FD_CACHE
+			unregister_fd_cache_lists(device_p);
+#endif
+			aci_detach_fd_lists(device_p);
+			if (device_p->vfsmount_p)
+				mntput(device_p->vfsmount_p);
+			clear_device_item(device_p);
+			spin_lock(&device_list_locks[hash]);
+		} else {
+			if (device_p->mount_count > 1) {
+				device_p->mount_count--;
+				if (device_p->vfsmount_p == vfsmount_p) {
+					if (device_p->rsbac_dir_dentry_p) {
+						down(&rsbac_write_sem);
+						dput(device_p->rsbac_dir_dentry_p);
+						device_p->rsbac_dir_dentry_p = NULL;
+						up(&rsbac_write_sem);
+					}
+					device_p->vfsmount_p = NULL;
+					spin_unlock(&device_list_locks[hash]);
+					mntput(vfsmount_p);
+					rsbac_printk(KERN_WARNING "rsbac_umount: removed primary mount for device %02u:%02u, inheritance broken!\n",
+						     RSBAC_MAJOR(kdev),
+						     RSBAC_MINOR(kdev));
+					spin_lock(&device_list_locks[hash]);
+				}
+			} else {
+				rsbac_printk(KERN_WARNING "rsbac_umount: device %02u:%02u has mount_count < 1!\n",
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev));
+			}
+		}
+	}
+	umount_device_in_progress = RSBAC_AUTO_DEV;
+	spin_unlock(&device_list_locks[hash]);
+
+	return 0;
+}
+
+/* On pivot_root, we must unblock the dentry tree of the old root */
+/* by putting all cached rsbac.dat dentries */
+
+int rsbac_free_dat_dentries(void)
+{
+	struct rsbac_device_list_item_t *device_p;
+	u_int i;
+
+	if (!rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_free_dat_dentry(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+
+	rsbac_printk(KERN_INFO "rsbac_free_dat_dentry(): freeing dat dir dentries\n");
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		spin_lock(&device_list_locks[i]);
+		device_p = device_head_p[i]->head;
+		while (device_p) {
+			if (device_p->rsbac_dir_dentry_p) {
+				dput(device_p->rsbac_dir_dentry_p);
+				device_p->rsbac_dir_dentry_p = NULL;
+			}
+			device_p = device_p->next;
+		}
+		spin_unlock(&device_list_locks[i]);
+	}
+	return 0;
+}
+
+/***************************************************/
+/* We also need some status information...         */
+
+int rsbac_stats(void)
+{
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	long fd_count;
+	u_long fd_sum = 0;
+	u_long dev_sum = 0;
+	u_long ipc_sum = 0;
+	u_long user_sum = 0;
+	u_long process_sum = 0;
+#if defined(CONFIG_RSBAC_UM)
+	u_long group_sum = 0;
+#endif
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	u_long nettemp_sum = 0;
+	u_long lnetobj_sum = 0;
+	u_long rnetobj_sum = 0;
+#endif
+	u_long total_sum = 0;
+	long tmp_count = 0;
+	u_int i;
+	int srcu_idx;
+
+	if (!rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_stats(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+		while (device_p) {	/* for all sublists */
+			fd_count = rsbac_list_count(device_p->handles.gen);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu GEN", fd_count);
+				fd_sum += fd_count;
+			}
+
+#if defined(CONFIG_RSBAC_MAC)
+			fd_count = rsbac_list_count(device_p->handles.mac);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu MAC", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+			fd_count = rsbac_list_count(device_p->handles.daz);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu DAZ", fd_count);
+				fd_sum += fd_count;
+			}
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+			fd_count = rsbac_list_count(device_p->handles.dazs);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu DAZ SCANNED", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+			fd_count = rsbac_list_count(device_p->handles.ff);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu FF", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+			fd_count = rsbac_list_count(device_p->handles.rc);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu RC", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+			fd_count = rsbac_list_count(device_p->handles.auth);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu AUTH", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+			fd_count = rsbac_list_count(device_p->handles.cap);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu CAP", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+#if defined(CONFIG_RSBAC_RES)
+			fd_count = rsbac_list_count(device_p->handles.res);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu RES", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+			fd_count = rsbac_list_count(device_p->handles.pax);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu PAX", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+			fd_count = rsbac_list_count(device_p->handles.udf);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu UDF", fd_count);
+				fd_sum += fd_count;
+			}
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+			fd_count = rsbac_list_count(device_p->handles.udfc);
+			if (fd_count > 0) {
+				rsbac_printk(", %lu UDF CHECKED", fd_count);
+				fd_sum += fd_count;
+			}
+#endif
+#endif
+
+			rsbac_printk("\n");
+			device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+		}
+		tmp_count += device_head_p[i]->count;
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+	rsbac_printk(KERN_INFO "rsbac_stats(): Sum of %u Devices with %lu fd-items\n",
+		     tmp_count, fd_sum);
+	/* free access to device_list_head */
+	total_sum += fd_sum;
+
+	/* dev lists */
+	tmp_count = rsbac_list_count(dev_handles.gen);
+	rsbac_printk(KERN_INFO "DEV items: %lu GEN", tmp_count);
+	dev_sum += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(dev_handles.mac);
+	rsbac_printk(", %lu MAC", tmp_count);
+	dev_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(dev_major_handles.rc);
+	rsbac_printk(", %lu major RC", tmp_count);
+	dev_sum += tmp_count;
+	tmp_count = rsbac_list_count(dev_handles.rc);
+	rsbac_printk(", %lu RC", tmp_count);
+	dev_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu DEV items\n", dev_sum);
+	total_sum += dev_sum;
+
+	/* ipc lists */
+	rsbac_printk(KERN_INFO "IPC items: no GEN");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(ipc_handles.mac);
+	rsbac_printk(", %lu MAC", tmp_count);
+	ipc_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(ipc_handles.rc);
+	rsbac_printk(", %lu RC", tmp_count);
+	ipc_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_list_count(ipc_handles.jail);
+	rsbac_printk(", %lu JAIL", tmp_count);
+	ipc_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu IPC items\n", ipc_sum);
+	total_sum += ipc_sum;
+
+	/* user lists */
+	tmp_count = rsbac_list_count(user_handles.gen);
+	rsbac_printk(KERN_INFO "USER items: %lu GEN", tmp_count);
+	user_sum += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(user_handles.mac);
+	rsbac_printk(", %lu MAC", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	tmp_count = rsbac_list_count(user_handles.daz);
+	rsbac_printk(", %lu DAZ", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(user_handles.rc);
+	rsbac_printk(", %lu RC", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	tmp_count = rsbac_list_count(user_handles.auth);
+	rsbac_printk(", %lu AUTH", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	tmp_count = rsbac_list_count(user_handles.cap);
+	rsbac_printk(", %lu CAP", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_list_count(user_handles.jail);
+	rsbac_printk(", %lu JAIL", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	tmp_count = rsbac_list_count(user_handles.res);
+	rsbac_printk(", %lu RES", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	tmp_count = rsbac_list_count(user_handles.pax);
+	rsbac_printk(", %lu PAX", tmp_count);
+	user_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	tmp_count = rsbac_list_count(user_handles.udf);
+	rsbac_printk(", %lu UDF", tmp_count);
+	user_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu USER items\n", user_sum);
+	total_sum += user_sum;
+
+	/* process lists */
+	tmp_count = rsbac_list_count(process_handles.gen);
+	rsbac_printk(KERN_INFO "PROCESS items: %lu GEN", tmp_count);
+	process_sum += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(process_handles.mac);
+	rsbac_printk(", %lu MAC", tmp_count);
+	process_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	tmp_count = rsbac_list_count(process_handles.daz);
+	rsbac_printk(", %lu DAZ", tmp_count);
+	process_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(process_handles.rc);
+	rsbac_printk(", %lu RC", tmp_count);
+	process_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	tmp_count = rsbac_list_count(process_handles.auth);
+	rsbac_printk(", %lu AUTH", tmp_count);
+	process_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	tmp_count = rsbac_list_count(process_handles.cap);
+	rsbac_printk(", %lu CAP", tmp_count);
+	process_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_list_count(process_handles.jail);
+	rsbac_printk(", %lu JAIL", tmp_count);
+	process_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	tmp_count = rsbac_list_count(process_handles.udf);
+	rsbac_printk(", %lu UDF", tmp_count);
+	process_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu PROCESS items\n", process_sum);
+	total_sum += process_sum;
+
+#if defined(CONFIG_RSBAC_UM)
+	/* group lists */
+	rsbac_printk(KERN_INFO "GROUP items: ");
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	tmp_count = rsbac_list_count(group_handles.rc);
+	rsbac_printk("%lu RC", tmp_count);
+	user_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu GROUP items\n", group_sum);
+	total_sum += group_sum;
+#endif
+
+#if defined(CONFIG_RSBAC_NET_OBJ)
+	/* nettemp lists */
+	rsbac_printk(KERN_INFO "NETTEMP items: ");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(nettemp_handles.mac);
+	rsbac_printk("%lu MAC, ", tmp_count);
+	nettemp_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(nettemp_handles.rc);
+	rsbac_printk("%lu RC, ", tmp_count);
+	nettemp_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu NETTEMP items\n", nettemp_sum);
+	total_sum += nettemp_sum;
+
+	/* local netobj lists */
+	rsbac_printk(KERN_INFO "Local NETOBJ items:");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(lnetobj_handles.mac);
+	rsbac_printk(" %lu MAC,", tmp_count);
+	lnetobj_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(lnetobj_handles.rc);
+	rsbac_printk(" %lu RC", tmp_count);
+	lnetobj_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu Local NETOBJ items\n",
+		     lnetobj_sum);
+	total_sum += lnetobj_sum;
+
+	/* remote netobj lists */
+	rsbac_printk(KERN_INFO "Remote NETOBJ items:");
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_list_count(rnetobj_handles.mac);
+	rsbac_printk(" %lu MAC,", tmp_count);
+	rnetobj_sum += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_list_count(rnetobj_handles.rc);
+	rsbac_printk(" %lu RC", tmp_count);
+	rnetobj_sum += tmp_count;
+#endif
+	rsbac_printk("\n");
+	rsbac_printk(KERN_INFO "Sum of %lu Remote NETOBJ items\n",
+		     rnetobj_sum);
+	total_sum += rnetobj_sum;
+#endif				/* NET_OBJ */
+
+	rsbac_printk(KERN_INFO "Total of %lu registered rsbac-items\n", total_sum);
+
+	rsbac_printk(KERN_INFO "adf_request calls: file: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu, unixsock: %lu\n",
+		     rsbac_adf_request_count[T_FILE],
+		     rsbac_adf_request_count[T_DIR],
+		     rsbac_adf_request_count[T_FIFO],
+		     rsbac_adf_request_count[T_SYMLINK],
+		     rsbac_adf_request_count[T_DEV],
+		     rsbac_adf_request_count[T_IPC],
+		     rsbac_adf_request_count[T_SCD],
+		     rsbac_adf_request_count[T_USER],
+		     rsbac_adf_request_count[T_PROCESS],
+		     rsbac_adf_request_count[T_NETDEV],
+		     rsbac_adf_request_count[T_NETTEMP],
+		     rsbac_adf_request_count[T_NETOBJ],
+		     rsbac_adf_request_count[T_UNIXSOCK]);
+	rsbac_printk(KERN_INFO "adf_set_attr calls: file: %lu, dir: %lu, fifo: %lu, symlink: %lu, dev: %lu, ipc: %lu, scd: %lu, user: %lu, process: %lu, netdev: %lu, nettemp: %lu, netobj: %lu, unixsock: %lu\n",
+		     rsbac_adf_set_attr_count[T_FILE],
+		     rsbac_adf_set_attr_count[T_DIR],
+		     rsbac_adf_set_attr_count[T_FIFO],
+		     rsbac_adf_set_attr_count[T_SYMLINK],
+		     rsbac_adf_set_attr_count[T_DEV],
+		     rsbac_adf_set_attr_count[T_IPC],
+		     rsbac_adf_set_attr_count[T_SCD],
+		     rsbac_adf_set_attr_count[T_USER],
+		     rsbac_adf_set_attr_count[T_PROCESS],
+		     rsbac_adf_set_attr_count[T_NETDEV],
+		     rsbac_adf_set_attr_count[T_NETTEMP],
+		     rsbac_adf_set_attr_count[T_NETOBJ],
+		     rsbac_adf_set_attr_count[T_UNIXSOCK]);
+
+#if defined(CONFIG_RSBAC_RC)
+	rsbac_stats_rc();
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	rsbac_stats_auth();
+#endif
+#if defined(CONFIG_RSBAC_ACL)
+	rsbac_stats_acl();
+#endif
+	return 0;
+}
+
+/***************************************************/
+/* rsbac_write() to write all dirty lists to disk  */
+/*               returns no. of lists written      */
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+int rsbac_write()
+{
+	int err = 0;
+	u_int count = 0;
+	int subcount;
+
+	if (!rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_write(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (rsbac_debug_no_write)
+		return 0;
+
+	subcount = rsbac_write_lists();
+	if (subcount > 0) {
+		count += subcount;
+	} else if (subcount < 0) {
+		err = subcount;
+		if (err != -RSBAC_ENOTWRITABLE) {
+			rsbac_printk(KERN_WARNING "rsbac_write(): rsbac_write_lists() returned error %i\n",
+				     err);
+		}
+	}
+
+#if defined(CONFIG_RSBAC_REG)
+	subcount = rsbac_write_reg();
+	if (subcount > 0) {
+		count += subcount;
+	} else if (subcount < 0) {
+		err = subcount;
+		if (err != -RSBAC_ENOTWRITABLE) {
+			rsbac_printk(KERN_WARNING "rsbac_write(): rsbac_write_reg() returned error %i\n",
+				     err);
+		}
+	}
+#endif
+
+	if (count > 0)
+		rsbac_pr_debug(write, "total of %u lists written\n", count);
+	return count;
+}
+#endif
+
+/************************************************* */
+/*               Attribute functions               */
+/************************************************* */
+
+/* A rsbac_set_attr() call for a non-existing object, user                  */
+/* or process entry will first add the target and then set the attribute.   */
+/* Invalid combinations and trying to set security_level to or from         */
+/* SL_rsbac_internal return an error.                                       */
+/* A rsbac_get_attr() call for a non-existing target will return the        */
+/* default value stored in def_aci, which should be the first enum item.*/
+
+/* All these procedures handle the rw-spinlocks to protect the targets during */
+/* access.                                                                  */
+
+#if 0
+static int rsbac_get_parent_kdev(struct vfsmount * vfsmount_p, kdev_t * kdev_p)
+{
+	if (!kdev_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	if (   !vfsmount_p
+	    || !real_mount(vfsmount_p)->mnt_mountpoint
+	    || !real_mount(vfsmount_p)->mnt_mountpoint->d_parent
+	    || (real_mount(vfsmount_p)->mnt_mountpoint->d_parent == real_mount(vfsmount_p)->mnt_mountpoint)
+	    || !real_mount(vfsmount_p)->mnt_mountpoint->d_sb
+	    || !real_mount(vfsmount_p)->mnt_mountpoint->d_sb->s_dev
+	   ) {
+		*kdev_p = RSBAC_ZERO_DEV;
+		return -RSBAC_ENOTFOUND;
+	}
+
+	*kdev_p = real_mount(vfsmount_p)->mnt_mountpoint->d_sb->s_dev;
+	return 0;
+}
+#endif
+
+/* get the parent of a target
+ * returns -RSBAC_EINVALIDTARGET for non-fs targets
+ * and -RSBAC_ENOTFOUND, if no parent available
+ * In kernels >= 2.4.0, device_p->d_covers is used and the device_p item is
+ * properly locked for reading, so never call with a write lock held on
+ * device_p!
+ */
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_get_parent);
+#endif
+int rsbac_get_parent(enum rsbac_target_t target,
+		     union rsbac_target_id_t tid,
+		     enum rsbac_target_t *parent_target_p,
+		     union rsbac_target_id_t *parent_tid_p)
+{
+	int srcu_idx;
+
+	if (!parent_target_p || !parent_tid_p)
+		return -RSBAC_EINVALIDPOINTER;
+/*
+	rsbac_pr_debug(ds, "Getting file/dir/fifo/symlink "
+		       "parent for device %02u:%02u, inode %lu, dentry_p %p\n",
+		       RSBAC_MAJOR(tid.file.device),
+		       RSBAC_MINOR(tid.file.device),
+		       (u_long)tid.file.inode, tid.file.dentry_p);
+*/
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		break;
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+
+	if (!tid.file.dentry_p)
+		return -RSBAC_ENOTFOUND;
+
+#ifdef CONFIG_RSBAC_XSTATS
+	get_parent_count++;
+#endif
+	*parent_target_p = T_DIR;
+	/* Is this dentry root of a mounted device? */
+	if (tid.file.dentry_p->d_sb
+	    && (tid.file.dentry_p->d_sb->s_root == tid.file.dentry_p)
+	    ) {
+		struct rsbac_device_list_item_t *device_p;
+		u_int hash;
+
+		if (tid.file.device == rsbac_root_dev)
+			return -RSBAC_ENOTFOUND;
+		hash = device_hash(tid.file.device);
+		srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+		device_p = lookup_device(tid.file.device, hash);
+		if (!device_p
+		    || !device_p->vfsmount_p
+		    || !real_mount(device_p->vfsmount_p)->mnt_mountpoint
+		    || !real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent
+		    || (real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent == real_mount(device_p->vfsmount_p)->mnt_mountpoint)
+		    || !real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent->d_inode
+		    || !real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent->d_inode->i_ino
+		    || !real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb
+		    || !real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb->s_dev
+		    || (real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_sb->s_dev == tid.file.device)) {
+			/* free access to device_list_head */
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			return -RSBAC_ENOTFOUND;
+		}
+		parent_tid_p->dir.device =
+		    real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent->d_sb->s_dev;
+		parent_tid_p->dir.inode =
+		    real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent->d_inode->i_ino;
+		parent_tid_p->dir.dentry_p = real_mount(device_p->vfsmount_p)->mnt_mountpoint->d_parent;
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	} else {		/* no root of filesystem -> use d_parent, dev keeps unchanged */
+		if (!tid.file.dentry_p->d_parent) {
+			rsbac_printk(KERN_DEBUG "rsbac_get_parent(): oops - d_parent is NULL!\n");
+			return -RSBAC_ENOTFOUND;
+		}
+		if (tid.file.dentry_p == tid.file.dentry_p->d_parent) {
+			// rsbac_printk(KERN_DEBUG "rsbac_get_parent(): oops - d_parent == dentry_p!\n");
+			return -RSBAC_ENOTFOUND;
+		}
+		if (!tid.file.dentry_p->d_parent->d_inode) {
+			rsbac_printk(KERN_DEBUG "rsbac_get_parent(): oops - d_parent has no d_inode!\n");
+			return -RSBAC_ENOTFOUND;
+		}
+		if (!tid.file.dentry_p->d_parent->d_inode->i_ino)
+		{
+			rsbac_printk(KERN_DEBUG "rsbac_get_parent(): oops - d_parent d_inode->i_ino is 0!\n");
+			return -RSBAC_ENOTFOUND;
+		}
+		parent_tid_p->dir.device = tid.file.device;
+		parent_tid_p->dir.inode =
+		    tid.file.dentry_p->d_parent->d_inode->i_ino;
+		parent_tid_p->dir.dentry_p = tid.file.dentry_p->d_parent;
+	}
+	return 0;
+}
+
+static int get_attr_fd(rsbac_list_ta_number_t ta_number,
+			enum rsbac_switch_target_t module,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t *tid_p,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *value_p,
+			rsbac_boolean_t inherit)
+{
+	int err = 0;
+	struct rsbac_device_list_item_t *device_p;
+#ifdef CONFIG_RSBAC_FD_CACHE
+	kdev_t firstdev = RSBAC_ZERO_DEV;
+	rsbac_inode_nr_t firstinode = 0;
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	rsbac_ff_flags_t ff_flags = 0;
+	rsbac_ff_flags_t ff_tmp_flags;
+	rsbac_ff_flags_t ff_mask = -1;
+#endif
+	u_int hash;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	/* use loop for inheritance - used to be recursive calls */
+	for (;;) {
+/*		rsbac_pr_debug(ds, "Getting file/dir/fifo/"
+			       "symlink attribute %u for device %02u:%02u, "
+			       "inode %lu, dentry_p %p\n", attr,
+			       RSBAC_MAJOR(tid_p->file.device),
+			       RSBAC_MINOR(tid_p->file.device),
+			       tid_p->file.inode,
+			       tid_p->file.dentry_p); */
+		hash = device_hash(tid_p->file.device);
+		srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+		device_p = lookup_device(tid_p->file.device, hash);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_get_attr(): unknown device %02u:%02u\n",
+				     RSBAC_MAJOR(tid_p->file.device),
+				     RSBAC_MINOR(tid_p->file.device));
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+		if (inherit && !ta_number && device_p->fd_cache_handle[module]) {
+			rsbac_enum_t cache_attr = attr;
+
+			if (!rsbac_list_lol_get_subdata(device_p->fd_cache_handle[module],
+						&tid_p->file.inode, &cache_attr,
+						value_p)) {
+#ifdef CONFIG_RSBAC_DEBUG
+				char * attr_name = NULL;
+				char * attr_val_name = NULL;
+
+				if (rsbac_debug_fdcache) {
+				        attr_name = rsbac_kmalloc(32);
+				        attr_val_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+				}
+				if (rsbac_debug_fdcache > 1)
+					rsbac_pr_debug(fdcache, "Found fd cache item device %02u:%02u inode %lu module %u attr %s value %s\n",
+						RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+						tid_p->file.inode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p));
+#endif
+#if defined(CONFIG_RSBAC_FF)
+				/* FF ff_flags is special, result needs some cleaning, if inherited */
+				if (attr == A_ff_flags)
+					value_p->ff_flags = (value_p->ff_flags & ff_mask ) | ff_flags;
+#endif
+				if (!RSBAC_IS_ZERO_DEV(firstdev) && firstinode) {
+					if (firstdev != tid_p->file.device) {
+						srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+						hash = device_hash(firstdev);
+						srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+						device_p = lookup_device(firstdev, hash);
+					}
+					if (device_p && device_p->fd_cache_handle[module]) {
+#ifdef CONFIG_RSBAC_DEBUG
+						if (rsbac_debug_fdcache) {
+							union rsbac_attribute_value_t tmp_value;
+
+							if (!rsbac_list_lol_get_subdata(device_p->fd_cache_handle[module],
+										&firstinode, &cache_attr,
+										&tmp_value)) {
+								rsbac_pr_debug(fdcache, "fd cache item already in cache: device %02u:%02u inode %lu module %u attr %s value %s (parent device %02u:%02u inode %lu was in cache)\n",
+									RSBAC_MAJOR(firstdev), RSBAC_MINOR(firstdev),
+									firstinode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, &tmp_value),
+									RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+									tid_p->file.inode);
+							}
+						}
+#endif
+						rsbac_pr_debug(fdcache, "Adding fd cache item device %02u:%02u inode %lu module %u attr %s value %s (parent device %02u:%02u inode %lu was in cache)\n",
+							RSBAC_MAJOR(firstdev), RSBAC_MINOR(firstdev),
+							firstinode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p),
+							RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+							tid_p->file.inode);
+						err = rsbac_list_lol_subadd_ttl(device_p->fd_cache_handle[module],
+								rsbac_fd_cache_ttl,
+								&firstinode, &cache_attr,
+								value_p);
+#ifdef CONFIG_RSBAC_DEBUG
+						if (err && rsbac_debug_fdcache) {
+							rsbac_pr_debug(fdcache, "Adding fd cache item device %02u:%02u inode %lu module %u attr %s value %s (parent device %02u:%02u inode %lu was in cache) failed with error %i\n",
+								RSBAC_MAJOR(firstdev), RSBAC_MINOR(firstdev),
+								firstinode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p),
+								RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+								tid_p->file.inode,
+								err);
+						}
+#endif
+#ifdef CONFIG_RSBAC_XSTATS
+						device_p->fd_cache_misses[module]++;
+#endif
+					}
+#ifdef CONFIG_RSBAC_DEBUG
+					else {
+						if (rsbac_debug_fdcache > 1)
+							rsbac_pr_debug(fdcache, "Not adding fd cache item device %02u:%02u inode %lu module %u attr %s value %s (parent device %02u:%02u inode %lu was in cache)\n",
+								RSBAC_MAJOR(firstdev), RSBAC_MINOR(firstdev),
+								firstinode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p),
+								RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+								tid_p->file.inode);
+					}
+#endif
+#ifdef CONFIG_RSBAC_XSTATS
+				} else {
+					device_p->fd_cache_hits[module]++;
+#endif
+				}
+#ifdef CONFIG_RSBAC_DEBUG
+				if (attr_name)
+					rsbac_kfree(attr_name);
+				if (attr_val_name)
+					rsbac_kfree(attr_val_name);
+#endif
+				srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+				return 0;
+			}
+		}
+#endif
+
+		inode_nr = tid_p->file.inode;
+
+		switch (module) {
+		case SW_GEN:
+			{
+				struct rsbac_gen_fd_aci_t aci =
+				    DEFAULT_GEN_FD_ACI;
+
+				if (attr == A_internal) {
+					if (!device_p->rsbac_dir_inode
+					    || !tid_p->file.inode)
+						value_p->internal = FALSE;
+					else if (device_p->
+						 rsbac_dir_inode ==
+						 tid_p->file.inode)
+						value_p->internal = TRUE;
+					else if (inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent(target, *tid_p, &parent_target, &parent_tid)) {	/* yes: inherit this single level */
+							if (device_p->
+							    rsbac_dir_inode
+							    ==
+							    parent_tid.
+							    file.inode)
+								value_p->
+								    internal
+								    = TRUE;
+							else
+								value_p->
+								    internal
+								    =
+								    FALSE;
+						} else {
+							value_p->internal =
+							    FALSE;
+						}
+					} else {
+						value_p->internal = FALSE;
+					}
+
+					/* free access to device_list_head */
+					srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+					return 0;
+				}
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.gen,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_log_array_low:
+					value_p->log_array_low =
+					    aci.log_array_low;
+					break;
+				case A_log_array_high:
+					value_p->log_array_high =
+					    aci.log_array_high;
+					break;
+				case A_log_program_based:
+					value_p->log_program_based =
+					    aci.log_program_based;
+					break;
+				case A_symlink_add_remote_ip:
+					value_p->symlink_add_remote_ip =
+					    aci.symlink_add_remote_ip;
+					break;
+				case A_symlink_add_uid:
+					value_p->symlink_add_uid =
+					    aci.symlink_add_uid;
+					break;
+				case A_symlink_add_mac_level:
+					value_p->symlink_add_mac_level =
+					    aci.symlink_add_mac_level;
+					break;
+				case A_symlink_add_rc_role:
+					value_p->symlink_add_rc_role =
+					    aci.symlink_add_rc_role;
+					break;
+				case A_linux_dac_disable:
+					value_p->linux_dac_disable =
+					    aci.linux_dac_disable;
+					if ((value_p->linux_dac_disable ==
+					     LDD_inherit) && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->linux_dac_disable =
+							    def_gen_root_dir_aci.linux_dac_disable;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				case A_fake_root_uid:
+					value_p->fake_root_uid =
+					    aci.fake_root_uid;
+					break;
+				case A_auid_exempt:
+					value_p->auid_exempt =
+					    aci.auid_exempt;
+					break;
+				case A_vset:
+					value_p->vset = aci.vset;
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+
+#if defined(CONFIG_RSBAC_MAC)
+		case SW_MAC:
+			{
+				struct rsbac_mac_fd_aci_t aci =
+				    DEFAULT_MAC_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.mac,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_security_level:
+					value_p->security_level =
+					    aci.sec_level;
+					if ((value_p->security_level ==
+					     SL_inherit) && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->
+							    security_level
+							    =
+							    def_mac_root_dir_aci.
+							    sec_level;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				case A_mac_categories:
+					value_p->mac_categories =
+					    aci.mac_categories;
+					if ((value_p->mac_categories ==
+					     RSBAC_MAC_INHERIT_CAT_VECTOR)
+					    && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p-> mac_categories = def_mac_root_dir_aci.mac_categories;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				case A_mac_auto:
+					value_p->mac_auto = aci.mac_auto;
+					if ((value_p->mac_auto == MA_inherit)
+					    && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->mac_auto = def_mac_root_dir_aci.mac_auto;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				case A_mac_prop_trusted:
+					value_p->mac_prop_trusted =
+					    aci.mac_prop_trusted;
+					break;
+				case A_mac_file_flags:
+					value_p->mac_file_flags =
+					    aci.mac_file_flags;
+					break;
+
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_DAZ)
+		case SW_DAZ:
+			{
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+				if (attr == A_daz_scanned) {
+					err = rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     device_p->handles.dazs,
+					     NULL,
+#ifdef CONFIG_RSBAC_DAZ_PERSIST
+					     device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+#else
+					     &tid_p->file.inode,
+#endif
+					     &value_p->daz_scanned);
+				} else
+#endif
+				{
+					struct rsbac_daz_fd_aci_t aci =
+					    DEFAULT_DAZ_FD_ACI;
+
+					rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     device_p->handles.daz,
+					     NULL, device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+					     &aci);
+					switch (attr) {
+					case A_daz_scanner:
+						value_p->daz_scanner =
+						    aci.daz_scanner;
+						break;
+					case A_daz_do_scan:
+						value_p->daz_do_scan = aci.daz_do_scan;
+						if(   (value_p->daz_do_scan == DAZ_inherit)
+							&& inherit) {
+							enum rsbac_target_t       parent_target;
+							union rsbac_target_id_t   parent_tid;
+
+							if(!rsbac_get_parent(target, *tid_p, &parent_target, &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+								if (RSBAC_IS_ZERO_DEV(firstdev)) {
+									firstdev = device_p->id;
+									firstinode = tid_p->file.inode;
+								}
+#endif
+								srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+								target = parent_target;
+								*tid_p = parent_tid;
+								continue;
+							} else {
+								value_p->daz_do_scan = def_daz_root_dir_aci.daz_do_scan;
+								err = 0;
+								break;
+							}
+						}
+						break;
+					default:
+						err = -RSBAC_EINVALIDATTR;
+					}
+				}
+			}
+			break;
+#endif				/* DAZ */
+
+#if defined(CONFIG_RSBAC_FF)
+		case SW_FF:
+			{
+				switch (attr) {
+				case A_ff_flags:
+					ff_tmp_flags = RSBAC_FF_DEF;
+					rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     device_p->handles.ff,
+					     NULL,
+					     device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+					     &ff_tmp_flags);
+					ff_flags |= ff_tmp_flags & ff_mask;
+					value_p->ff_flags = ff_flags;
+					if (   (ff_tmp_flags & FF_add_inherited)
+					    && inherit) {
+						enum rsbac_target_t parent_target;
+						union rsbac_target_id_t parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							ff_mask &= ~ (FF_no_delete_or_rename | FF_add_inherited);
+							ff_flags &= ~(FF_add_inherited);
+							continue;
+						} else
+							value_p->ff_flags &= ~(FF_add_inherited);
+					}
+					break;
+
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* FF */
+
+#if defined(CONFIG_RSBAC_RC)
+		case SW_RC:
+			{
+				struct rsbac_rc_fd_aci_t aci =
+				    DEFAULT_RC_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.rc,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_rc_type_fd:
+					value_p->rc_type_fd = aci.rc_type_fd;
+					if (value_p->rc_type_fd ==
+					    RC_type_inherit_parent
+					    && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->rc_type_fd = def_rc_root_dir_aci.rc_type_fd;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				case A_rc_force_role:
+					value_p->rc_force_role =
+					    aci.rc_force_role;
+					if (value_p->rc_force_role ==
+					    RC_role_inherit_parent
+					    && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->rc_force_role = def_rc_root_dir_aci.rc_force_role;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				case A_rc_initial_role:
+					value_p->rc_initial_role =
+					    aci.rc_initial_role;
+					if (value_p->rc_initial_role ==
+					    RC_role_inherit_parent
+					    && inherit) {
+						enum rsbac_target_t
+						    parent_target;
+						union rsbac_target_id_t
+						    parent_tid;
+
+						/* inheritance possible? */
+						if (!rsbac_get_parent
+						    (target, *tid_p,
+						     &parent_target,
+						     &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							/* free access to device_list_head - see above */
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->rc_initial_role = def_rc_root_dir_aci.rc_initial_role;
+							err = 0;
+							break;
+						}
+					}
+					break;
+
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* RC */
+
+#if defined(CONFIG_RSBAC_AUTH)
+		case SW_AUTH:
+			{
+				struct rsbac_auth_fd_aci_t aci =
+				    DEFAULT_AUTH_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.auth,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_auth_may_setuid:
+					value_p->auth_may_setuid =
+					    aci.auth_may_setuid;
+					break;
+				case A_auth_may_set_cap:
+					value_p->auth_may_set_cap =
+					    aci.auth_may_set_cap;
+					break;
+				case A_auth_learn:
+					value_p->auth_learn = aci.auth_learn;
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* AUTH */
+
+#if defined(CONFIG_RSBAC_CAP)
+		case SW_CAP:
+			{
+				struct rsbac_cap_fd_aci_t aci =
+				    DEFAULT_CAP_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.cap,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_min_caps:
+					value_p->min_caps.cap[0] = aci.min_caps.cap[0];
+                                        value_p->min_caps.cap[1] = aci.min_caps.cap[1];
+					break;
+				case A_max_caps:
+					value_p->max_caps.cap[0] = aci.max_caps.cap[0];
+					value_p->max_caps.cap[1] = aci.max_caps.cap[1];
+					break;
+				case A_cap_ld_env:
+					value_p->cap_ld_env = aci.cap_ld_env;
+					if ((value_p->cap_ld_env == LD_inherit) && inherit) {
+						enum rsbac_target_t parent_target;
+						union rsbac_target_id_t parent_tid;
+						if (!rsbac_get_parent(target,
+									*tid_p,
+									&parent_target,
+									&parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+							if (RSBAC_IS_ZERO_DEV(firstdev)) {
+								firstdev = device_p->id;
+								firstinode = tid_p->file.inode;
+							}
+#endif
+							srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+							target = parent_target;
+							*tid_p = parent_tid;
+							continue;
+						} else {
+							value_p->cap_ld_env = LD_deny;
+							err = 0;
+							break;
+						}
+					}
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* CAP */
+
+#if defined(CONFIG_RSBAC_RES)
+		case SW_RES:
+			{
+				struct rsbac_res_fd_aci_t aci =
+				    DEFAULT_RES_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.res,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_res_min:
+					memcpy(&value_p->res_array,
+					       &aci.res_min,
+					       sizeof(aci.res_min));
+					break;
+				case A_res_max:
+					memcpy(&value_p->res_array,
+					       &aci.res_max,
+					       sizeof(aci.res_max));
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* RES */
+
+#if defined(CONFIG_RSBAC_PAX)
+		case SW_PAX:
+			{
+				switch (attr) {
+				case A_pax_flags:
+					value_p->pax_flags =
+					    RSBAC_PAX_DEF_FLAGS;
+					rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     device_p->handles.pax,
+					     NULL, device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+					     &value_p->pax_flags);
+					break;
+
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+			break;
+#endif				/* PAX */
+
+#if defined(CONFIG_RSBAC_UDF)
+		case SW_UDF:
+			{
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+				if (attr == A_udf_checked) {
+					err = rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     device_p->handles.udfc,
+					     NULL,
+#ifdef CONFIG_RSBAC_UDF_PERSIST
+					     device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+#else
+					     &tid_p->file.inode,
+#endif
+					     &value_p->udf_checked);
+				} else
+#endif
+				{
+					struct rsbac_udf_fd_aci_t aci =
+					    DEFAULT_UDF_FD_ACI;
+
+					rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     device_p->handles.udf,
+					     NULL, device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+					     &aci);
+					switch (attr) {
+					case A_udf_checker:
+						value_p->udf_checker =
+						    aci.udf_checker;
+						break;
+					case A_udf_do_check:
+						value_p->udf_do_check = aci.udf_do_check;
+						if(   (value_p->udf_do_check == UDF_inherit)
+							&& inherit) {
+							enum rsbac_target_t       parent_target;
+							union rsbac_target_id_t   parent_tid;
+
+							if(!rsbac_get_parent(target, *tid_p, &parent_target, &parent_tid)) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+								if (RSBAC_IS_ZERO_DEV(firstdev)) {
+									firstdev = device_p->id;
+									firstinode = tid_p->file.inode;
+								}
+#endif
+								srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+								target = parent_target;
+								*tid_p = parent_tid;
+								continue;
+							} else {
+								value_p->udf_do_check
+									= def_udf_root_dir_aci.udf_do_check;
+								err = 0;
+								break;
+							}
+						}
+						break;
+					default:
+						err = -RSBAC_EINVALIDATTR;
+					}
+				}
+			}
+			break;
+#endif				/* UDF */
+
+		default:
+			err = -RSBAC_EINVALIDMODULE;
+		}
+#ifdef CONFIG_RSBAC_FD_CACHE
+		if (!err && inherit && !ta_number) {
+			rsbac_enum_t cache_attr = attr;
+#ifdef CONFIG_RSBAC_DEBUG
+			char * attr_name = NULL;
+			char * attr_val_name = NULL;
+			if (rsbac_debug_fdcache) {
+			        attr_name = rsbac_kmalloc(32);
+			        attr_val_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+			}
+#endif
+			if (!RSBAC_IS_ZERO_DEV(firstdev)) {
+				if (firstdev != tid_p->file.device) {
+					srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+					hash = device_hash(firstdev);
+					srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+					device_p = lookup_device(firstdev, hash);
+					tid_p->file.device = firstdev;
+				}
+			}
+			if (device_p && device_p->fd_cache_handle[module]) {
+				if (firstinode)
+					tid_p->file.inode = firstinode;
+				rsbac_pr_debug(fdcache, "Adding fd cache item device %02u:%02u inode %lu module %u attr %s value %s (no parent was in cache)\n",
+					RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+					tid_p->file.inode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p));
+				err = rsbac_list_lol_subadd_ttl(device_p->fd_cache_handle[module],
+						rsbac_fd_cache_ttl,
+						&tid_p->file.inode, &cache_attr,
+						value_p);
+				if (err) {
+#ifdef CONFIG_RSBAC_DEBUG
+					if (rsbac_debug_fdcache) {
+						rsbac_pr_debug(fdcache, "Adding fd cache item device %02u:%02u inode %lu module %u attr %s value %s (parent device %02u:%02u inode %lu was in cache) failed with error %i\n",
+								RSBAC_MAJOR(firstdev), RSBAC_MINOR(firstdev),
+								firstinode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p),
+								RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+								tid_p->file.inode,
+								err);
+					}
+#endif
+					err = 0;
+				}
+#ifdef CONFIG_RSBAC_XSTATS
+				device_p->fd_cache_misses[module]++;
+#endif
+			}
+#ifdef CONFIG_RSBAC_DEBUG
+			else {
+				if (rsbac_debug_fdcache > 1)
+					rsbac_pr_debug(fdcache, "Not adding fd cache item device %02u:%02u inode %lu module %u attr %s value %s (no parent was in cache)\n",
+						RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+						tid_p->file.inode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p));
+			}
+			if (attr_name)
+				rsbac_kfree(attr_name);
+			if (attr_val_name)
+				rsbac_kfree(attr_val_name);
+#endif
+		}
+#endif /* CONFIG_RSBAC_FD_CACHE */
+
+		/* free access to device_list_head */
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		/* and return */
+		return err;
+	}			/* end of for(;;) loop for inheritance */
+}
+
+static int get_attr_dev(rsbac_list_ta_number_t ta_number,
+			enum rsbac_switch_target_t module,
+			enum rsbac_target_t target,
+			struct rsbac_dev_desc_t dev,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *value,
+			rsbac_boolean_t inherit)
+{
+	int err = 0;
+/*	rsbac_pr_debug(ds, "Getting dev attribute\n"); */
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_dev_aci_t aci =
+			    DEFAULT_GEN_DEV_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   dev_handles.gen,
+						   NULL, &dev, &aci);
+			switch (attr) {
+			case A_log_array_low:
+				value->log_array_low = aci.log_array_low;
+				break;
+			case A_log_array_high:
+				value->log_array_high = aci.log_array_high;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_dev_aci_t aci =
+			    DEFAULT_MAC_DEV_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   dev_handles.mac,
+						   NULL, &dev, &aci);
+			switch (attr) {
+			case A_security_level:
+				value->security_level = aci.sec_level;
+				break;
+			case A_mac_categories:
+				value->mac_categories = aci.mac_categories;
+				break;
+			case A_mac_check:
+				value->mac_check = aci.mac_check;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;
+
+			switch (dev.type) {
+			case D_char:
+			case D_block:
+				if (rsbac_ta_list_get_data_ttl(ta_number,
+							       dev_handles.
+							       rc, NULL,
+							       &dev, &type)
+				    || ((type == RC_type_inherit_parent)
+					&& inherit)
+				    ) {
+				    	dev.minor = 0;
+					rsbac_ta_list_get_data_ttl
+					    (ta_number,
+					     dev_major_handles.rc, NULL,
+					     &dev, &type);
+				}
+				break;
+			case D_char_major:
+			case D_block_major:
+				dev.type -= (D_block_major - D_block);
+			    	dev.minor = 0;
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   dev_major_handles.
+							   rc, NULL, &dev,
+							   &type);
+				break;
+			default:
+				return -RSBAC_EINVALIDTARGET;
+			}
+			switch (attr) {
+			case A_rc_type:
+				value->rc_type = type;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	/* and return */
+	return err;
+}
+
+static int get_attr_ipc(rsbac_list_ta_number_t ta_number,
+			enum rsbac_switch_target_t module,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t *tid_p,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *value,
+			rsbac_boolean_t inherit)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Getting ipc attribute\n"); */
+	/* lookup only, if not sock or (sock-id != NULL), OK with NULL fifo */
+	switch (module) {
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_ipc_aci_t aci =
+			    DEFAULT_MAC_IPC_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   ipc_handles.mac,
+						   NULL,
+						   &tid_p->ipc, &aci);
+			switch (attr) {
+			case A_security_level:
+				value->security_level = aci.sec_level;
+				break;
+			case A_mac_categories:
+				value->mac_categories = aci.mac_categories;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   ipc_handles.rc,
+						   NULL,
+						   &tid_p->ipc, &type);
+			switch (attr) {
+			case A_rc_type:
+				value->rc_type = type;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+#if defined(CONFIG_RSBAC_JAIL)
+	case SW_JAIL:
+		{
+			rsbac_jail_id_t id = RSBAC_JAIL_DEF_ID;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   ipc_handles.jail,
+						   NULL, &tid_p->ipc, &id);
+			switch (attr) {
+			case A_jail_id:
+				value->jail_id = id;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* JAIL */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	/* and return */
+	return err;
+}
+
+static int get_attr_user(rsbac_list_ta_number_t ta_number,
+			enum rsbac_switch_target_t module,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t *tid_p,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *value,
+			rsbac_boolean_t inherit)
+{
+	int err = 0;
+#if defined(CONFIG_RSBAC_UM_VIRTUAL) || defined(CONFIG_RSBAC_RES)
+	rsbac_uid_t all_user;
+#endif
+
+	/* rsbac_pr_debug(ds, "Getting user attribute\n"); */
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_user_aci_t aci =
+			    DEFAULT_GEN_U_ACI;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.gen,
+						   NULL,
+						   &tid_p->user, &aci);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.gen,
+								NULL,
+								&all_user,
+								&aci);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.gen,
+						   NULL,
+						   &tid_p->user, &aci);
+#endif
+			switch (attr) {
+			case A_pseudo:
+				value->pseudo = aci.pseudo;
+				break;
+			case A_log_user_based:
+				value->log_user_based = aci.log_user_based;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_user_aci_t aci =
+			    DEFAULT_MAC_U_ACI;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.mac,
+						   NULL,
+						   &tid_p->user, &aci);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.mac,
+								NULL,
+								&all_user,
+								&aci);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.mac,
+						   NULL,
+						   &tid_p->user, &aci);
+#endif
+			switch (attr) {
+			case A_security_level:
+				value->security_level = aci.security_level;
+				break;
+			case A_initial_security_level:
+				value->security_level =
+				    aci.initial_security_level;
+				break;
+			case A_min_security_level:
+				value->security_level =
+				    aci.min_security_level;
+				break;
+			case A_mac_categories:
+				value->mac_categories = aci.mac_categories;
+				break;
+			case A_mac_initial_categories:
+				value->mac_categories =
+				    aci.mac_initial_categories;
+				break;
+			case A_mac_min_categories:
+				value->mac_categories =
+				    aci.mac_min_categories;
+				break;
+			case A_system_role:
+			case A_mac_role:
+				value->system_role = aci.system_role;
+				break;
+			case A_mac_user_flags:
+				value->mac_user_flags = aci.mac_user_flags;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_DAZ)
+	case SW_DAZ:
+		{
+			rsbac_system_role_int_t role = SR_user;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.daz,
+						   NULL,
+						   &tid_p->user, &role);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.daz,
+								NULL,
+								&all_user,
+								&role);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.daz,
+						   NULL,
+						   &tid_p->user, &role);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_daz_role:
+				value->system_role = role;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* DAZ */
+
+#if defined(CONFIG_RSBAC_FF)
+	case SW_FF:
+		{
+			rsbac_system_role_int_t role = SR_user;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.ff,
+						   NULL,
+						   &tid_p->user, &role);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.ff,
+								NULL,
+								&all_user,
+								&role);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.ff,
+						   NULL,
+						   &tid_p->user, &role);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_ff_role:
+				value->system_role = role;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* FF */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_user_aci_t aci = DEFAULT_RC_U_ACI;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.rc,
+						   NULL,
+						   &tid_p->user, &aci);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.rc,
+								NULL,
+								&all_user,
+								&aci);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.rc,
+						   NULL,
+						   &tid_p->user, &aci);
+#endif
+			switch (attr) {
+			case A_rc_def_role:
+				value->rc_def_role = aci.rc_role;
+				break;
+			case A_rc_type:
+				value->rc_type = aci.rc_type;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+#if defined(CONFIG_RSBAC_AUTH)
+	case SW_AUTH:
+		{
+			rsbac_system_role_int_t role = SR_user;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.auth,
+						   NULL,
+						   &tid_p->user, &role);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.auth,
+								NULL,
+								&all_user,
+								&role);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.auth,
+						   NULL,
+						   &tid_p->user, &role);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_auth_role:
+				value->system_role = role;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* AUTH */
+
+#if defined(CONFIG_RSBAC_CAP)
+	case SW_CAP:
+		{
+			struct rsbac_cap_user_aci_t aci =
+			    DEFAULT_CAP_U_ACI;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.cap,
+						   NULL,
+						   &tid_p->user, &aci);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.cap,
+								NULL,
+								&all_user,
+								&aci);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.cap,
+						   NULL,
+						   &tid_p->user, &aci);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_cap_role:
+				value->system_role = aci.cap_role;
+				break;
+			case A_min_caps:
+				value->min_caps.cap[0] = aci.min_caps.cap[0];
+				value->min_caps.cap[1] = aci.min_caps.cap[1];
+				break;
+			case A_max_caps:
+				value->max_caps.cap[0] = aci.max_caps.cap[0];
+				value->max_caps.cap[1] = aci.max_caps.cap[1];
+				break;
+			case A_cap_ld_env:
+				value->cap_ld_env = aci.cap_ld_env;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* CAP */
+
+#if defined(CONFIG_RSBAC_JAIL)
+	case SW_JAIL:
+		{
+			rsbac_system_role_int_t role = SR_user;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.jail,
+						   NULL,
+						   &tid_p->user, &role);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.jail,
+								NULL,
+								&all_user,
+								&role);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.jail,
+						   NULL,
+						   &tid_p->user, &role);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_jail_role:
+				value->system_role = role;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* JAIL */
+
+#if defined(CONFIG_RSBAC_RES)
+	case SW_RES:
+		{
+			struct rsbac_res_user_aci_t aci =
+			    DEFAULT_RES_U_ACI;
+
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.res,
+						   NULL,
+						   &tid_p->user, &aci);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					err = rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.res,
+								NULL,
+								&all_user,
+								&aci);
+					if (err == -RSBAC_ENOTFOUND) {
+						err = 0;
+						if (RSBAC_UID_SET(tid_p->user)) {
+							all_user = RSBAC_ALL_USERS;
+							rsbac_ta_list_get_data_ttl(ta_number,
+										user_handles.res,
+										NULL,
+										&all_user,
+										&aci);
+						}
+					}
+				}
+			}
+			switch (attr) {
+			case A_system_role:
+			case A_res_role:
+				value->system_role = aci.res_role;
+				break;
+			case A_res_min:
+				memcpy(&value->res_array, &aci.res_min,
+				       sizeof(aci.res_min));
+				break;
+			case A_res_max:
+				memcpy(&value->res_array, &aci.res_max,
+				       sizeof(aci.res_max));
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RES */
+
+#if defined(CONFIG_RSBAC_PAX)
+	case SW_PAX:
+		{
+			rsbac_system_role_int_t role = SR_user;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.pax,
+						   NULL,
+						   &tid_p->user, &role);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.pax,
+								NULL,
+								&all_user,
+								&role);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.pax,
+						   NULL,
+						   &tid_p->user, &role);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_pax_role:
+				value->system_role = role;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* PAX */
+
+#if defined(CONFIG_RSBAC_UDF)
+	case SW_UDF:
+		{
+			rsbac_system_role_int_t role = SR_user;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.udf,
+						   NULL,
+						   &tid_p->user, &role);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					all_user = RSBAC_GEN_UID(RSBAC_UID_SET(tid_p->user), RSBAC_ALL_USERS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								user_handles.udf,
+								NULL,
+								&all_user,
+								&role);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.udf,
+						   NULL,
+						   &tid_p->user, &role);
+#endif
+			switch (attr) {
+			case A_system_role:
+			case A_udf_role:
+				value->system_role = role;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* UDF */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	/* and return */
+	return err;
+}
+
+static int get_attr_process(rsbac_list_ta_number_t ta_number,
+			    enum rsbac_switch_target_t module,
+			    enum rsbac_target_t target,
+			    union rsbac_target_id_t *tid_p,
+			    enum rsbac_attribute_t attr,
+			    union rsbac_attribute_value_t *value,
+			    rsbac_boolean_t inherit)
+{
+	int err = 0;
+/*	rsbac_pr_debug(ds, "Getting process attribute"); */
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_process_aci_t aci =
+			    DEFAULT_GEN_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.gen,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_vset:
+				value->vset = aci.vset;
+				break;
+			case A_log_program_based:
+				value->log_program_based =
+				    aci.log_program_based;
+				break;
+			case A_fake_root_uid:
+				value->fake_root_uid = aci.fake_root_uid;
+				break;
+			case A_audit_uid:
+				value->audit_uid = aci.audit_uid;
+				break;
+			case A_auid_exempt:
+				value->auid_exempt = aci.auid_exempt;
+				break;
+			case A_remote_ip:
+				value->remote_ip = aci.remote_ip;
+				break;
+			case A_kernel_thread:
+				value->kernel_thread = aci.kernel_thread;
+				break;
+#if defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+			case A_program_file:
+				value->program_file = aci.program_file;
+				break;
+#endif
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_process_aci_t aci =
+			    DEFAULT_MAC_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.mac,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_security_level:
+				value->security_level =
+				    aci.owner_sec_level;
+				break;
+			case A_initial_security_level:
+				value->security_level =
+				    aci.owner_initial_sec_level;
+				break;
+			case A_min_security_level:
+				value->security_level =
+				    aci.owner_min_sec_level;
+				break;
+			case A_mac_categories:
+				value->mac_categories =
+				    aci.mac_owner_categories;
+				break;
+			case A_mac_initial_categories:
+				value->mac_categories =
+				    aci.mac_owner_initial_categories;
+				break;
+			case A_mac_min_categories:
+				value->mac_categories =
+				    aci.mac_owner_min_categories;
+				break;
+			case A_current_sec_level:
+				value->current_sec_level =
+				    aci.current_sec_level;
+				break;
+			case A_mac_curr_categories:
+				value->mac_categories =
+				    aci.mac_curr_categories;
+				break;
+			case A_min_write_open:
+				value->min_write_open = aci.min_write_open;
+				break;
+			case A_min_write_categories:
+				value->mac_categories =
+				    aci.min_write_categories;
+				break;
+			case A_max_read_open:
+				value->max_read_open = aci.max_read_open;
+				break;
+			case A_max_read_categories:
+				value->mac_categories =
+				    aci.max_read_categories;
+				break;
+			case A_mac_process_flags:
+				value->mac_process_flags =
+				    aci.mac_process_flags;
+				break;
+			case A_mac_auto:
+				if (aci.mac_process_flags & MAC_auto)
+					value->mac_auto = TRUE;
+				else
+					value->mac_auto = FALSE;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_DAZ)
+	case SW_DAZ:
+		{
+			struct rsbac_daz_process_aci_t aci =
+			    DEFAULT_DAZ_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.daz,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_daz_scanner:
+				value->daz_scanner = aci.daz_scanner;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* DAZ */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_process_aci_t aci =
+			    DEFAULT_RC_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.rc,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_rc_role:
+				value->rc_role = aci.rc_role;
+				break;
+			case A_rc_type:
+				value->rc_type = aci.rc_type;
+				break;
+			case A_rc_select_type:
+			        value->rc_select_type = aci.rc_select_type;
+			        break;
+			case A_rc_force_role:
+				value->rc_force_role = aci.rc_force_role;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+#if defined(CONFIG_RSBAC_AUTH)
+	case SW_AUTH:
+		{
+			struct rsbac_auth_process_aci_t aci =
+			    DEFAULT_AUTH_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.auth,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_auth_may_setuid:
+				value->auth_may_setuid =
+				    aci.auth_may_setuid;
+				break;
+			case A_auth_may_set_cap:
+				value->auth_may_set_cap =
+				    aci.auth_may_set_cap;
+				break;
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+			case A_auth_start_uid:
+				value->auth_start_uid = aci.auth_start_uid;
+				break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+			case A_auth_start_euid:
+				value->auth_start_euid =
+				    aci.auth_start_euid;
+				break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+			case A_auth_start_gid:
+				value->auth_start_gid = aci.auth_start_gid;
+				break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+			case A_auth_start_egid:
+				value->auth_start_egid =
+				    aci.auth_start_egid;
+				break;
+#endif
+#endif
+			case A_auth_learn:
+				value->auth_learn = aci.auth_learn;
+				break;
+#else
+			case A_auth_learn:
+				value->auth_learn = FALSE;
+				break;
+#endif
+			case A_auth_last_auth:
+				value->auth_last_auth = aci.auth_last_auth;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* AUTH */
+
+#if defined(CONFIG_RSBAC_CAP)
+	case SW_CAP:
+		{
+			struct rsbac_cap_process_aci_t aci =
+			    DEFAULT_CAP_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.cap,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_cap_process_hiding:
+				value->cap_process_hiding =
+				    aci.cap_process_hiding;
+				break;
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_CAP_LEARN)
+			case A_max_caps_user:
+				value->max_caps_user.cap[0] = aci.max_caps_user.cap[0];
+				value->max_caps_user.cap[1] = aci.max_caps_user.cap[1];
+				break;
+			case A_max_caps_program:
+				value->max_caps_program.cap[0] = aci.max_caps_program.cap[0];
+				value->max_caps_program.cap[1] = aci.max_caps_program.cap[1];
+				break;
+#endif
+			case A_cap_ld_env:
+				value->cap_ld_env = aci.cap_ld_env;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* CAP */
+
+#if defined(CONFIG_RSBAC_JAIL)
+	case SW_JAIL:
+		{
+			struct rsbac_jail_process_aci_t aci =
+			    DEFAULT_JAIL_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.jail,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_jail_id:
+				value->jail_id = aci.id;
+				break;
+			case A_jail_parent:
+				value->jail_parent = aci.parent;
+				break;
+			case A_jail_ip:
+				value->jail_ip = aci.ip;
+				break;
+			case A_jail_flags:
+				value->jail_flags = aci.flags;
+				break;
+			case A_jail_max_caps:
+				value->jail_max_caps.cap[0] = aci.max_caps.cap[0];
+				value->jail_max_caps.cap[1] = aci.max_caps.cap[1];
+				break;
+			case A_jail_scd_get:
+				value->jail_scd_get = aci.scd_get;
+				break;
+			case A_jail_scd_modify:
+				value->jail_scd_modify = aci.scd_modify;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* JAIL */
+
+#if defined(CONFIG_RSBAC_PAX)
+	case SW_PAX:
+		{
+			struct task_struct *task_p;
+
+			switch (attr) {
+			case A_pax_flags:
+				task_p = get_pid_task(tid_p->process, PIDTYPE_PID);
+				if (task_p) {
+					if (pid_alive(task_p)) {
+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
+						if (task_p->mm)
+							value->pax_flags =
+							    task_p->mm->
+							    pax_flags &
+							    RSBAC_PAX_ALL_FLAGS;
+						else
+#endif
+							value->pax_flags = 0;
+					} else {
+						value->pax_flags = 0;
+					}
+					put_task_struct(task_p);
+				} else
+					err = -RSBAC_EINVALIDTARGET;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* PAX */
+
+#if defined(CONFIG_RSBAC_UDF)
+	case SW_UDF:
+		{
+			struct rsbac_udf_process_aci_t aci =
+			    DEFAULT_UDF_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.udf,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_udf_checker:
+				value->udf_checker = aci.udf_checker;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* UDF */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_UM
+static int get_attr_group(rsbac_list_ta_number_t ta_number,
+			  enum rsbac_switch_target_t module,
+			  enum rsbac_target_t target,
+			  union rsbac_target_id_t *tid_p,
+			  enum rsbac_attribute_t attr,
+			  union rsbac_attribute_value_t *value,
+			  rsbac_boolean_t inherit)
+{
+	int err = 0;
+
+	/* rsbac_pr_debug(ds, "Getting group attribute\n"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;
+
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+			err = rsbac_ta_list_get_data_ttl(ta_number,
+						   group_handles.rc,
+						   NULL,
+						   &tid_p->group, &type);
+			if (err == -RSBAC_ENOTFOUND) {
+				err = 0;
+				if(inherit) {
+					rsbac_gid_t all_group;
+
+					all_group = RSBAC_GEN_GID(RSBAC_GID_SET(tid_p->group), RSBAC_ALL_GROUPS);
+					rsbac_ta_list_get_data_ttl(ta_number,
+								group_handles.rc,
+								NULL,
+								&all_group,
+								&type);
+				}
+			}
+#else
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   group_handles.rc,
+						   NULL,
+						   &tid_p->group, &type);
+#endif
+			switch (attr) {
+			case A_rc_type:
+				value->rc_type = type;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	/* and return */
+	return err;
+}
+#endif
+
+#ifdef CONFIG_RSBAC_NET_DEV
+static int get_attr_netdev(rsbac_list_ta_number_t ta_number,
+			   enum rsbac_switch_target_t module,
+			   enum rsbac_target_t target,
+			   union rsbac_target_id_t *tid_p,
+			   enum rsbac_attribute_t attr,
+			   union rsbac_attribute_value_t *value,
+			   rsbac_boolean_t inherit)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Getting netdev attribute\n"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	case SW_GEN:
+		{
+			struct rsbac_gen_netdev_aci_t aci =
+			    DEFAULT_GEN_NETDEV_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   netdev_handles.gen,
+						   NULL,
+						   &tid_p->netdev, &aci);
+			switch (attr) {
+			case A_log_array_low:
+				value->log_array_low = aci.log_array_low;
+				break;
+			case A_log_array_high:
+				value->log_array_high = aci.log_array_high;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   netdev_handles.rc,
+						   NULL,
+						   &tid_p->netdev, &type);
+			switch (attr) {
+			case A_rc_type:
+				value->rc_type = type;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	/* and return */
+	return err;
+}
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+static int get_attr_nettemp(rsbac_list_ta_number_t ta_number,
+			    enum rsbac_switch_target_t module,
+			    enum rsbac_target_t target,
+			    union rsbac_target_id_t *tid_p,
+			    enum rsbac_attribute_t attr,
+			    union rsbac_attribute_value_t *value,
+			    rsbac_boolean_t inherit)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Getting nettemp attribute"); */
+	if (tid_p->nettemp
+	    && !rsbac_ta_list_exist(ta_number, net_temp_handle, &tid_p->nettemp)
+	    )
+		return -RSBAC_EINVALIDTARGET;
+	switch (module) {
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+	case SW_GEN:
+		{
+			struct rsbac_gen_fd_aci_t aci =
+			    DEFAULT_GEN_NETOBJ_ACI;
+
+			if (tid_p->nettemp)
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   nettemp_handles.
+							   gen, NULL,
+							   &tid_p->nettemp,
+							   &aci);
+			switch (attr) {
+			case A_log_array_low:
+				value->log_array_low = aci.log_array_low;
+				break;
+			case A_log_array_high:
+				value->log_array_high = aci.log_array_high;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_netobj_aci_t aci =
+			    DEFAULT_MAC_NETOBJ_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   nettemp_handles.mac,
+						   NULL,
+						   &tid_p->nettemp, &aci);
+			switch (attr) {
+			case A_security_level:
+				value->security_level = aci.sec_level;
+				break;
+			case A_mac_categories:
+				value->mac_categories = aci.mac_categories;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_nettemp_aci_t aci =
+			    DEFAULT_RC_NETTEMP_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   nettemp_handles.rc,
+						   NULL,
+						   &tid_p->nettemp, &aci);
+			switch (attr) {
+			case A_rc_type:
+				value->rc_type = aci.netobj_type;
+				break;
+
+			case A_rc_type_nt:
+				value->rc_type = aci.nettemp_type;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	return err;
+}
+
+static int get_attr_netobj(rsbac_list_ta_number_t ta_number,
+			   enum rsbac_switch_target_t module,
+			   enum rsbac_target_t target,
+			   union rsbac_target_id_t *tid_p,
+			   enum rsbac_attribute_t attr,
+			   union rsbac_attribute_value_t *value,
+			   rsbac_boolean_t inherit)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Getting netobj attribute"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+	case SW_GEN:
+		{
+			struct rsbac_gen_netobj_aci_t aci =
+			    DEFAULT_GEN_NETOBJ_ACI;
+			rsbac_net_temp_id_t temp;
+
+			switch (attr) {
+			case A_local_log_array_low:
+			case A_local_log_array_high:
+				if(!ta_number && tid_p->netobj.local_temp)
+					temp = tid_p->netobj.local_temp;
+				else
+					rsbac_ta_net_lookup_templates(ta_number,
+								      &tid_p->
+								      netobj,
+								      &temp, NULL);
+				break;
+			case A_remote_log_array_low:
+			case A_remote_log_array_high:
+				if(!ta_number && tid_p->netobj.remote_temp)
+					temp = tid_p->netobj.remote_temp;
+				else
+					rsbac_ta_net_lookup_templates(ta_number,
+								      &tid_p->
+								      netobj, NULL,
+								      &temp);
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (temp)
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   nettemp_handles.
+							   gen, NULL,
+							   &temp, &aci);
+			switch (attr) {
+			case A_local_log_array_low:
+			case A_remote_log_array_low:
+				value->log_array_low = aci.log_array_low;
+				break;
+			case A_local_log_array_high:
+			case A_remote_log_array_high:
+				value->log_array_high = aci.log_array_high;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_netobj_aci_t aci =
+			    DEFAULT_MAC_NETOBJ_ACI;
+
+			switch (attr) {
+			case A_local_sec_level:
+			case A_local_mac_categories:
+				if (rsbac_ta_list_get_data_ttl(ta_number, lnetobj_handles.mac, NULL, &tid_p->netobj.sock_p, &aci)) {	/* not found -> fallback to template */
+					rsbac_net_temp_id_t temp = 0;
+
+					if(!ta_number && tid_p->netobj.local_temp)
+						temp = tid_p->netobj.local_temp;
+					else
+						rsbac_ta_net_lookup_templates
+						    (ta_number, &tid_p->netobj,
+						     &temp, NULL);
+					if (temp)
+						rsbac_ta_list_get_data_ttl
+						    (ta_number,
+						     nettemp_handles.mac,
+						     NULL, &temp, &aci);
+				}
+				break;
+
+			case A_remote_sec_level:
+			case A_remote_mac_categories:
+				if (rsbac_ta_list_get_data_ttl(ta_number, rnetobj_handles.mac, NULL, &tid_p->netobj.sock_p, &aci)) {	/* not found -> fallback to template */
+					rsbac_net_temp_id_t temp = 0;
+
+					if(!ta_number && tid_p->netobj.remote_temp)
+						temp = tid_p->netobj.remote_temp;
+					else
+						rsbac_ta_net_lookup_templates
+						    (ta_number, &tid_p->netobj,
+						     NULL, &temp);
+					if (temp)
+						rsbac_ta_list_get_data_ttl
+						    (ta_number,
+						     nettemp_handles.mac,
+						     NULL, &temp, &aci);
+				}
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (err)
+				break;
+			switch (attr) {
+			case A_local_sec_level:
+			case A_remote_sec_level:
+				value->security_level = aci.sec_level;
+				break;
+			case A_local_mac_categories:
+			case A_remote_mac_categories:
+				value->mac_categories = aci.mac_categories;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = RSBAC_RC_GENERAL_TYPE;
+
+			switch (attr) {
+			case A_local_rc_type:
+				if (rsbac_ta_list_get_data_ttl(ta_number, lnetobj_handles.rc, NULL, &tid_p->netobj.sock_p, &type)) {	/* not found -> fallback to template */
+					rsbac_net_temp_id_t temp = 0;
+					struct rsbac_rc_nettemp_aci_t aci;
+
+					if(!ta_number && tid_p->netobj.local_temp)
+						temp = tid_p->netobj.local_temp;
+					else
+						rsbac_ta_net_lookup_templates
+						    (ta_number, &tid_p->netobj,
+						     &temp, NULL);
+					if (temp) {
+						if (!rsbac_ta_list_get_data_ttl(ta_number, nettemp_handles.rc, NULL, &temp, &aci))
+							type = aci.netobj_type;
+					}
+				}
+				break;
+
+			case A_remote_rc_type:
+				if (rsbac_ta_list_get_data_ttl(ta_number, rnetobj_handles.rc, NULL, &tid_p->netobj.sock_p, &type)) {	/* not found -> fallback to template */
+					rsbac_net_temp_id_t temp = 0;
+					struct rsbac_rc_nettemp_aci_t aci;
+
+					if(!ta_number && tid_p->netobj.remote_temp)
+						temp = tid_p->netobj.remote_temp;
+					else
+						rsbac_ta_net_lookup_templates
+						    (ta_number, &tid_p->netobj,
+						     NULL, &temp);
+					if (temp) {
+						if (!rsbac_ta_list_get_data_ttl(ta_number, nettemp_handles.rc, NULL, &temp, &aci))
+							type =
+							    aci.
+							    netobj_type;
+					}
+				}
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err)
+				value->rc_type = type;
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+	return err;
+}
+#endif				/* NET_OBJ */
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+int rsbac_fd_cache_invalidate(struct rsbac_fs_file_t * file_p)
+{
+	int i;
+	struct rsbac_device_list_item_t *device_p;
+	u_int hash;
+	int srcu_idx;
+
+	if (!file_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (RSBAC_MAJOR(file_p->device) <= 1)
+		return 0;
+
+	rsbac_pr_debug(fdcache, "Invalidating fd cache item device %02u:%02u inode %lu\n",
+			RSBAC_MAJOR(file_p->device), RSBAC_MINOR(file_p->device),
+			file_p->inode);
+
+	hash = device_hash(file_p->device);
+
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(file_p->device, hash);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_fd_cache_invalidate(): No entry for device %02u:%02u\n",
+			     MAJOR(file_p->device), MINOR(file_p->device));
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+
+	for (i = 0; i < SW_NONE; i++) {
+		if (device_p->fd_cache_handle[i])
+			rsbac_list_lol_remove(device_p->fd_cache_handle[i], &file_p->inode);
+	}
+#ifdef CONFIG_RSBAC_XSTATS
+	device_p->fd_cache_invalidates++;
+#endif
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	return 0;
+}
+
+int rsbac_fd_cache_invalidate_device(kdev_t kdev)
+{
+	int i;
+	struct rsbac_device_list_item_t *device_p;
+	u_int hash;
+	int srcu_idx;
+
+	if (RSBAC_MAJOR(kdev) <= 1)
+		return 0;
+	rsbac_pr_debug(fdcache, "Invalidating fd cache for device %02u:%02u\n",
+			RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+
+	hash = device_hash(kdev);
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(kdev, hash);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_fd_cache_invalidate(): No entry for device %02u:%02u\n",
+			     MAJOR(kdev), MINOR(kdev));
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+
+	for (i = 0; i < SW_NONE; i++) {
+		if (device_p->fd_cache_handle[i])
+			rsbac_list_lol_remove_all(device_p->fd_cache_handle[i]);
+	}
+#ifdef CONFIG_RSBAC_XSTATS
+	device_p->fd_cache_invalidate_alls++;
+#endif
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+	return 0;
+}
+
+int rsbac_fd_cache_invalidate_all(void)
+{
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	u_int i, j;
+	int srcu_idx;
+
+	rsbac_pr_debug(fdcache, "Invalidating fd cache completely\n");
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+		while (device_p) {	/* for all sublists */
+			for (j = 0; j < SW_NONE; j++) {
+				if (device_p->fd_cache_handle[j])
+					rsbac_list_lol_remove_all(device_p->fd_cache_handle[j]);
+			}
+#ifdef CONFIG_RSBAC_XSTATS
+			device_p->fd_cache_invalidate_alls++;
+#endif
+			device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+		}
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+	return 0;
+}
+#endif
+
+/* The value parameter to rsbac_get_attr(s) and rsbac_set_attr() is a pointer */
+/* to the appropiate data structure holding the attribute value.            */
+
+int rsbac_ta_get_attr(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_switch_target_t module,
+		      enum rsbac_target_t target,
+		      union rsbac_target_id_t tid,
+		      enum rsbac_attribute_t attr,
+		      union rsbac_attribute_value_t *value_p,
+		      rsbac_boolean_t inherit)
+{
+	int err = 0;
+
+	if (!rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_get_attr(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (!value_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_get_attr(): called from interrupt, process %u(%s)!\n",
+				current->pid, current->comm);
+		return -RSBAC_EFROMINTERRUPT;
+	}
+#ifdef CONFIG_RSBAC_XSTATS
+	get_attr_count[target]++;
+#endif
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		return get_attr_fd(ta_number, module, target, &tid,
+				   attr, value_p, inherit);
+
+	case T_DEV:
+		return get_attr_dev(ta_number, module, target, tid.dev,
+				    attr, value_p, inherit);
+
+	case T_IPC:
+		return get_attr_ipc(ta_number, module, target, &tid,
+				    attr, value_p, inherit);
+
+	case T_USER:
+		return get_attr_user(ta_number, module, target, &tid,
+				     attr, value_p, inherit);
+
+	case T_PROCESS:
+		return get_attr_process(ta_number, module, target, &tid,
+					attr, value_p, inherit);
+
+#ifdef CONFIG_RSBAC_UM
+	case T_GROUP:
+		return get_attr_group(ta_number, module, target, &tid,
+				      attr, value_p, inherit);
+#endif				/* CONFIG_RSBAC_UM */
+
+#ifdef CONFIG_RSBAC_NET_DEV
+	case T_NETDEV:
+		return get_attr_netdev(ta_number, module, target, &tid,
+				       attr, value_p, inherit);
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+	case T_NETTEMP:
+		return get_attr_nettemp(ta_number, module, target, &tid,
+					attr, value_p, inherit);
+
+	case T_NETOBJ:
+		return get_attr_netobj(ta_number, module, target, &tid,
+				       attr, value_p, inherit);
+#endif
+
+		/* switch target: no valid target */
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+
+	return err;
+}
+
+/************************************************************************** */
+
+static int set_attr_fd(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_switch_target_t module,
+		       enum rsbac_target_t target,
+		       union rsbac_target_id_t *tid_p,
+		       enum rsbac_attribute_t attr,
+		       union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	struct rsbac_device_list_item_t *device_p;
+	u_int hash;
+	int srcu_idx;
+	int need_set = 0;
+	rsbac_old_inode_nr_t inode_nr = tid_p->file.inode;
+#ifdef CONFIG_RSBAC_FD_CACHE
+	int need_flush = 0;
+#endif
+
+	/* rsbac_pr_debug(ds, "Setting file/dir/fifo/symlink "
+		       "attribute %u for device %02u:%02u, inode %lu, "
+		       "dentry_p %p\n", attr,
+		       RSBAC_MAJOR(tid_p->file.device),
+		       RSBAC_MINOR(tid_p->file.device),
+		       (u_long)tid_p->file.inode, tid_p->file.dentry_p); */
+	hash = device_hash(tid_p->file.device);
+	srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+	device_p = lookup_device(tid_p->file.device, hash);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_set_attr(): unknown device %02u:%02u\n",
+			     RSBAC_MAJOR(tid_p->file.
+					 device),
+			     RSBAC_MINOR(tid_p->file.
+					 device));
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_fd_aci_t aci = DEFAULT_GEN_FD_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   device_p->handles.gen,
+						   NULL,
+						   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						   &aci);
+			switch (attr) {
+			case A_log_array_low:
+				aci.log_array_low = value_p->log_array_low;
+				break;
+			case A_log_array_high:
+				aci.log_array_high =
+				    value_p->log_array_high;
+				break;
+			case A_log_program_based:
+				aci.log_program_based =
+				    value_p->log_program_based;
+				break;
+			case A_symlink_add_remote_ip:
+				aci.symlink_add_remote_ip =
+				    value_p->symlink_add_remote_ip;
+				break;
+			case A_symlink_add_uid:
+				aci.symlink_add_uid =
+				    value_p->symlink_add_uid;
+				break;
+			case A_symlink_add_mac_level:
+				aci.symlink_add_mac_level =
+				    value_p->symlink_add_mac_level;
+				break;
+			case A_symlink_add_rc_role:
+				aci.symlink_add_rc_role =
+				    value_p->symlink_add_rc_role;
+				break;
+			case A_linux_dac_disable:
+				if (aci.linux_dac_disable != value_p->linux_dac_disable) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+					if (target == T_DIR)
+						need_flush = 1;
+#endif
+					aci.linux_dac_disable = value_p->linux_dac_disable;
+				}
+				break;
+			case A_fake_root_uid:
+				aci.fake_root_uid = value_p->fake_root_uid;
+				break;
+			case A_auid_exempt:
+				aci.auid_exempt = value_p->auid_exempt;
+				break;
+			case A_vset:
+				aci.vset = value_p->vset;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    device_p->handles.gen,
+							    0,
+							    device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							    &aci);
+#ifdef CONFIG_RSBAC_FD_CACHE
+				need_set = 1;
+#endif
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_fd_aci_t aci = DEFAULT_MAC_FD_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						device_p->handles.mac,
+						NULL,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						&aci);
+			switch (attr) {
+			case A_security_level:
+				aci.sec_level = value_p->security_level;
+#ifdef CONFIG_RSBAC_FD_CACHE
+				if (target == T_DIR)
+					need_flush = 1;
+#endif
+				break;
+			case A_mac_categories:
+				aci.mac_categories =
+				    value_p->mac_categories;
+#ifdef CONFIG_RSBAC_FD_CACHE
+				if (target == T_DIR)
+					need_flush = 1;
+#endif
+				break;
+			case A_mac_auto:
+				aci.mac_auto = value_p->mac_auto;
+#ifdef CONFIG_RSBAC_FD_CACHE
+				if (target == T_DIR)
+					need_flush = 1;
+#endif
+				break;
+			case A_mac_prop_trusted:
+				aci.mac_prop_trusted =
+				    value_p->mac_prop_trusted;
+				break;
+			case A_mac_file_flags:
+				aci.mac_file_flags =
+				    value_p->
+				    mac_file_flags & RSBAC_MAC_F_FLAGS;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							device_p->handles.mac,
+							0,
+							device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							&aci);
+#ifdef CONFIG_RSBAC_FD_CACHE
+				need_set = 1;
+#endif
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_DAZ)
+	case SW_DAZ:
+		{
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+			if (attr == A_daz_scanned) {
+				err = rsbac_list_add_ttl(device_p->handles.dazs,
+						       rsbac_daz_ttl,
+#ifdef CONFIG_RSBAC_DAZ_PERSIST
+						       device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+#else
+						       &tid_p->file.inode,
+#endif
+						       &value_p->daz_scanned);
+#ifdef CONFIG_RSBAC_FD_CACHE
+				need_set = 1;
+#endif
+			} else
+#endif
+			{
+				struct rsbac_daz_fd_aci_t aci =
+				    DEFAULT_DAZ_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->
+							   handles.daz,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_daz_scanner:
+					if (aci.daz_scanner != value_p->daz_scanner) {
+						aci.daz_scanner = value_p->daz_scanner;
+						need_set = 1;
+					}
+					break;
+				case A_daz_do_scan:
+					if (aci.daz_do_scan != value_p->daz_do_scan) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+						if (target == T_DIR)
+							need_flush = 1;
+#endif
+						aci.daz_do_scan = value_p->daz_do_scan;
+						need_set = 1;
+					}
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+				if (need_set) {
+					err = rsbac_ta_list_add_ttl
+						(ta_number,
+						device_p->handles.daz,
+						0,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						&aci);
+				}
+			}
+		}
+		break;
+#endif				/* DAZ */
+
+#if defined(CONFIG_RSBAC_FF)
+	case SW_FF:
+		{
+			switch (attr) {
+			case A_ff_flags:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							device_p->
+							handles.ff,
+							0,
+							device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							&value_p->ff_flags);
+#ifdef CONFIG_RSBAC_FD_CACHE
+				if (target == T_DIR)
+					need_flush = 1;
+				need_set = 1;
+#endif
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* FF */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_fd_aci_t aci = DEFAULT_RC_FD_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   device_p->handles.rc,
+						   NULL,
+						   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						   &aci);
+			switch (attr) {
+			case A_rc_type_fd:
+				if (aci.rc_type_fd != value_p->rc_type_fd) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+					if (target == T_DIR)
+						need_flush = 1;
+#endif
+					aci.rc_type_fd = value_p->rc_type_fd;
+					need_set = 1;
+				}
+				break;
+			case A_rc_force_role:
+				if (aci.rc_force_role != value_p->rc_force_role) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+					if (target == T_DIR)
+						need_flush = 1;
+#endif
+					aci.rc_force_role = value_p->rc_force_role;
+					need_set = 1;
+				}
+				break;
+			case A_rc_initial_role:
+				if (aci.rc_initial_role != value_p->rc_initial_role) {
+					aci.rc_initial_role = value_p->rc_initial_role;
+					need_set = 1;
+				}
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (need_set) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							device_p->handles.rc,
+							0,
+							device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							&aci);
+			}
+		}
+		break;
+#endif				/* RC */
+
+#if defined(CONFIG_RSBAC_AUTH)
+	case SW_AUTH:
+		{
+			struct rsbac_auth_fd_aci_t aci =
+			    DEFAULT_AUTH_FD_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						device_p->handles.auth,
+						NULL,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						&aci);
+			switch (attr) {
+			case A_auth_may_setuid:
+				if (aci.auth_may_setuid != value_p->auth_may_setuid) {
+					aci.auth_may_setuid = value_p->auth_may_setuid;
+					need_set = 1;
+				}
+				break;
+			case A_auth_may_set_cap:
+				if (aci.auth_may_set_cap != value_p->auth_may_set_cap) {
+					aci.auth_may_set_cap = value_p->auth_may_set_cap;
+					need_set = 1;
+				}
+				break;
+			case A_auth_learn:
+				if (aci.auth_learn != value_p->auth_learn) {
+					aci.auth_learn = value_p->auth_learn;
+					need_set = 1;
+				}
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (need_set) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							device_p->handles.auth,
+							0,
+							device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							&aci);
+			}
+		}
+		break;
+#endif				/* AUTH */
+
+#if defined(CONFIG_RSBAC_CAP)
+	case SW_CAP:
+		{
+			struct rsbac_cap_fd_aci_t aci = DEFAULT_CAP_FD_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						device_p->handles.cap,
+						NULL,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						&aci);
+			switch (attr) {
+			case A_min_caps:
+				if ((aci.min_caps.cap[0] != value_p->min_caps.cap[0]) || (aci.min_caps.cap[1] != value_p->min_caps.cap[1])) {
+					aci.min_caps.cap[0] = value_p->min_caps.cap[0];
+	                                aci.min_caps.cap[1] = value_p->min_caps.cap[1];
+	                                need_set = 1;
+				}
+				break;
+			case A_max_caps:
+				if ((aci.max_caps.cap[0] != value_p->max_caps.cap[0]) || (aci.max_caps.cap[1] != value_p->max_caps.cap[1])) {
+					aci.max_caps.cap[0] = value_p->max_caps.cap[0];
+	                                aci.max_caps.cap[1] = value_p->max_caps.cap[1];
+	                                need_set = 1;
+				}
+				break;
+			case A_cap_ld_env:
+				if (aci.cap_ld_env != value_p->cap_ld_env) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+					if (target == T_DIR)
+						need_flush = 1;
+#endif
+					aci.cap_ld_env = value_p->cap_ld_env;
+					need_set = 1;
+				}
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (need_set) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    device_p->handles.cap,
+							    0,
+							    device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+	case SW_RES:
+		{
+			struct rsbac_res_fd_aci_t aci = DEFAULT_RES_FD_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						device_p->handles.res,
+						NULL,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						&aci);
+			switch (attr) {
+				case A_res_min:
+					memcpy(&aci.res_min, &value_p->res_array,
+					       sizeof(aci.res_min));
+					break;
+				case A_res_max:
+					memcpy(&aci.res_max, &value_p->res_array,
+					       sizeof(aci.res_max));
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				struct rsbac_res_fd_aci_t def_aci =
+				    DEFAULT_RES_FD_ACI;
+
+				if (memcmp(&aci, &def_aci, sizeof(aci)))
+					err = rsbac_ta_list_add_ttl
+						(ta_number,
+						device_p->handles.res,
+						0,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode, &aci);
+				else
+					err = rsbac_ta_list_remove(ta_number,
+								 device_p->handles.res,
+								 device_p->persist ? (void *)&inode_nr : &tid_p->file.inode);
+#ifdef CONFIG_RSBAC_FD_CACHE
+				need_set = 1;
+#endif
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+	case SW_PAX:
+		{
+			switch (attr) {
+				case A_pax_flags:
+					value_p->pax_flags &= RSBAC_PAX_ALL_FLAGS;
+					err = rsbac_ta_list_add_ttl(ta_number,
+								    device_p->handles.pax,
+								    0,
+								    device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+								    &value_p->pax_flags);
+#ifdef CONFIG_RSBAC_FD_CACHE
+					need_set = 1;
+#endif
+					break;
+
+				default:
+					err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* PAX */
+
+#if defined(CONFIG_RSBAC_UDF)
+	case SW_UDF:
+		{
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+			if (attr == A_udf_checked) {
+				err = rsbac_list_add_ttl(device_p->handles.udfc,
+						       rsbac_udf_ttl,
+#ifdef CONFIG_RSBAC_UDF_PERSIST
+						       device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+#else
+						       &tid_p->file.inode,
+#endif
+						       &value_p->udf_checked);
+			} else
+#endif
+			{
+				struct rsbac_udf_fd_aci_t aci =
+				    DEFAULT_UDF_FD_ACI;
+
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   device_p->handles.udf,
+							   NULL,
+							   device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+							   &aci);
+				switch (attr) {
+				case A_udf_checker:
+					if (aci.udf_checker != value_p->udf_checker) {
+						aci.udf_checker = value_p->udf_checker;
+						need_set = 1;
+					}
+					break;
+				case A_udf_do_check:
+					if (aci.udf_do_check != value_p->udf_do_check) {
+#ifdef CONFIG_RSBAC_FD_CACHE
+						if (target == T_DIR)
+							need_flush = 1;
+#endif
+						aci.udf_do_check = value_p->udf_do_check;
+						need_set = 1;
+					}
+					break;
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+				if (need_set) {
+					err = rsbac_ta_list_add_ttl
+						(ta_number,
+						device_p->handles.udf,
+						0,
+						device_p->persist ? (void *)&inode_nr : &tid_p->file.inode,
+						&aci);
+				}
+			}
+		}
+		break;
+#endif				/* UDF */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+#ifdef CONFIG_RSBAC_FD_CACHE
+	if (!need_flush && need_set && device_p->fd_cache_handle[module]) {
+#ifdef CONFIG_RSBAC_DEBUG
+		char * attr_name = NULL;
+		char * attr_val_name = NULL;
+		if (rsbac_debug_fdcache) {
+		        attr_name = rsbac_kmalloc(32);
+		        attr_val_name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		}
+#endif
+		rsbac_pr_debug(fdcache, "Invalidating fd cache item device %02u:%02u inode %lu, module %u, attr %s, new value %s\n",
+				RSBAC_MAJOR(tid_p->file.device), RSBAC_MINOR(tid_p->file.device),
+				tid_p->file.inode, module, get_attribute_name(attr_name, attr), get_attribute_value_name(attr_val_name, attr, value_p));
+		rsbac_list_lol_remove(device_p->fd_cache_handle[module], &tid_p->file.inode);
+#ifdef CONFIG_RSBAC_XSTATS
+		device_p->fd_cache_invalidates++;
+#endif
+#ifdef CONFIG_RSBAC_DEBUG
+		if (attr_name)
+			rsbac_kfree(attr_name);
+		if (attr_val_name)
+			rsbac_kfree(attr_val_name);
+#endif
+	}
+#endif
+
+	/* free access to device_list_head */
+	srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+	if (need_flush) {
+		u_int i;
+		struct rsbac_device_list_head_t *head_p;
+
+		rsbac_pr_debug(fdcache, "Invalidating fd cache for module %u on all devices\n",
+				module);
+		for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+			srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+			head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+			device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+			while (device_p) {
+				if (device_p->fd_cache_handle[module])
+					rsbac_list_lol_remove_all(device_p->fd_cache_handle[module]);
+				device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+			}
+			srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+		}
+	}
+#endif
+
+	return err;
+}
+
+static int set_attr_dev(rsbac_list_ta_number_t ta_number,
+			enum rsbac_switch_target_t module,
+			enum rsbac_target_t target,
+			struct rsbac_dev_desc_t dev,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting dev attribute\n"); */
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_dev_aci_t aci =
+			    DEFAULT_GEN_DEV_ACI;
+
+			if (dev.type > D_char)
+				return -RSBAC_EINVALIDTARGET;
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   dev_handles.gen,
+						   NULL, &dev, &aci);
+			switch (attr) {
+			case A_log_array_low:
+				aci.log_array_low = value_p->log_array_low;
+				break;
+			case A_log_array_high:
+				aci.log_array_high =
+				    value_p->log_array_high;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    dev_handles.
+							    gen, 0, &dev,
+							    &aci);
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_dev_aci_t aci =
+			    DEFAULT_MAC_DEV_ACI;
+
+			if (dev.type > D_char)
+				return -RSBAC_EINVALIDTARGET;
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   dev_handles.mac,
+						   NULL, &dev, &aci);
+			switch (attr) {
+			case A_security_level:
+				aci.sec_level = value_p->security_level;
+				break;
+			case A_mac_categories:
+				aci.mac_categories =
+				    value_p->mac_categories;
+				break;
+			case A_mac_check:
+				aci.mac_check = value_p->mac_check;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    dev_handles.
+							    mac, 0, &dev,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = value_p->rc_type;
+			struct rsbac_dev_desc_t dev_desc;
+			rsbac_list_handle_t handle;
+
+			dev_desc.major = dev.major;
+			dev_desc.minor = dev.minor;
+			switch (dev.type) {
+			case D_char:
+				dev_desc.type = D_char;
+				handle = dev_handles.rc;
+				break;
+			case D_block:
+				dev_desc.type = D_block;
+				handle = dev_handles.rc;
+				break;
+			case D_char_major:
+				if (type > RC_type_max_value)
+					return -RSBAC_EINVALIDVALUE;
+				dev_desc.type = D_char;
+			    	dev_desc.minor = 0;
+				handle = dev_major_handles.rc;
+				break;
+			case D_block_major:
+				if (type > RC_type_max_value)
+					return -RSBAC_EINVALIDVALUE;
+				dev_desc.type = D_block;
+			    	dev_desc.minor = 0;
+				handle = dev_major_handles.rc;
+				break;
+			default:
+				return -RSBAC_EINVALIDTARGET;
+			}
+
+			switch (attr) {
+			case A_rc_type:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    handle,
+							    0,
+							    &dev_desc,
+							    &type);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+
+static int set_attr_ipc(rsbac_list_ta_number_t ta_number,
+			enum rsbac_switch_target_t module,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t *tid_p,
+			enum rsbac_attribute_t attr,
+			union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting ipc attribute"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_ipc_aci_t aci =
+			    DEFAULT_MAC_IPC_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   ipc_handles.mac,
+						   NULL,
+						   &tid_p->ipc, &aci);
+			switch (attr) {
+			case A_security_level:
+				aci.sec_level = value_p->security_level;
+				break;
+			case A_mac_categories:
+				aci.mac_categories =
+				    value_p->mac_categories;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    ipc_handles.
+							    mac, 0,
+							    &tid_p->ipc,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = value_p->rc_type;
+
+			switch (attr) {
+			case A_rc_type:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    ipc_handles.rc,
+							    0,
+							    &tid_p->ipc,
+							    &type);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+	case SW_JAIL:
+		{
+			rsbac_jail_id_t id = value_p->jail_id;
+
+			switch (attr) {
+			case A_jail_id:
+/*				if (id)
+					rsbac_pr_debug(aef,
+						       "Setting jail_id for IPC "
+						       "%s %lu to %u\n",
+						       get_ipc_target_name(tmp,
+						       			   tid_p->ipc.type),
+						       tid_p->ipc.id.id_nr,
+						       id); */
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    ipc_handles.
+							    jail, 0,
+							    &tid_p->ipc,
+							    &id);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+
+static int set_attr_user(rsbac_list_ta_number_t ta_number,
+			 enum rsbac_switch_target_t module,
+			 enum rsbac_target_t target,
+			 union rsbac_target_id_t *tid_p,
+			 enum rsbac_attribute_t attr,
+			 union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting %s user attribute %i "
+		       "for %u to %i\n",
+		       get_switch_target_name(tmp, module), attr,
+		       tid_p->user, value_p->dummy); */
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_user_aci_t aci =
+			    DEFAULT_GEN_U_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.gen,
+						   NULL,
+						   &tid_p->user, &aci);
+			switch (attr) {
+			case A_pseudo:
+				aci.pseudo = value_p->pseudo;
+				break;
+			case A_log_user_based:
+				aci.log_user_based =
+				    value_p->log_user_based;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    gen, 0,
+							    &tid_p->user,
+							    &aci);
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_user_aci_t aci =
+			    DEFAULT_MAC_U_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.mac,
+						   NULL,
+						   &tid_p->user, &aci);
+			switch (attr) {
+			case A_security_level:
+				if (value_p->security_level <
+				    aci.min_security_level)
+					err = -RSBAC_EINVALIDVALUE;
+				else
+					aci.security_level =
+					    value_p->security_level;
+				break;
+			case A_initial_security_level:
+				if ((value_p->security_level <
+				     aci.min_security_level)
+				    || (value_p->security_level >
+					aci.security_level)
+				    )
+					err = -RSBAC_EINVALIDVALUE;
+				else
+					aci.initial_security_level =
+					    value_p->security_level;
+				break;
+			case A_min_security_level:
+				if (value_p->security_level >
+				    aci.security_level)
+					err = -RSBAC_EINVALIDVALUE;
+				else
+					aci.min_security_level =
+					    value_p->security_level;
+				break;
+			case A_mac_categories:
+				if ((value_p->mac_categories & aci.
+				     mac_min_categories) !=
+				    aci.mac_min_categories)
+					err = -RSBAC_EINVALIDVALUE;
+				else
+					aci.mac_categories =
+					    value_p->mac_categories;
+				break;
+			case A_mac_initial_categories:
+				if (((value_p->mac_categories & aci.
+				      mac_min_categories) !=
+				     aci.mac_min_categories)
+				    ||
+				    ((value_p->mac_categories & aci.
+				      mac_categories) !=
+				     value_p->mac_categories)
+				    )
+					err = -RSBAC_EINVALIDVALUE;
+				else
+					aci.mac_initial_categories =
+					    value_p->mac_categories;
+				break;
+			case A_mac_min_categories:
+				if ((value_p->mac_categories & aci.
+				     mac_categories) !=
+				    value_p->mac_categories)
+					err = -RSBAC_EINVALIDVALUE;
+				else
+					aci.mac_min_categories =
+					    value_p->mac_categories;
+				break;
+			case A_system_role:
+			case A_mac_role:
+				aci.system_role = value_p->system_role;
+				break;
+			case A_mac_user_flags:
+				aci.mac_user_flags =
+				    value_p->
+				    mac_user_flags & RSBAC_MAC_U_FLAGS;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    mac, 0,
+							    &tid_p->user,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+	case SW_DAZ:
+		{
+			rsbac_system_role_int_t role =
+			    value_p->system_role;
+
+			switch (attr) {
+			case A_system_role:
+			case A_daz_role:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    daz, 0,
+							    &tid_p->user,
+							    &role);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_FF)
+	case SW_FF:
+		{
+			rsbac_system_role_int_t role =
+			    value_p->system_role;
+
+			switch (attr) {
+			case A_system_role:
+			case A_ff_role:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    ff, 0,
+							    &tid_p->user,
+							    &role);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_user_aci_t aci = DEFAULT_RC_U_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.rc,
+						   NULL,
+						   &tid_p->user, &aci);
+			switch (attr) {
+			case A_rc_def_role:
+				aci.rc_role = value_p->rc_def_role;
+				break;
+			case A_rc_type:
+				aci.rc_type = value_p->rc_type;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    rc, 0,
+							    &tid_p->user,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+	case SW_AUTH:
+		{
+			rsbac_system_role_int_t role =
+			    value_p->system_role;
+
+			switch (attr) {
+			case A_system_role:
+			case A_auth_role:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    auth, 0,
+							    &tid_p->user,
+							    &role);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+	case SW_CAP:
+		{
+			struct rsbac_cap_user_aci_t aci =
+			    DEFAULT_CAP_U_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.cap,
+						   NULL,
+						   &tid_p->user, &aci);
+			switch (attr) {
+			case A_system_role:
+			case A_cap_role:
+				aci.cap_role = value_p->system_role;
+				break;
+			case A_min_caps:
+				aci.min_caps.cap[0] = value_p->min_caps.cap[0];
+				aci.min_caps.cap[1] = value_p->min_caps.cap[1];
+				break;
+			case A_max_caps:
+				aci.max_caps.cap[0] = value_p->max_caps.cap[0];
+				aci.max_caps.cap[1] = value_p->max_caps.cap[1];
+				break;
+			case A_cap_ld_env:
+				aci.cap_ld_env = value_p->cap_ld_env;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    cap, 0,
+							    &tid_p->user,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+	case SW_JAIL:
+		{
+			rsbac_system_role_int_t role =
+			    value_p->system_role;
+
+			switch (attr) {
+			case A_system_role:
+			case A_jail_role:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    jail, 0,
+							    &tid_p->user,
+							    &role);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_RES)
+	case SW_RES:
+		{
+			struct rsbac_res_user_aci_t aci =
+			    DEFAULT_RES_U_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   user_handles.res,
+						   NULL,
+						   &tid_p->user, &aci);
+			switch (attr) {
+			case A_system_role:
+			case A_res_role:
+				aci.res_role = value_p->system_role;
+				break;
+			case A_res_min:
+				memcpy(&aci.res_min, &value_p->res_array,
+				       sizeof(aci.res_min));
+				break;
+			case A_res_max:
+				memcpy(&aci.res_max, &value_p->res_array,
+				       sizeof(aci.res_max));
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				struct rsbac_res_user_aci_t def_aci =
+				    DEFAULT_RES_U_ACI;
+
+				if (tid_p->user != RSBAC_ALL_USERS) {
+					rsbac_uid_t all_users =
+					    RSBAC_ALL_USERS;
+
+					rsbac_ta_list_get_data_ttl
+					    (ta_number, user_handles.res,
+					     NULL, &all_users, &def_aci);
+				}
+				if (memcmp(&aci, &def_aci, sizeof(aci)))
+					err =
+					    rsbac_ta_list_add_ttl
+					    (ta_number, user_handles.res,
+					     0, &tid_p->user, &aci);
+				else
+					err =
+					    rsbac_ta_list_remove(ta_number,
+								 user_handles.
+								 res,
+								 &tid_p->
+								 user);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+	case SW_PAX:
+		{
+			rsbac_system_role_int_t role =
+			    value_p->system_role;
+
+			switch (attr) {
+			case A_system_role:
+			case A_pax_role:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    pax, 0,
+							    &tid_p->user,
+							    &role);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+	case SW_UDF:
+		{
+			rsbac_system_role_int_t role =
+			    value_p->system_role;
+
+			switch (attr) {
+			case A_system_role:
+			case A_udf_role:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    user_handles.
+							    udf, 0,
+							    &tid_p->user,
+							    &role);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+
+static int set_attr_process(rsbac_list_ta_number_t ta_number,
+			    enum rsbac_switch_target_t module,
+			    enum rsbac_target_t target,
+			    union rsbac_target_id_t *tid_p,
+			    enum rsbac_attribute_t attr,
+			    union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting process attribute\n"); */
+	if (!tid_p->process) {
+		rsbac_printk(KERN_WARNING "rsbac_set_attr(): Trying to set attribute for process 0!\n");
+		return -RSBAC_EINVALIDTARGET;
+	}
+	switch (module) {
+	case SW_GEN:
+		{
+			struct rsbac_gen_process_aci_t aci =
+			    DEFAULT_GEN_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.gen,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_vset:
+				aci.vset = value_p->vset;
+				break;
+			case A_log_program_based:
+				aci.log_program_based =
+				    value_p->log_program_based;
+				break;
+			case A_fake_root_uid:
+				aci.fake_root_uid = value_p->fake_root_uid;
+				break;
+			case A_audit_uid:
+				aci.audit_uid = value_p->audit_uid;
+				break;
+			case A_auid_exempt:
+				aci.auid_exempt = value_p->auid_exempt;
+				break;
+			case A_remote_ip:
+				aci.remote_ip = value_p->remote_ip;
+				break;
+			case A_kernel_thread:
+				aci.kernel_thread = value_p->kernel_thread;
+				break;
+#if defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_LOG_PROGRAM_FILE) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+			case A_program_file:
+				aci.program_file =
+				    value_p->program_file;
+				break;
+#endif
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.gen,
+							    0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_process_aci_t aci =
+			    DEFAULT_MAC_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.mac,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_security_level:
+				aci.owner_sec_level =
+				    value_p->security_level;
+				break;
+			case A_initial_security_level:
+				aci.owner_initial_sec_level =
+				    value_p->security_level;
+				break;
+			case A_min_security_level:
+				aci.owner_min_sec_level =
+				    value_p->security_level;
+				break;
+			case A_mac_categories:
+				aci.mac_owner_categories =
+				    value_p->mac_categories;
+				break;
+			case A_mac_initial_categories:
+				aci.mac_owner_initial_categories =
+				    value_p->mac_categories;
+				break;
+			case A_mac_min_categories:
+				aci.mac_owner_min_categories =
+				    value_p->mac_categories;
+				break;
+			case A_current_sec_level:
+				aci.current_sec_level =
+				    value_p->current_sec_level;
+				break;
+			case A_mac_curr_categories:
+				aci.mac_curr_categories =
+				    value_p->mac_categories;
+				break;
+			case A_min_write_open:
+				aci.min_write_open =
+				    value_p->min_write_open;
+				break;
+			case A_min_write_categories:
+				aci.min_write_categories =
+				    value_p->mac_categories;
+				break;
+			case A_max_read_open:
+				aci.max_read_open = value_p->max_read_open;
+				break;
+			case A_max_read_categories:
+				aci.max_read_categories =
+				    value_p->mac_categories;
+				break;
+			case A_mac_process_flags:
+				aci.mac_process_flags =
+				    value_p->
+				    mac_process_flags & RSBAC_MAC_P_FLAGS;
+				break;
+			case A_mac_auto:
+				if (value_p->mac_auto)
+					aci.mac_process_flags |= MAC_auto;
+				else
+					aci.mac_process_flags &= ~MAC_auto;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.mac,
+							    0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+	case SW_DAZ:
+		{
+			struct rsbac_daz_process_aci_t aci =
+			    DEFAULT_DAZ_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.daz,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_daz_scanner:
+				aci.daz_scanner = value_p->daz_scanner;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.
+							    daz, 0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_process_aci_t aci =
+			    DEFAULT_RC_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.rc,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_rc_role:
+				aci.rc_role = value_p->rc_role;
+				break;
+			case A_rc_type:
+				aci.rc_type = value_p->rc_type;
+				break;
+			case A_rc_select_type:
+			        aci.rc_select_type = value_p->rc_select_type;
+			        break;
+			case A_rc_force_role:
+				aci.rc_force_role = value_p->rc_force_role;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.rc,
+							    0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+	case SW_AUTH:
+		{
+			struct rsbac_auth_process_aci_t aci =
+			    DEFAULT_AUTH_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.auth,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_auth_may_setuid:
+				aci.auth_may_setuid =
+				    value_p->auth_may_setuid;
+				break;
+			case A_auth_may_set_cap:
+				aci.auth_may_set_cap =
+				    value_p->auth_may_set_cap;
+				break;
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+			case A_auth_start_uid:
+				aci.auth_start_uid =
+				    value_p->auth_start_uid;
+				break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+			case A_auth_start_euid:
+				aci.auth_start_euid =
+				    value_p->auth_start_euid;
+				break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+			case A_auth_start_gid:
+				aci.auth_start_gid =
+				    value_p->auth_start_gid;
+				break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+			case A_auth_start_egid:
+				aci.auth_start_egid =
+				    value_p->auth_start_egid;
+				break;
+#endif
+#endif
+			case A_auth_learn:
+				aci.auth_learn = value_p->auth_learn;
+				break;
+#endif
+			case A_auth_last_auth:
+				aci.auth_last_auth =
+				    value_p->auth_last_auth;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.auth,
+							    0,
+							    &tid_p->process,
+							    &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_CAP)
+	case SW_CAP:
+		{
+			struct rsbac_cap_process_aci_t aci =
+			    DEFAULT_CAP_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.cap,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_cap_process_hiding:
+				aci.cap_process_hiding =
+				    value_p->cap_process_hiding;
+				break;
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_CAP_LEARN)
+			case A_max_caps_user:
+				aci.max_caps_user.cap[0] = value_p->max_caps_user.cap[0];
+				aci.max_caps_user.cap[1] = value_p->max_caps_user.cap[1];
+				break;
+			case A_max_caps_program:
+				aci.max_caps_program.cap[0] = value_p->max_caps_program.cap[0];
+				aci.max_caps_program.cap[1] = value_p->max_caps_program.cap[1];
+#endif
+				break;
+			case A_cap_ld_env:
+				aci.cap_ld_env = value_p->cap_ld_env;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.
+							    cap, 0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+	case SW_JAIL:
+		{
+			struct rsbac_jail_process_aci_t aci =
+			    DEFAULT_JAIL_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.jail,
+						   NULL, &tid_p->process,
+						   &aci);
+			switch (attr) {
+			case A_jail_id:
+				aci.id = value_p->jail_id;
+				break;
+			case A_jail_parent:
+				aci.parent = value_p->jail_parent;
+				break;
+			case A_jail_ip:
+				aci.ip = value_p->jail_ip;
+				break;
+			case A_jail_flags:
+				aci.flags = value_p->jail_flags;
+				break;
+			case A_jail_max_caps:
+				aci.max_caps.cap[0] = value_p->jail_max_caps.cap[0];
+				aci.max_caps.cap[1] = value_p->jail_max_caps.cap[1];
+				break;
+			case A_jail_scd_get:
+				aci.scd_get = value_p->jail_scd_get;
+				break;
+			case A_jail_scd_modify:
+				aci.scd_modify = value_p->jail_scd_modify;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.jail,
+							    0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+	case SW_UDF:
+		{
+			struct rsbac_udf_process_aci_t aci =
+			    DEFAULT_UDF_P_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   process_handles.udf,
+						   NULL,
+						   &tid_p->process, &aci);
+			switch (attr) {
+			case A_udf_checker:
+				aci.udf_checker = value_p->udf_checker;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    process_handles.
+							    udf, 0,
+							    &tid_p->
+							    process, &aci);
+			}
+		}
+		break;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_UM
+static int set_attr_group(rsbac_list_ta_number_t ta_number,
+			  enum rsbac_switch_target_t module,
+			  enum rsbac_target_t target,
+			  union rsbac_target_id_t *tid_p,
+			  enum rsbac_attribute_t attr,
+			  union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting group attribute\n"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = value_p->rc_type;
+			rsbac_gid_t group_desc;
+
+			group_desc = tid_p->group;
+
+			switch (attr) {
+			case A_rc_type:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    group_handles.
+							    rc, 0,
+							    &group_desc,
+							    &type);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+#endif				/* UM */
+
+#ifdef CONFIG_RSBAC_NET_DEV
+static int set_attr_netdev(rsbac_list_ta_number_t ta_number,
+			   enum rsbac_switch_target_t module,
+			   enum rsbac_target_t target,
+			   union rsbac_target_id_t *tid_p,
+			   enum rsbac_attribute_t attr,
+			   union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting netdev attribute\n"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	case SW_GEN:
+		{
+			struct rsbac_gen_netdev_aci_t aci =
+			    DEFAULT_GEN_NETDEV_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   netdev_handles.gen,
+						   NULL,
+						   &tid_p->netdev, &aci);
+			switch (attr) {
+			case A_log_array_low:
+				aci.log_array_low = value_p->log_array_low;
+				break;
+			case A_log_array_high:
+				aci.log_array_high =
+				    value_p->log_array_high;
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    netdev_handles.
+							    gen, 0,
+							    &tid_p->netdev,
+							    &aci);
+			}
+		}
+		break;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = value_p->rc_type;
+
+			switch (attr) {
+			case A_rc_type:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    netdev_handles.
+							    rc, 0,
+							    &tid_p->netdev,
+							    &type);
+				break;
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+static int set_attr_nettemp(rsbac_list_ta_number_t ta_number,
+			    enum rsbac_switch_target_t module,
+			    enum rsbac_target_t target,
+			    union rsbac_target_id_t *tid_p,
+			    enum rsbac_attribute_t attr,
+			    union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting nettemp attribute\n"); */
+	if (!rsbac_ta_list_exist(ta_number, net_temp_handle, &tid_p->nettemp))
+		return -RSBAC_EINVALIDTARGET;
+	switch (module) {
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+	case SW_GEN:
+		{
+			struct rsbac_gen_netobj_aci_t aci =
+			    DEFAULT_GEN_NETOBJ_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   nettemp_handles.gen,
+						   NULL,
+						   &tid_p->nettemp, &aci);
+			switch (attr) {
+			case A_log_array_low:
+				aci.log_array_low = value_p->log_array_low;
+				break;
+			case A_log_array_high:
+				aci.log_array_high =
+				    value_p->log_array_high;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    nettemp_handles.
+							    gen, 0,
+							    &tid_p->
+							    nettemp, &aci);
+			}
+		}
+		break;
+#endif				/* IND_NETOBJ_LOG */
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_netobj_aci_t aci =
+			    DEFAULT_MAC_NETOBJ_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   nettemp_handles.mac,
+						   NULL,
+						   &tid_p->nettemp, &aci);
+			switch (attr) {
+			case A_security_level:
+				aci.sec_level = value_p->security_level;
+				break;
+			case A_mac_categories:
+				aci.mac_categories =
+				    value_p->mac_categories;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    nettemp_handles.
+							    mac, 0,
+							    &tid_p->
+							    nettemp, &aci);
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			struct rsbac_rc_nettemp_aci_t aci =
+			    DEFAULT_RC_NETTEMP_ACI;
+
+			rsbac_ta_list_get_data_ttl(ta_number,
+						   nettemp_handles.rc,
+						   NULL,
+						   &tid_p->nettemp, &aci);
+			switch (attr) {
+			case A_rc_type:
+				aci.netobj_type = value_p->rc_type;
+				break;
+			case A_rc_type_nt:
+				aci.nettemp_type = value_p->rc_type;
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (!err) {
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    nettemp_handles.
+							    rc, 0,
+							    &tid_p->
+							    nettemp, &aci);
+			}
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+
+static int set_attr_netobj(rsbac_list_ta_number_t ta_number,
+			   enum rsbac_switch_target_t module,
+			   enum rsbac_target_t target,
+			   union rsbac_target_id_t *tid_p,
+			   enum rsbac_attribute_t attr,
+			   union rsbac_attribute_value_t *value_p)
+{
+	int err = 0;
+	/* rsbac_pr_debug(ds, "Setting netobj attribute\n"); */
+	switch (module) {
+#if defined(CONFIG_RSBAC_MAC)
+	case SW_MAC:
+		{
+			struct rsbac_mac_netobj_aci_t aci =
+			    DEFAULT_MAC_NETOBJ_ACI;
+
+			switch (attr) {
+			case A_local_sec_level:
+			case A_local_mac_categories:
+				if (rsbac_ta_list_get_data_ttl(ta_number, lnetobj_handles.mac, NULL, &tid_p->netobj.sock_p, &aci)) {	/* not found -> fallback to template */
+					rsbac_net_temp_id_t temp = 0;
+
+					rsbac_ta_net_lookup_templates
+					    (ta_number, &tid_p->netobj,
+					     &temp, NULL);
+					if (temp)
+						rsbac_ta_list_get_data_ttl
+						    (ta_number,
+						     nettemp_handles.mac,
+						     NULL, &temp, &aci);
+				}
+				break;
+
+			case A_remote_sec_level:
+			case A_remote_mac_categories:
+				if (rsbac_ta_list_get_data_ttl(ta_number, rnetobj_handles.mac, NULL, &tid_p->netobj.sock_p, &aci)) {	/* not found -> fallback to template */
+					rsbac_net_temp_id_t temp = 0;
+
+					rsbac_ta_net_lookup_templates
+					    (ta_number, &tid_p->netobj,
+					     NULL, &temp);
+					if (temp)
+						rsbac_ta_list_get_data_ttl
+						    (ta_number,
+						     nettemp_handles.mac,
+						     NULL, &temp, &aci);
+				}
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+			if (err)
+				break;
+			{
+				switch (attr) {
+				case A_local_sec_level:
+					aci.sec_level =
+					    value_p->security_level;
+					err =
+					    rsbac_ta_list_add_ttl
+					    (ta_number,
+					     lnetobj_handles.mac, 0,
+					     &tid_p->netobj.sock_p, &aci);
+					break;
+				case A_remote_sec_level:
+					aci.sec_level =
+					    value_p->security_level;
+					err =
+					    rsbac_ta_list_add_ttl
+					    (ta_number,
+					     rnetobj_handles.mac, 0,
+					     &tid_p->netobj.sock_p, &aci);
+					break;
+				case A_local_mac_categories:
+					aci.mac_categories =
+					    value_p->mac_categories;
+					err =
+					    rsbac_ta_list_add_ttl
+					    (ta_number,
+					     lnetobj_handles.mac, 0,
+					     &tid_p->netobj.sock_p, &aci);
+					break;
+				case A_remote_mac_categories:
+					aci.mac_categories =
+					    value_p->mac_categories;
+					err =
+					    rsbac_ta_list_add_ttl
+					    (ta_number,
+					     rnetobj_handles.mac, 0,
+					     &tid_p->netobj.sock_p, &aci);
+					break;
+
+				default:
+					err = -RSBAC_EINVALIDATTR;
+				}
+			}
+		}
+		break;
+#endif				/* MAC */
+
+#if defined(CONFIG_RSBAC_RC)
+	case SW_RC:
+		{
+			rsbac_rc_type_id_t type = value_p->rc_type;
+
+			switch (attr) {
+			case A_local_rc_type:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    lnetobj_handles.rc, 0,
+							    &tid_p->netobj.
+							    sock_p, &type);
+				break;
+
+			case A_remote_rc_type:
+				err = rsbac_ta_list_add_ttl(ta_number,
+							    rnetobj_handles.rc, 0,
+							    &tid_p->netobj.
+							    sock_p, &type);
+				break;
+
+			default:
+				err = -RSBAC_EINVALIDATTR;
+			}
+		}
+		break;
+#endif				/* RC */
+
+	default:
+		err = -RSBAC_EINVALIDMODULE;
+	}
+
+	return err;
+}
+#endif				/* UM */
+
+
+int rsbac_ta_set_attr(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_switch_target_t module,
+		      enum rsbac_target_t target,
+		      union rsbac_target_id_t tid,
+		      enum rsbac_attribute_t attr,
+		      union rsbac_attribute_value_t value)
+{
+	int err = 0;
+/*
+#ifdef CONFIG_RSBAC_DEBUG
+      char tmp[RSBAC_MAXNAMELEN];
+#endif
+*/
+	if (!rsbac_initialized) {
+		rsbac_printk(KERN_WARNING "rsbac_set_attr(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_set_attr(): called from interrupt, process %u(%s)!\n",
+				current->pid, current->comm);
+		return -RSBAC_EFROMINTERRUPT;
+	}
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		err = set_attr_fd(ta_number, module, target, &tid, attr, &value);
+		break;
+
+	case T_DEV:
+		err =
+		    set_attr_dev(ta_number, module, target, tid.dev, attr,
+				 &value);
+		break;
+
+	case T_IPC:
+		err =
+		    set_attr_ipc(ta_number, module, target, &tid, attr,
+				 &value);
+		break;
+
+	case T_USER:
+		err =
+		    set_attr_user(ta_number, module, target, &tid, attr,
+				  &value);
+		break;
+
+	case T_PROCESS:
+		err =
+		    set_attr_process(ta_number, module, target, &tid, attr,
+				     &value);
+		break;
+
+#ifdef CONFIG_RSBAC_UM
+	case T_GROUP:
+		err =
+		    set_attr_group(ta_number, module, target, &tid, attr,
+				   &value);
+		break;
+#endif				/* CONFIG_RSBAC_UM */
+
+#ifdef CONFIG_RSBAC_NET_DEV
+	case T_NETDEV:
+		err =
+		    set_attr_netdev(ta_number, module, target, &tid, attr,
+				    &value);
+		break;
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+	case T_NETTEMP:
+		err =
+		    set_attr_nettemp(ta_number, module, target, &tid, attr,
+				     &value);
+		break;
+
+	case T_NETOBJ:
+		err =
+		    set_attr_netobj(ta_number, module, target, &tid, attr,
+				    &value);
+		break;
+#endif				/* NET_OBJ */
+
+		/* switch(target): no valid target */
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+#ifdef CONFIG_RSBAC_XSTATS
+	if (!err)
+		set_attr_count[target]++;
+#endif
+	return err;
+}
+
+/************************************************************************** */
+
+int rsbac_ta_remove_target(rsbac_list_ta_number_t ta_number,
+			   enum rsbac_target_t target,
+			   union rsbac_target_id_t tid)
+{
+	int error = 0;
+	struct rsbac_device_list_item_t *device_p;
+	u_int hash;
+	int srcu_idx;
+	rsbac_inode_nr_t inode_nr;
+
+	if (!rsbac_initialized) {
+		// rsbac_printk(KERN_WARNING "rsbac_ta_remove_target(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_ta_remove_target(): called from interrupt!\n");
+		return -RSBAC_EFROMINTERRUPT;
+	}
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		inode_nr = tid.file.inode;
+		/* rsbac_pr_debug(ds, "Removing file/dir/fifo/symlink ACI\n"); */
+#if defined(CONFIG_RSBAC_MAC)
+		/* file and dir items can also have mac_f_trusets -> remove first */
+		if ((target == T_FILE)
+		    || (target == T_DIR)
+		    )
+			error = rsbac_mac_remove_f_trusets(tid.file);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+		/* file and dir items can also have auth_f_capsets -> remove first */
+		if ((target == T_FILE)
+		    || (target == T_DIR)
+		    )
+			error = rsbac_auth_remove_f_capsets(tid.file);
+#endif
+#if defined(CONFIG_RSBAC_ACL)
+		/* items can also have an acl_fd_item -> remove first */
+		error = rsbac_acl_remove_acl(ta_number, target, tid);
+#endif
+		hash = device_hash(tid.file.device);
+		srcu_idx = srcu_read_lock(&device_list_srcu[hash]);
+
+		device_p = lookup_device(tid.file.device, hash);
+		if (!device_p) {
+			srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+			rsbac_printk(KERN_WARNING "rsbac_remove_target(): unknown device %02u:%02u\n",
+				     RSBAC_MAJOR(tid.file.
+						 device),
+				     RSBAC_MINOR(tid.file.
+						 device));
+			return -RSBAC_EINVALIDDEV;
+		}
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.gen,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#if defined(CONFIG_RSBAC_MAC)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.mac,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.daz,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.dazs,
+#ifdef CONFIG_RSBAC_DAZ_PERSIST
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#else
+				     &tid.file.inode);
+#endif
+#endif
+#endif
+#if defined(CONFIG_RSBAC_FF)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.ff,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.rc,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.auth,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.cap,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.pax,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_RES)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.res,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.udf,
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+		rsbac_ta_list_remove(ta_number,
+				     device_p->handles.udfc,
+#ifdef CONFIG_RSBAC_UDF_PERSIST
+				     device_p->persist ? (void *)&inode_nr : &tid.file.inode);
+#else
+				     &tid.file.inode);
+#endif
+#endif
+#endif
+
+		/* free access to device_list_head */
+		srcu_read_unlock(&device_list_srcu[hash], srcu_idx);
+#ifdef CONFIG_RSBAC_FD_CACHE
+                rsbac_pr_debug(fdcache, "removed FD item device %02u:%02u inode %lu, invalidate cache item\n",
+				RSBAC_MAJOR(tid.file.device), RSBAC_MINOR(tid.file.device),
+				tid.file.inode);
+		rsbac_fd_cache_invalidate(&tid.file);
+#endif
+		break;
+
+	case T_DEV:
+		{
+                  switch (tid.dev.type)
+                    {
+                      case D_block:
+                      case D_char:
+                        rsbac_ta_list_remove(ta_number,
+                                         dev_handles.gen,
+                                         &tid.dev);
+#if defined(CONFIG_RSBAC_MAC)
+                        rsbac_ta_list_remove(ta_number,
+                                         dev_handles.mac,
+                                         &tid.dev);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+                        rsbac_ta_list_remove(ta_number,
+                                         dev_handles.rc,
+                                         &tid.dev);
+#endif
+                        break;
+                      case D_block_major:
+                      case D_char_major:
+                        {
+                          enum rsbac_dev_type_t orig_devtype=tid.dev.type;
+
+                          if (tid.dev.type==D_block_major)    
+                            tid.dev.type=D_block;
+                          else
+                            tid.dev.type=D_char;
+                          rsbac_ta_list_remove(ta_number,
+                                           dev_major_handles.gen,
+                                           &tid.dev);
+#if defined(CONFIG_RSBAC_MAC)
+                          rsbac_ta_list_remove(ta_number,
+                                           dev_major_handles.mac,
+                                           &tid.dev);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+                          rsbac_ta_list_remove(ta_number,
+                                           dev_major_handles.rc,
+                                           &tid.dev);
+#endif
+                          tid.dev.type=orig_devtype;
+                          break;
+                        }
+                      default:
+                        return -RSBAC_EINVALIDTARGET;
+                    }
+		}
+		break;
+
+	case T_IPC:
+		/* rsbac_pr_debug(ds, "Removing ipc ACI\n"); */
+#if defined(CONFIG_RSBAC_MAC)
+		rsbac_ta_list_remove(ta_number, ipc_handles.mac, &tid.ipc);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number, ipc_handles.rc, &tid.ipc);
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+		rsbac_ta_list_remove(ta_number,
+				     ipc_handles.jail, &tid.ipc);
+#endif
+		break;
+
+	case T_USER:
+		/* rsbac_pr_debug(ds, "Removing user ACI"); */
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.gen, &tid.user);
+#if defined(CONFIG_RSBAC_MAC)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.mac, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.daz, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_FF)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.ff, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.rc, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.auth, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.cap, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.jail, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.pax, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_RES)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.res, &tid.user);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+		rsbac_ta_list_remove(ta_number,
+				     user_handles.udf, &tid.user);
+#endif
+		break;
+
+	case T_PROCESS:
+/* too noisy... kicked out.
+		rsbac_pr_debug(ds, "Removing process ACI\n");
+*/
+#if defined(CONFIG_RSBAC_ACL)
+		/* process items can also have an acl_p_item -> remove first */
+		error = rsbac_acl_remove_acl(ta_number, target, tid);
+#endif
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.gen,
+				     &tid.process);
+#if defined(CONFIG_RSBAC_MAC)
+		/* process items can also have mac_p_trusets -> remove first */
+		error = rsbac_mac_remove_p_trusets(tid.process);
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.mac,
+				     &tid.process);
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.daz, &tid.process);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.rc,
+				     &tid.process);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+		/* process items can also have auth_p_capsets -> remove first */
+		error = rsbac_auth_remove_p_capsets(tid.process);
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.auth, &tid.process);
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.cap, &tid.process);
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.jail,
+				     &tid.process);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+		rsbac_ta_list_remove(ta_number,
+				     process_handles.udf, &tid.process);
+#endif
+		break;
+
+#ifdef CONFIG_RSBAC_UM
+	case T_GROUP:
+		/* rsbac_pr_debug(ds, "Removing group ACI\n"); */
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+		rsbac_ta_list_remove(ta_number,
+				     group_handles.rc, &tid.group);
+#endif
+		break;
+#endif				/* CONFIG_RSBAC_UM */
+
+#ifdef CONFIG_RSBAC_NET_DEV
+	case T_NETDEV:
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+		rsbac_ta_list_remove(ta_number,
+				     netdev_handles.gen, &tid.netdev);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number,
+				     netdev_handles.rc, &tid.netdev);
+#endif
+		break;
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+	case T_NETTEMP:
+/* too noisy... kicked out.
+		rsbac_pr_debug(ds, "Removing nettemp ACI\n");
+*/
+#if defined(CONFIG_RSBAC_IND_NETOBJ_LOG)
+		rsbac_ta_list_remove(ta_number,
+				     nettemp_handles.gen, &tid.nettemp);
+#endif
+#if defined(CONFIG_RSBAC_MAC)
+		rsbac_ta_list_remove(ta_number,
+				     nettemp_handles.mac, &tid.nettemp);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number,
+				     nettemp_handles.rc, &tid.nettemp);
+#endif
+#if defined(CONFIG_RSBAC_ACL_NET_OBJ_PROT)
+		rsbac_acl_remove_acl(ta_number, T_NETTEMP_NT, tid);
+		rsbac_acl_remove_acl(ta_number, T_NETTEMP, tid);
+#endif
+		break;
+
+	case T_NETOBJ:
+/* too noisy... kicked out.
+		rsbac_pr_debug(ds, "Removing netobj ACI\n");
+*/
+#if defined(CONFIG_RSBAC_MAC)
+		rsbac_ta_list_remove(ta_number,
+				     lnetobj_handles.mac,
+				     &tid.netobj.sock_p);
+		rsbac_ta_list_remove(ta_number,
+				     rnetobj_handles.mac,
+				     &tid.netobj.sock_p);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+		rsbac_ta_list_remove(ta_number,
+				     lnetobj_handles.rc,
+				     &tid.netobj.sock_p);
+		rsbac_ta_list_remove(ta_number,
+				     rnetobj_handles.rc,
+				     &tid.netobj.sock_p);
+#endif
+		break;
+
+#endif
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+#ifdef CONFIG_RSBAC_XSTATS
+	remove_count[target]++;
+#endif
+	return error;
+}
+EXPORT_SYMBOL(rsbac_ta_remove_target);
+
+int rsbac_ta_list_all_dev(rsbac_list_ta_number_t ta_number,
+			  struct rsbac_dev_desc_t **id_pp)
+{
+	int count = 0;
+	int tmp_count;
+
+	tmp_count = rsbac_ta_list_count(ta_number, dev_handles.gen);
+	if (tmp_count > 0)
+		count += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_ta_list_count(ta_number, dev_handles.mac);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_ta_list_count(ta_number, dev_major_handles.rc);
+	if (tmp_count > 0)
+		count += tmp_count;
+	tmp_count = rsbac_ta_list_count(ta_number, dev_handles.rc);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+	if (id_pp) {
+		struct rsbac_dev_desc_t *i_id_p = NULL;
+		char *pos = NULL;
+#if defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC)
+		u_int i;
+#endif
+
+		if (count > 0) {
+			int i_count = 0;
+
+			i_count = count + 20;	/* max value to expect */
+			*id_pp = rsbac_kmalloc_unlocked(i_count * sizeof(**id_pp));
+			if (!*id_pp)
+				return -RSBAC_ENOMEM;
+			pos = (char *) *id_pp;
+			tmp_count = rsbac_ta_list_get_all_desc(ta_number,
+							       dev_handles.
+							       gen,
+							       (void **)
+							       &i_id_p);
+			if (tmp_count > 0) {
+				if (tmp_count > i_count)
+					tmp_count = i_count;
+				memcpy(pos, i_id_p,
+				       tmp_count * sizeof(*i_id_p));
+				rsbac_kfree(i_id_p);
+				count = tmp_count;
+				i_count -= tmp_count;
+				pos += tmp_count * sizeof(*i_id_p);
+			} else
+				count = 0;
+#if defined(CONFIG_RSBAC_MAC)
+			if (i_count) {
+				tmp_count =
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       dev_handles.
+							       mac,
+							       (void **)
+							       &i_id_p);
+				if (tmp_count > 0) {
+					if (tmp_count > i_count)
+						tmp_count = i_count;
+					for (i = 0; i < tmp_count; i++) {
+						if (!rsbac_ta_list_exist
+						    (ta_number,
+						     dev_handles.gen,
+						     &i_id_p[i])) {
+							memcpy(pos,
+							       &i_id_p[i],
+							       sizeof
+							       (*i_id_p));
+							pos +=
+							    sizeof
+							    (*i_id_p);
+							count++;
+							i_count--;
+						}
+					}
+					rsbac_kfree(i_id_p);
+				}
+			}
+#endif
+#if defined(CONFIG_RSBAC_RC)
+			if (i_count) {
+				tmp_count =
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       dev_major_handles.
+							       rc,
+							       (void **)
+							       &i_id_p);
+				if (tmp_count > 0) {
+					if (tmp_count > i_count)
+						tmp_count = i_count;
+					for (i = 0; i < tmp_count; i++) {
+						i_id_p[i].type +=
+						    (D_block_major -
+						     D_block);
+						memcpy(pos, &i_id_p[i],
+						       sizeof(*i_id_p));
+						pos += sizeof(*i_id_p);
+						count++;
+						i_count--;
+					}
+					rsbac_kfree(i_id_p);
+				}
+			}
+			if (i_count) {
+				tmp_count =
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       dev_handles.
+							       rc,
+							       (void **)
+							       &i_id_p);
+				if (tmp_count > 0) {
+					if (tmp_count > i_count)
+						tmp_count = i_count;
+					for (i = 0; i < tmp_count; i++) {
+						if (!rsbac_ta_list_exist
+						    (ta_number,
+						     dev_handles.gen,
+						     &i_id_p[i]))
+#if defined(CONFIG_RSBAC_MAC)
+							if (!rsbac_ta_list_exist(ta_number, dev_handles.mac, &i_id_p[i]))
+#endif
+								{
+									memcpy
+									    (pos,
+									     &i_id_p
+									     [i],
+									     sizeof
+									     (*i_id_p));
+									pos += sizeof(*i_id_p);
+									count++;
+									i_count--;
+								}
+					}
+					rsbac_kfree(i_id_p);
+				}
+			}
+#endif
+			if (!count)
+				rsbac_kfree(*id_pp);
+		}
+	}
+	return count;
+}
+
+/* Copy new items, of they do not exist. Adjust list counters. */
+static int copy_new_uids(rsbac_list_handle_t list,
+			 rsbac_list_ta_number_t ta_number,
+			 int *count_p,
+			 int *i_count_p, rsbac_uid_t * res_id_p)
+{
+	rsbac_uid_t *i_id_p = NULL;
+	rsbac_boolean_t found;
+	int tmp_count;
+	int i;
+	int j;
+
+	if (!list || !count_p || !i_count_p || !res_id_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!*i_count_p)
+		return 0;
+/*	rsbac_pr_debug(ds, "list %p, ta_number %u, count %u, "
+		       "i_count %u, res_id_p %p, res_id_p[0] %u\n",
+		       list, ta_number, *count_p, *i_count_p, res_id_p,
+		       res_id_p[0]); */
+	tmp_count =
+	    rsbac_ta_list_get_all_desc(ta_number, list, (void **) &i_id_p);
+	if (tmp_count > 0) {
+		if (tmp_count > *i_count_p)
+			tmp_count = *i_count_p;
+		for (i = 0; i < tmp_count; i++) {
+			found = FALSE;
+			for (j = 0; j < *count_p; j++) {
+				if (res_id_p[j] == i_id_p[i]) {
+					found = TRUE;
+					break;
+				}
+			}
+			if (found == FALSE) {
+				res_id_p[*count_p] = i_id_p[i];
+				(*count_p)++;
+				(*i_count_p)--;
+			}
+		}
+		rsbac_kfree(i_id_p);
+	}
+	return 0;
+}
+
+int rsbac_ta_list_all_user(rsbac_list_ta_number_t ta_number,
+			   rsbac_uid_t ** id_pp)
+{
+	int count = 0;
+	int tmp_count;
+
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.gen);
+	if (tmp_count > 0)
+		count += tmp_count;
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.mac);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.daz);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_FF)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.ff);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.rc);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.auth);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.cap);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.jail);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.pax);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RES)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.res);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+	tmp_count = rsbac_ta_list_count(ta_number, user_handles.udf);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+	if (id_pp) {
+		if (count > 0) {
+			int i_count;
+			rsbac_uid_t *i_id_p = NULL;
+
+			i_count = count + 20;	/* max value to expect */
+			*id_pp = rsbac_kmalloc_unlocked(i_count * sizeof(**id_pp));
+			if (!*id_pp)
+				return -RSBAC_ENOMEM;
+			tmp_count = rsbac_ta_list_get_all_desc(ta_number,
+							       user_handles.
+							       gen,
+							       (void **)
+							       &i_id_p);
+			if (tmp_count > 0) {
+				if (tmp_count > i_count)
+					tmp_count = i_count;
+				memcpy(*id_pp, i_id_p,
+				       tmp_count * sizeof(*i_id_p));
+				rsbac_kfree(i_id_p);
+				count = tmp_count;
+				i_count -= tmp_count;
+			} else
+				count = 0;
+#if defined(CONFIG_RSBAC_MAC)
+			copy_new_uids(user_handles.mac, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_DAZ)
+			copy_new_uids(user_handles.daz, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_FF)
+			copy_new_uids(user_handles.ff, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_RC)
+			copy_new_uids(user_handles.rc, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_AUTH)
+			copy_new_uids(user_handles.auth, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_CAP)
+			copy_new_uids(user_handles.cap, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+			copy_new_uids(user_handles.jail, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+			copy_new_uids(user_handles.pax, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_RES)
+			copy_new_uids(user_handles.res, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+			copy_new_uids(user_handles.udf, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+			if (!count)
+				rsbac_kfree(*id_pp);
+		}
+	}
+	return count;
+}
+
+/* Copy new items, of they do not exist. Adjust list counters. */
+static int copy_new_ipcs(rsbac_list_handle_t list,
+			 rsbac_list_ta_number_t ta_number,
+			 int *count_p,
+			 int *i_count_p, struct rsbac_ipc_t * res_id_p)
+{
+	struct rsbac_ipc_t *i_id_p = NULL;
+	rsbac_boolean_t found;
+	int tmp_count;
+	int i;
+	int j;
+
+	if (!list || !count_p || !i_count_p || !res_id_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!*i_count_p)
+		return 0;
+/*	rsbac_pr_debug(ds, "list %p, ta_number %u, count %u, "
+		      "i_count %u, res_id_p %p, res_id_p[0] %u\n",
+		       list, ta_number, *count_p, *i_count_p, res_id_p,
+		       res_id_p[0]); */
+	tmp_count =
+	    rsbac_ta_list_get_all_desc(ta_number, list, (void **) &i_id_p);
+	if (tmp_count > 0) {
+		if (tmp_count > *i_count_p)
+			tmp_count = *i_count_p;
+		for (i = 0; i < tmp_count; i++) {
+			found = FALSE;
+			for (j = 0; j < *count_p; j++) {
+				if (!ipc_compare(&res_id_p[j], &i_id_p[i])) {
+					found = TRUE;
+					break;
+				}
+			}
+			if (found == FALSE) {
+				res_id_p[*count_p] = i_id_p[i];
+				(*count_p)++;
+				(*i_count_p)--;
+			}
+		}
+		rsbac_kfree(i_id_p);
+	}
+	return 0;
+}
+
+int rsbac_ta_list_all_ipc(rsbac_list_ta_number_t ta_number,
+			   struct rsbac_ipc_t ** id_pp)
+{
+	int count = 0;
+#if (defined(CONFIG_RSBAC_MAC) || defined(CONFIG_RSBAC_RC) || defined(CONFIG_RSBAC_JAIL))
+	int tmp_count;
+#endif
+
+#if defined(CONFIG_RSBAC_MAC)
+	tmp_count = rsbac_ta_list_count(ta_number, ipc_handles.mac);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_ta_list_count(ta_number, ipc_handles.rc);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+	tmp_count = rsbac_ta_list_count(ta_number, ipc_handles.jail);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+
+	if (id_pp) {
+		if (count > 0) {
+			int i_count;
+
+			i_count = count + 20;	/* max value to expect */
+			*id_pp = rsbac_kmalloc_unlocked(i_count * sizeof(**id_pp));
+			if (!*id_pp)
+				return -RSBAC_ENOMEM;
+			count = 0;
+
+#if defined(CONFIG_RSBAC_MAC)
+			copy_new_ipcs(ipc_handles.mac, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+			copy_new_ipcs(ipc_handles.rc, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+#if defined(CONFIG_RSBAC_JAIL)
+			copy_new_ipcs(ipc_handles.jail, ta_number, &count,
+				      &i_count, *id_pp);
+#endif
+
+			if (!count)
+				rsbac_kfree(*id_pp);
+		}
+	}
+	return count;
+}
+
+int rsbac_ta_list_all_group(rsbac_list_ta_number_t ta_number,
+			    rsbac_gid_t ** id_pp)
+{
+#if defined(CONFIG_RSBAC_RC_UM_PROT)
+	int count = 0;
+	int tmp_count;
+
+	tmp_count = rsbac_ta_list_count(ta_number, group_handles.rc);
+	if (tmp_count > 0)
+		count += tmp_count;
+	if (id_pp) {
+		if (count > 0) {
+			int i_count;
+			rsbac_gid_t *i_id_p = NULL;
+
+			i_count = count + 20;	/* max value to expect */
+			*id_pp = rsbac_kmalloc_unlocked(i_count * sizeof(**id_pp));
+			if (!*id_pp)
+				return -RSBAC_ENOMEM;
+			tmp_count = rsbac_ta_list_get_all_desc(ta_number,
+							       group_handles.
+							       rc,
+							       (void **)
+							       &i_id_p);
+			if (tmp_count > 0) {
+				if (tmp_count > i_count)
+					tmp_count = i_count;
+				memcpy(*id_pp, i_id_p,
+				       tmp_count * sizeof(*i_id_p));
+				rsbac_kfree(i_id_p);
+				count = tmp_count;
+				i_count -= tmp_count;
+			} else
+				count = 0;
+			if (!count)
+				rsbac_kfree(*id_pp);
+		}
+	}
+	return count;
+#else
+	return 0;
+#endif
+}
+
+
+#ifdef CONFIG_RSBAC_NET_DEV
+int rsbac_ta_net_list_all_netdev(rsbac_list_ta_number_t ta_number,
+				 rsbac_netdev_id_t ** id_pp)
+{
+	int count = 0;
+	int tmp_count;
+
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+	tmp_count = rsbac_ta_list_count(ta_number, netdev_handles.gen);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+	tmp_count = rsbac_ta_list_count(ta_number, netdev_handles.rc);
+	if (tmp_count > 0)
+		count += tmp_count;
+#endif
+	if (id_pp) {
+		rsbac_netdev_id_t *i_id_p = NULL;
+		char *pos = NULL;
+#if defined(CONFIG_RSBAC_RC)
+		u_int i;
+#endif
+
+		if (count > 0) {
+			int i_count = 0;
+
+			i_count = count + 20;	/* max value to expect */
+			*id_pp = rsbac_kmalloc_unlocked(i_count * sizeof(**id_pp));
+			if (!*id_pp)
+				return -RSBAC_ENOMEM;
+			pos = (char *) *id_pp;
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+			tmp_count = rsbac_ta_list_get_all_desc(ta_number,
+							       netdev_handles.
+							       gen,
+							       (void **)
+							       &i_id_p);
+			if (tmp_count > 0) {
+				if (tmp_count > i_count)
+					tmp_count = i_count;
+				memcpy(pos, i_id_p,
+				       tmp_count * sizeof(*i_id_p));
+				rsbac_kfree(i_id_p);
+				count = tmp_count;
+				i_count -= tmp_count;
+				pos += tmp_count * sizeof(*i_id_p);
+			} else
+				count = 0;
+#endif
+#if defined(CONFIG_RSBAC_RC)
+			if (i_count) {
+				tmp_count =
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       netdev_handles.
+							       rc,
+							       (void **)
+							       &i_id_p);
+				if (tmp_count > 0) {
+					if (tmp_count > i_count)
+						tmp_count = i_count;
+					for (i = 0; i < tmp_count; i++) {
+#if defined(CONFIG_RSBAC_IND_NETDEV_LOG)
+						if (!rsbac_ta_list_exist
+						    (ta_number,
+						     netdev_handles.gen,
+						     &i_id_p[i]))
+#endif
+						{
+							memcpy(pos,
+							       &i_id_p[i],
+							       sizeof
+							       (*i_id_p));
+							pos +=
+							    sizeof
+							    (*i_id_p);
+							count++;
+							i_count--;
+						}
+					}
+					rsbac_kfree(i_id_p);
+				}
+			}
+#endif
+			if (!count)
+				rsbac_kfree(*id_pp);
+		}
+	}
+	return count;
+}
+#endif
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+/* Get a template id from a net description */
+int rsbac_net_get_id(rsbac_list_ta_number_t ta_number,
+		     struct rsbac_net_description_t *desc_p,
+		     rsbac_net_temp_id_t * id_p)
+{
+	if (!rsbac_initialized)
+		return -RSBAC_ENOTINITIALIZED;
+	if (!id_p || !desc_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (rsbac_ta_list_get_desc(ta_number,
+				   net_temp_handle,
+				   id_p, desc_p, rsbac_net_compare_data)
+	    )
+		*id_p = RSBAC_NET_UNKNOWN;
+	return 0;
+}
+
+/* get the template ids for a netobj */
+/* set *_temp_p to NULL, if you do not need it */
+int rsbac_ta_net_lookup_templates(rsbac_list_ta_number_t ta_number,
+				  struct rsbac_net_obj_desc_t *netobj_p,
+				  rsbac_net_temp_id_t * local_temp_p,
+				  rsbac_net_temp_id_t * remote_temp_p)
+{
+	struct rsbac_net_description_t *rsbac_net_desc_p;
+	int err = 0;
+	struct net_device *dev;
+
+	if (!netobj_p || !netobj_p->sock_p || !netobj_p->sock_p->sk
+	    || !netobj_p->sock_p->ops)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!local_temp_p && !remote_temp_p)
+		return -RSBAC_EINVALIDVALUE;
+
+	rsbac_net_desc_p = rsbac_kmalloc_unlocked(sizeof(*rsbac_net_desc_p));
+	if (!rsbac_net_desc_p)
+		return -RSBAC_ENOMEM;
+
+	rsbac_net_desc_p->address_family = netobj_p->sock_p->ops->family;
+	rsbac_net_desc_p->type = netobj_p->sock_p->type;
+	rsbac_net_desc_p->protocol = netobj_p->sock_p->sk->sk_protocol;
+	if (netobj_p->sock_p->sk->sk_bound_dev_if) {
+		dev = dev_get_by_index(&init_net, netobj_p->sock_p->sk->
+				     sk_bound_dev_if);
+		if (dev) {
+			strcpy(rsbac_net_desc_p->netdev, dev->name);
+			dev_put(dev);
+		} else
+			rsbac_net_desc_p->netdev[0] = RSBAC_NET_UNKNOWN;
+	} else
+		rsbac_net_desc_p->netdev[0] = RSBAC_NET_UNKNOWN;
+	if (local_temp_p) {
+		switch (rsbac_net_desc_p->address_family) {
+		case AF_INET:
+			if (netobj_p->local_addr) {
+				struct sockaddr_in *addr =
+				    netobj_p->local_addr;
+
+				rsbac_net_desc_p->address =
+				    &addr->sin_addr.s_addr;
+				rsbac_net_desc_p->address_len =
+				    sizeof(__u32);
+				rsbac_net_desc_p->port =
+				    ntohs(addr->sin_port);
+			} else {
+				rsbac_net_desc_p->address =
+				    &inet_sk(netobj_p->sock_p->sk)->
+				    inet_rcv_saddr;
+				rsbac_net_desc_p->address_len =
+				    sizeof(__u32);
+				rsbac_net_desc_p->port =
+				    inet_sk(netobj_p->sock_p->sk)->inet_num;
+			}
+			dev = ip_dev_find(&init_net, *(__u32 *) rsbac_net_desc_p->address);
+
+			if (dev) {
+				strcpy(rsbac_net_desc_p->netdev,
+				       dev->name);
+				dev_put(dev);
+			}
+			break;
+		case AF_UNIX:
+			rsbac_printk(KERN_WARNING "rsbac_ta_net_lookup_templates(): unsupported family AF_UNIX, should be target UNIXSOCK or IPC-anonunix\n");
+			BUG();
+			return -RSBAC_EINVALIDTARGET;
+
+		default:
+			rsbac_net_desc_p->address = NULL;
+			rsbac_net_desc_p->port = RSBAC_NET_UNKNOWN;
+		}
+		if ((err = rsbac_net_get_id(ta_number, rsbac_net_desc_p,
+			local_temp_p))) {
+			*local_temp_p = 0;
+			rsbac_printk(KERN_WARNING "rsbac_net_lookup_templates(): rsbac_net_get_id for local returned error %u\n",
+				     err);
+		}
+		if (rsbac_net_desc_p->address_family == AF_INET)
+			rsbac_pr_debug(ds_net,
+				       "user %u temp id for local is %u\n",
+				       __kuid_val(current_uid()), *local_temp_p);
+	}
+	if (remote_temp_p) {
+		switch (rsbac_net_desc_p->address_family) {
+		case AF_INET:
+			if (netobj_p->remote_addr) {
+				struct sockaddr_in *addr =
+				    netobj_p->remote_addr;
+
+				rsbac_net_desc_p->address =
+				    &addr->sin_addr.s_addr;
+				rsbac_net_desc_p->address_len =
+				    sizeof(__u32);
+				rsbac_net_desc_p->port =
+				    ntohs(addr->sin_port);
+			} else {
+				rsbac_net_desc_p->address =
+				    &inet_sk(netobj_p->sock_p->sk)->inet_daddr;
+				rsbac_net_desc_p->address_len =
+				    sizeof(__u32);
+				rsbac_net_desc_p->port =
+				    ntohs(inet_sk(netobj_p->sock_p->sk)->
+					  inet_dport);
+			}
+			dev = ip_dev_find(&init_net, *(__u32 *) rsbac_net_desc_p->address);
+
+			if (dev) {
+				strcpy(rsbac_net_desc_p->netdev,
+				       dev->name);
+				dev_put(dev);
+			}
+			break;
+		case AF_UNIX:
+			rsbac_printk(KERN_WARNING "rsbac_ta_net_lookup_templates(): unsupported family AF_UNIX, should be target UNIXSOCK or IPC-anonunix\n");
+			return -RSBAC_EINVALIDTARGET;
+
+		default:
+			rsbac_net_desc_p->address = NULL;
+			rsbac_net_desc_p->address_len = 0;
+			rsbac_net_desc_p->port = RSBAC_NET_UNKNOWN;
+		}
+		if ((err =
+		     rsbac_net_get_id(ta_number, rsbac_net_desc_p,
+				      remote_temp_p))) {
+			*remote_temp_p = 0;
+			rsbac_printk(KERN_WARNING "rsbac_net_lookup_templates(): rsbac_net_get_id for remote returned error %u\n",
+				     err);
+		}
+		if (rsbac_net_desc_p->address_family == AF_INET)
+			rsbac_pr_debug(ds_net,
+				       "user %u temp id for remote is %u\n",
+				       __kuid_val(current_uid()), *remote_temp_p);
+	}
+	rsbac_kfree(rsbac_net_desc_p);
+	return 0;
+}
+
+void rsbac_net_obj_cleanup(rsbac_net_obj_id_t netobj)
+{
+	union rsbac_target_id_t tid;
+
+	tid.netobj.sock_p = netobj;
+	rsbac_remove_target(T_NETOBJ, tid);
+}
+
+int rsbac_ta_net_template_exists(rsbac_list_ta_number_t ta_number,
+	rsbac_net_temp_id_t id)
+{
+  return rsbac_ta_list_exist(ta_number, net_temp_handle, &id);
+}
+
+int rsbac_ta_net_template(rsbac_list_ta_number_t ta_number,
+			  enum rsbac_net_temp_syscall_t call,
+			  rsbac_net_temp_id_t id,
+			  union rsbac_net_temp_syscall_data_t *data_p)
+{
+	struct rsbac_net_temp_data_t int_data;
+	int err;
+
+	memset(&int_data, 0, sizeof(int_data));
+	int_data.address_family = AF_MAX;
+	int_data.type = RSBAC_NET_ANY;
+	int_data.protocol = RSBAC_NET_ANY;
+	strcpy(int_data.name, "DEFAULT");
+
+	switch (call) {
+	case NTS_new_template:
+	case NTS_check_id:
+		break;
+	case NTS_copy_template:
+		err = rsbac_ta_list_get_data_ttl(ta_number,
+						 net_temp_handle,
+						 NULL,
+						 &data_p->id, &int_data);
+		if (err)
+			return err;
+		break;
+	default:
+		err = rsbac_ta_list_get_data_ttl(ta_number,
+						 net_temp_handle,
+						 NULL, &id, &int_data);
+		if (err)
+			return err;
+	}
+	/* get data values from user space */
+	switch (call) {
+	case NTS_set_address:
+		if(int_data.address_family == AF_INET) {
+			int i;
+
+			memcpy(&int_data.address.inet, &data_p->address.inet,
+				sizeof(int_data.address.inet));
+			if(int_data.address.inet.nr_addr > RSBAC_NET_NR_INET_ADDR)
+				return -RSBAC_EINVALIDVALUE;
+			for(i=0; i<int_data.address.inet.nr_addr; i++)
+				if(int_data.address.inet.valid_bits[i] > 32)
+					return -RSBAC_EINVALIDVALUE;
+		} else {
+			memcpy(&int_data.address.other, &data_p->address.other,
+				sizeof(int_data.address.other));
+		}
+		return rsbac_ta_list_add_ttl(ta_number, net_temp_handle, 0,
+					     &id, &int_data);
+	case NTS_set_address_family:
+		if(int_data.address_family != data_p->address_family) {
+			int_data.address_family = data_p->address_family;
+			memset(&int_data.address, 0, sizeof(int_data.address));
+		}
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_set_type:
+		int_data.type = data_p->type;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_set_protocol:
+		int_data.protocol = data_p->protocol;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_set_netdev:
+		strncpy(int_data.netdev, data_p->netdev, RSBAC_IFNAMSIZ);
+		int_data.netdev[RSBAC_IFNAMSIZ] = 0;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_set_ports:
+		memcpy(&int_data.ports, &data_p->ports,
+			sizeof(int_data.ports));
+		if(int_data.ports.nr_ports > RSBAC_NET_NR_PORTS)
+			return -RSBAC_EINVALIDVALUE;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_set_name:
+		strncpy(int_data.name, data_p->name,
+			RSBAC_NET_TEMP_NAMELEN - 1);
+		int_data.name[RSBAC_NET_TEMP_NAMELEN - 1] = 0;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_new_template:
+		if (rsbac_ta_list_exist(ta_number, net_temp_handle, &id))
+			return -RSBAC_EEXISTS;
+		strncpy(int_data.name, data_p->name,
+			RSBAC_NET_TEMP_NAMELEN - 1);
+		int_data.name[RSBAC_NET_TEMP_NAMELEN - 1] = 0;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_copy_template:
+		if (rsbac_ta_list_exist(ta_number, net_temp_handle, &id))
+			return -RSBAC_EEXISTS;
+		return rsbac_ta_list_add_ttl(ta_number,
+					     net_temp_handle,
+					     0, &id, &int_data);
+	case NTS_delete_template:
+		return rsbac_ta_list_remove(ta_number, net_temp_handle,
+					    &id);
+	case NTS_check_id:
+		if (rsbac_ta_list_exist(ta_number, net_temp_handle, &id)) {
+			data_p->id = id;
+			return 0;
+		} else
+			return -RSBAC_ENOTFOUND;
+	case NTS_get_address:
+		memcpy(&data_p->address, &int_data.address,
+		       sizeof(int_data.address));
+		return 0;
+	case NTS_get_address_family:
+		data_p->address_family = int_data.address_family;
+		return 0;
+	case NTS_get_type:
+		data_p->type = int_data.type;
+		return 0;
+	case NTS_get_protocol:
+		data_p->protocol = int_data.protocol;
+		return 0;
+	case NTS_get_netdev:
+		strncpy(data_p->netdev, int_data.netdev, RSBAC_IFNAMSIZ);
+		return 0;
+	case NTS_get_ports:
+		memcpy(&data_p->ports, &int_data.ports,
+		       sizeof(int_data.ports));
+		return 0;
+	case NTS_get_name:
+		strcpy(data_p->name, int_data.name);
+		return 0;
+
+	default:
+		return -RSBAC_EINVALIDREQUEST;
+	}
+}
+
+int rsbac_ta_net_list_all_template(rsbac_list_ta_number_t ta_number,
+				   rsbac_net_temp_id_t ** id_pp)
+{
+	if (id_pp)
+		return rsbac_ta_list_get_all_desc(ta_number,
+						  net_temp_handle,
+						  (void **) id_pp);
+	else
+		return rsbac_ta_list_count(ta_number, net_temp_handle);
+}
+
+int rsbac_ta_net_template_exist(rsbac_list_ta_number_t ta_number,
+				rsbac_net_temp_id_t temp)
+{
+	return rsbac_ta_list_exist(ta_number, net_temp_handle, &temp);
+}
+
+int rsbac_net_remote_request(enum rsbac_adf_request_t request)
+{
+	switch (request) {
+	case R_SEND:
+	case R_RECEIVE:
+	case R_READ:
+	case R_WRITE:
+	case R_ACCEPT:
+	case R_CONNECT:
+		return TRUE;
+
+	default:
+		return FALSE;
+	}
+}
+
+#endif				/* NET_OBJ */
+
+#if defined(CONFIG_RSBAC_DAZ)
+EXPORT_SYMBOL(rsbac_daz_get_ttl);
+/* Get ttl for new cache items in seconds */
+rsbac_time_t rsbac_daz_get_ttl(void)
+{
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	return rsbac_daz_ttl;
+#else
+	return 0;
+#endif
+}
+
+EXPORT_SYMBOL(rsbac_daz_set_ttl);
+void rsbac_daz_set_ttl(rsbac_time_t ttl)
+{
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	if (ttl) {
+		if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
+			ttl = RSBAC_LIST_MAX_AGE_LIMIT;
+		rsbac_daz_ttl = ttl;
+	}
+#endif
+}
+
+EXPORT_SYMBOL(rsbac_daz_flush_cache);
+int rsbac_daz_flush_cache(void)
+{
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	u_int i;
+	int srcu_idx;
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+		while (device_p) {
+			rsbac_list_remove_all(device_p->handles.dazs);
+			device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+		}
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+#endif
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+static int rsbac_jail_exists_compare(void * data1, void * data2)
+{
+  struct rsbac_jail_process_aci_t * aci_p = data1;
+
+  return memcmp(&aci_p->id, data2, sizeof(rsbac_jail_id_t));
+}
+
+rsbac_boolean_t rsbac_jail_exists(rsbac_jail_id_t jail_id)
+{
+	rsbac_pid_t pid;
+
+	if(!rsbac_ta_list_get_desc(0,
+				process_handles.jail,
+				&pid,
+				&jail_id,
+				rsbac_jail_exists_compare))
+		return TRUE;
+	else
+		return FALSE;
+}
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+EXPORT_SYMBOL(rsbac_udf_get_ttl);
+/* Get ttl for new cache items in seconds */
+rsbac_time_t rsbac_udf_get_ttl(void)
+{
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	return rsbac_udf_ttl;
+#else
+	return 0;
+#endif
+}
+
+EXPORT_SYMBOL(rsbac_udf_set_ttl);
+void rsbac_udf_set_ttl(rsbac_time_t ttl)
+{
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	if (ttl) {
+		if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
+			ttl = RSBAC_LIST_MAX_AGE_LIMIT;
+		rsbac_udf_ttl = ttl;
+	}
+#endif
+}
+
+EXPORT_SYMBOL(rsbac_udf_flush_cache);
+int rsbac_udf_flush_cache(void)
+{
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+	struct rsbac_device_list_head_t *head_p;
+	struct rsbac_device_list_item_t *device_p;
+	u_int i;
+	int srcu_idx;
+
+	for (i = 0; i < RSBAC_NR_DEVICE_LISTS; i++) {
+		srcu_idx = srcu_read_lock(&device_list_srcu[i]);
+		head_p = srcu_dereference(device_head_p[i], &device_list_srcu[i]);
+		device_p = srcu_dereference(head_p->head, &device_list_srcu[i]);
+		while (device_p) {
+			rsbac_list_remove_all(device_p->handles.udfc);
+			device_p = srcu_dereference(device_p->next, &device_list_srcu[i]);
+		}
+		srcu_read_unlock(&device_list_srcu[i], srcu_idx);
+	}
+#endif
+	return 0;
+}
+#endif
+
+void rsbac_flags_set(unsigned long int rsbac_flags)
+{
+}
diff --git a/rsbac/data_structures/acl_data_structures.c b/rsbac/data_structures/acl_data_structures.c
new file mode 100644
index 0000000..80a7643
--- /dev/null
+++ b/rsbac/data_structures/acl_data_structures.c
@@ -0,0 +1,8440 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of ACL data structures             */
+/* Author and (c) 1999-2018: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 09/Apr/2018                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/acl_data_structures.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/acl.h>
+#include <rsbac/lists.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/getname.h>
+#include <rsbac/acl_getname.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/network.h>
+#include <linux/string.h>
+#include <linux/srcu.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+/* The following global variables are needed for access to ACL data.*/
+
+static struct rsbac_acl_device_list_head_t * device_list_head_p;
+static spinlock_t device_list_lock;
+static struct srcu_struct device_list_srcu;
+static struct lock_class_key device_list_lock_class;
+
+static rsbac_list_handle_t dev_handle = NULL;
+static rsbac_list_handle_t dev_major_handle = NULL;
+static rsbac_list_handle_t scd_handle = NULL;
+static rsbac_list_handle_t group_handle = NULL;
+static rsbac_list_handle_t gm_handle = NULL;
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+static rsbac_list_handle_t netdev_handle = NULL;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+static rsbac_list_handle_t nettemp_nt_handle = NULL;
+static rsbac_list_handle_t nettemp_handle = NULL;
+static rsbac_list_handle_t netobj_handle = NULL;
+#endif
+
+static rsbac_list_handle_t default_fd_handle = NULL;
+static rsbac_list_handle_t default_dev_handle = NULL;
+static rsbac_list_handle_t default_ipc_handle = NULL;
+static rsbac_list_handle_t default_scd_handle = NULL;
+static rsbac_list_handle_t u_handle = NULL;
+static rsbac_list_handle_t default_u_handle = NULL;
+static rsbac_list_handle_t default_p_handle = NULL;
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+static rsbac_list_handle_t g_handle = NULL;
+static rsbac_list_handle_t default_g_handle = NULL;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+static rsbac_list_handle_t default_netdev_handle = NULL;
+static rsbac_acl_rights_vector_t default_netdev_rights = 0;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+static rsbac_list_handle_t default_nettemp_nt_handle = NULL;
+static rsbac_list_handle_t default_netobj_handle = NULL;
+static rsbac_acl_rights_vector_t default_nettemp_nt_rights = 0;
+static rsbac_acl_rights_vector_t default_netobj_rights = 0;
+#endif
+
+static rsbac_acl_group_id_t group_last_new = 0;
+
+static rsbac_acl_rights_vector_t default_fd_rights = 0;
+static rsbac_acl_rights_vector_t default_dev_rights = 0;
+static rsbac_acl_rights_vector_t default_ipc_rights = 0;
+static rsbac_acl_rights_vector_t default_scd_rights = 0;
+static rsbac_acl_rights_vector_t default_u_rights = 0;
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+static rsbac_acl_rights_vector_t default_g_rights = 0;
+#endif
+static rsbac_acl_rights_vector_t default_p_rights = 0;
+
+static struct kmem_cache * acl_device_item_slab = NULL;
+
+/**************************************************/
+/*       Declarations of external functions       */
+/**************************************************/
+
+rsbac_boolean_t writable(struct super_block *sb_p);
+
+/**************************************************/
+/*       Declarations of internal functions       */
+/**************************************************/
+
+/************************************************* */
+/*               Internal Help functions           */
+/************************************************* */
+
+/* nr_hashes is always 2^n, no matter what the macros say */
+
+static u_int nr_fd_hash_bits = RSBAC_ACL_NR_FD_LIST_BITS;
+
+static int entry_compare(void *desc1, void *desc2)
+{
+	int result;
+	struct rsbac_acl_entry_desc_t *i_desc1 = desc1;
+	struct rsbac_acl_entry_desc_t *i_desc2 = desc2;
+
+	result = memcmp(&i_desc1->subj_type,
+			&i_desc2->subj_type, sizeof(i_desc1->subj_type));
+	if (result)
+		return result;
+	else
+		return memcmp(&i_desc1->subj_id,
+			      &i_desc2->subj_id, sizeof(i_desc1->subj_id));
+}
+
+static int dev_compare(void *desc1, void *desc2)
+{
+	int result;
+	struct rsbac_dev_desc_t *i_desc1 = desc1;
+	struct rsbac_dev_desc_t *i_desc2 = desc2;
+
+	result = memcmp(&i_desc1->type,
+			&i_desc2->type, sizeof(i_desc1->type));
+	if (result)
+		return result;
+	result = memcmp(&i_desc1->major,
+			&i_desc2->major, sizeof(i_desc1->major));
+	if (result)
+		return result;
+	return memcmp(&i_desc1->minor,
+		      &i_desc2->minor, sizeof(i_desc1->minor));
+}
+
+static int dev_major_compare(void *desc1, void *desc2)
+{
+	int result;
+	struct rsbac_dev_desc_t *i_desc1 = desc1;
+	struct rsbac_dev_desc_t *i_desc2 = desc2;
+
+	result = memcmp(&i_desc1->type,
+			&i_desc2->type, sizeof(i_desc1->type));
+	if (result)
+		return result;
+	return memcmp(&i_desc1->major,
+		      &i_desc2->major, sizeof(i_desc1->major));
+}
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+static int netdev_compare(void *desc1, void *desc2)
+{
+	return strncmp(desc1, desc2, RSBAC_IFNAMSIZ);
+}
+#endif
+
+static int fd_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static int fd_old_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_FD_OLD_LIST_VERSION:
+		return fd_conv;
+	case RSBAC_ACL_FD_OLD_OLD_LIST_VERSION:
+		return fd_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int dev_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(struct rsbac_dev_desc_t));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static int dev_old_conv(void *old_desc,
+		    void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(struct rsbac_dev_desc_t));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static int dev_old_old_conv(void *old_desc,
+			void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_dev_desc_t *new = new_desc;
+	struct rsbac_dev_t *old = old_desc;
+	rsbac_acl_rights_vector_t *newd = new_data;
+	rsbac_acl_rights_vector_t *oldd = old_data;
+
+
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	new->type = old->type;
+	new->major = RSBAC_MAJOR(old->id);
+	new->minor = RSBAC_MINOR(old->id);
+	*newd = (*oldd & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*oldd & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *dev_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEV_OLD_LIST_VERSION:
+		return dev_conv;
+	case RSBAC_ACL_DEV_OLD_OLD_LIST_VERSION:
+		return dev_old_conv;
+	case RSBAC_ACL_DEV_OLD_OLD_OLD_LIST_VERSION:
+		return dev_old_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int scd_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(__u8));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static int scd_old_conv(void *old_desc,
+		    void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(__u8));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *scd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_SCD_OLD_LIST_VERSION:
+		return scd_conv;
+	case RSBAC_ACL_SCD_OLD_OLD_LIST_VERSION:
+		return scd_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int u_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_uid_t *new = new_desc;
+	rsbac_old_uid_t *old = old_desc;
+
+	*new = *old;
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *u_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_U_OLD_LIST_VERSION:
+		return u_conv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+static int g_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_gid_t *new = new_desc;
+	rsbac_old_gid_t *old = old_desc;
+
+	*new = *old;
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *g_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_G_OLD_LIST_VERSION:
+		return g_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+static int netdev_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_netdev_id_t));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static int netdev_old_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_netdev_id_t));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *netdev_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETDEV_OLD_LIST_VERSION:
+		return netdev_conv;
+	case RSBAC_ACL_NETDEV_OLD_OLD_LIST_VERSION:
+		return netdev_old_conv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+static int nettemp_nt_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_net_temp_id_t));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static int nettemp_nt_old_conv(void *old_desc,
+			   void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_net_temp_id_t));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *nettemp_nt_get_conv(rsbac_version_t
+						old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETTEMP_NT_OLD_LIST_VERSION:
+		return nettemp_nt_conv;
+	case RSBAC_ACL_NETTEMP_NT_OLD_OLD_LIST_VERSION:
+		return nettemp_nt_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int nettemp_old_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_net_temp_id_t));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static int nettemp_conv(void *old_desc,
+			void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_net_temp_id_t));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *nettemp_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETTEMP_OLD_LIST_VERSION:
+		return nettemp_conv;
+	case RSBAC_ACL_NETTEMP_OLD_OLD_LIST_VERSION:
+		return nettemp_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int netobj_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_net_obj_id_t));
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *netobj_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETOBJ_OLD_LIST_VERSION:
+		return netobj_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int gm_conv(void *old_desc,
+		   void *old_data, void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *) new_desc) = *((rsbac_old_uid_t *) old_desc);
+	return 0;
+}
+
+static rsbac_list_conv_function_t *gm_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_GM_OLD_VERSION:
+		return gm_conv;
+	default:
+		return NULL;
+	}
+}
+
+
+static int common_subconv(void *old_desc,
+			  void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_acl_entry_desc_t *new_d = new_desc;
+	struct rsbac_acl_old_entry_desc_t *old_d = old_desc;
+
+	memcpy(new_data, old_data, sizeof(rsbac_acl_rights_vector_t));
+	new_d->subj_type = old_d->subj_type;
+	new_d->subj_id = old_d->subj_id;
+	return 0;
+}
+
+static int common_old_subconv(void *old_desc,
+			  void *old_data, void *new_desc, void *new_data)
+{
+	rsbac_acl_rights_vector_t *new = new_data;
+	rsbac_acl_rights_vector_t *old = old_data;
+	struct rsbac_acl_entry_desc_t *new_d = new_desc;
+	struct rsbac_acl_old_entry_desc_t *old_d = old_desc;
+
+	new_d->subj_type = old_d->subj_type;
+	new_d->subj_id = old_d->subj_id;
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_ACL_SPECIAL_RIGHT_BASE -
+		RSBAC_ACL_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *fd_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_FD_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_FD_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *dev_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEV_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEV_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *scd_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_SCD_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_SCD_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *u_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_U_OLD_LIST_VERSION:
+		return common_subconv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+static rsbac_list_conv_function_t *g_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_G_OLD_LIST_VERSION:
+		return common_subconv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+static rsbac_list_conv_function_t *netdev_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETDEV_OLD_LIST_VERSION:
+		return common_subconv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+static rsbac_list_conv_function_t *nettemp_nt_get_subconv(rsbac_version_t
+						   old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETTEMP_NT_OLD_LIST_VERSION:
+		return common_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *nettemp_get_subconv(rsbac_version_t
+						old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETTEMP_OLD_LIST_VERSION:
+		return common_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *netobj_get_subconv(rsbac_version_t
+						old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_NETOBJ_OLD_LIST_VERSION:
+		return common_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static int gm_subconv(void *old_desc,
+			  void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_acl_group_id_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *gm_get_subconv(rsbac_version_t
+						old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_GM_OLD_VERSION:
+		return gm_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_FD_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_FD_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_dev_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_DEV_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_DEV_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_ipc_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_IPC_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_IPC_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_scd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_SCD_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_SCD_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_u_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_U_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_U_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_p_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_P_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_P_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+static rsbac_list_conv_function_t *def_g_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_G_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_G_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+static rsbac_list_conv_function_t *def_netdev_get_conv(rsbac_version_t
+						old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_NETDEV_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_NETDEV_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+#endif
+
+static rsbac_list_conv_function_t *def_nettemp_nt_get_conv(rsbac_version_t
+						    old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_NETTEMP_NT_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_NETTEMP_NT_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static rsbac_list_conv_function_t *def_netobj_get_conv(rsbac_version_t
+						old_version)
+{
+	switch (old_version) {
+	case RSBAC_ACL_DEF_NETOBJ_OLD_LIST_VERSION:
+		return common_subconv;
+	case RSBAC_ACL_DEF_NETOBJ_OLD_OLD_LIST_VERSION:
+		return common_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+
+/* acl_register_fd_lists() */
+/* register fd ACL lists for device */
+
+static int acl_register_fd_lists(struct rsbac_acl_device_list_item_t
+				 *device_p, kdev_t kdev)
+{
+	int err = 0;
+	int tmperr;
+	struct rsbac_list_lol_info_t lol_info;
+	rsbac_acl_rights_vector_t def_mask = RSBAC_ACL_DEFAULT_FD_MASK;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	/* register all the ACL lists of lists */
+	lol_info.version = RSBAC_ACL_FD_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+					 NULL,
+					 entry_compare,
+					 fd_get_conv,
+					 fd_get_subconv, &def_mask,
+					 NULL,
+					 RSBAC_ACL_FD_FILENAME, kdev,
+					 nr_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_ACL_FD_OLD_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "acl_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_ACL_FD_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	return err;
+}
+
+/* acl_detach_fd_lists() */
+/* detach from fd ACL lists for device */
+
+static int acl_detach_fd_lists(struct rsbac_acl_device_list_item_t
+			       *device_p)
+{
+	int err = 0;
+	int tmperr;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	/* detach all the ACL lists of lists */
+	tmperr = rsbac_list_lol_detach(&device_p->handle,
+				       RSBAC_ACL_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "acl_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_ACL_FD_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	return err;
+}
+
+/************************************************************************** */
+/* The lookup functions return NULL, if the item is not found, and a        */
+/* pointer to the item otherwise.                                           */
+
+/* first the device item lookup */
+static struct rsbac_acl_device_list_item_t *acl_lookup_device(kdev_t kdev)
+{
+	struct rsbac_acl_device_list_head_t *head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	struct rsbac_acl_device_list_item_t *curr = srcu_dereference(head_p->curr, &device_list_srcu);
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!curr || (RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+	    || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+	    ) {
+		curr = srcu_dereference(head_p->head, &device_list_srcu);
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = srcu_dereference(curr->next, &device_list_srcu);
+		}
+		if (curr)
+			device_list_head_p->curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_acl_device_list_item_t *acl_lookup_device_locked(kdev_t kdev)
+{
+	struct rsbac_acl_device_list_item_t *curr = device_list_head_p->curr;
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!curr || (RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+	    || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+	    ) {
+		curr = device_list_head_p->head;
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = curr->next;
+		}
+		if (curr)
+			device_list_head_p->curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/************************************************************************** */
+/* The add_item() functions add an item to the list, set head.curr to it,   */
+/* and return a pointer to the item.                                        */
+/* These functions will NOT check, if there is already an item under the    */
+/* same ID! If this happens, the lookup functions will return the old item! */
+
+/* Create a device item without adding to list. No locking needed. */
+static struct rsbac_acl_device_list_item_t
+*create_device_item(kdev_t kdev)
+{
+	struct rsbac_acl_device_list_item_t *new_item_p;
+
+	/* allocate memory for new device, return NULL, if failed */
+	if (!(new_item_p = rsbac_smalloc_clear_unlocked(acl_device_item_slab)))
+		return NULL;
+	new_item_p->id = kdev;
+	new_item_p->mount_count = 1;
+	return new_item_p;
+}
+
+/* Add an existing device item to list. Locking needed. */
+static struct rsbac_acl_device_list_item_t
+*add_device_item(struct rsbac_acl_device_list_item_t *device_p)
+{
+	struct rsbac_acl_device_list_head_t * new_p;
+	struct rsbac_acl_device_list_head_t * old_p;
+
+	if (!device_p)
+		return NULL;
+
+	spin_lock(&device_list_lock);
+	old_p = device_list_head_p;
+	new_p = rsbac_kmalloc(sizeof(*new_p));
+	*new_p = *old_p;
+	/* add new device to device list */
+	if (!new_p->head) {	/* first device */
+		new_p->head = device_p;
+		new_p->tail = device_p;
+		new_p->curr = device_p;
+		new_p->count = 1;
+		device_p->prev = NULL;
+		device_p->next = NULL;
+	} else {		/* there is another device -> hang to tail */
+		device_p->prev = new_p->tail;
+		device_p->next = NULL;
+		new_p->tail->next = device_p;
+		new_p->tail = device_p;
+		new_p->curr = device_p;
+		new_p->count++;
+	}
+	rcu_assign_pointer(device_list_head_p, new_p);
+	spin_unlock(&device_list_lock);
+	synchronize_srcu(&device_list_srcu);
+	rsbac_kfree(old_p);
+	return device_p;
+}
+
+/************************************************************************** */
+/* The remove_item() functions remove an item from the list. If this item   */
+/* is head, tail or curr, these pointers are set accordingly.               */
+/* To speed up removing several subsequent items, curr is set to the next   */
+/* item, if possible.                                                       */
+/* If the item is not found, nothing is done.                               */
+
+static void clear_device_item(struct rsbac_acl_device_list_item_t
+			      *device_p)
+{
+	if (!device_p)
+		return;
+	acl_detach_fd_lists(device_p);
+	rsbac_sfree(acl_device_item_slab, device_p);;
+}
+
+static void remove_device_item(kdev_t kdev)
+{
+	struct rsbac_acl_device_list_item_t *item_p;
+	struct rsbac_acl_device_list_head_t * new_p;
+	struct rsbac_acl_device_list_head_t * old_p;
+
+	old_p = device_list_head_p;
+	new_p = rsbac_kmalloc(sizeof(*new_p));
+	*new_p = *old_p;
+
+	/* first we must locate the item. */
+	if ((item_p = acl_lookup_device_locked(kdev))) {
+		if (new_p->head == item_p) {	/* item is head */
+			if (new_p->tail == item_p) {	/* item is head and tail = only item -> list will be empty */
+				new_p->head = NULL;
+				new_p->tail = NULL;
+			} else {	/* item is head, but not tail -> next item becomes head */
+				item_p->next->prev = NULL;
+				new_p->head = item_p->next;
+			}
+		} else {	/* item is not head */
+			if (new_p->tail == item_p) {	/*item is not head, but tail -> previous item becomes tail */
+				item_p->prev->next = NULL;
+				new_p->tail = item_p->prev;
+			} else {	/* item is neither head nor tail -> item is cut out */
+				item_p->prev->next = item_p->next;
+				item_p->next->prev = item_p->prev;
+			}
+		}
+
+		/* curr is no longer valid -> reset.                              */
+		new_p->curr = NULL;
+		/* adjust counter */
+		new_p->count--;
+		rcu_assign_pointer(device_list_head_p, new_p);
+		spin_unlock(&device_list_lock);
+		synchronize_rcu();
+		rsbac_kfree(old_p);
+
+		/* now we can remove the item from memory. This means cleaning up */
+		/* everything below. */
+		clear_device_item(item_p);
+	}			/* end of if: item was found */
+	else
+		spin_unlock(&device_list_lock);
+}
+
+/************************************************* */
+/*               proc functions                    */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC)
+static int
+acl_devices_proc_show(struct seq_file *m, void *v)
+{
+	struct rsbac_acl_device_list_item_t *device_p;
+	struct rsbac_acl_device_list_head_t *head_p;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized())
+		return -ENOSYS;
+
+	seq_printf(m, "%u RSBAC ACL Devices\n-------------------\n",
+		    device_list_head_p->count);
+
+	/* wait for read access to device_list_head */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	for (device_p = srcu_dereference(head_p->head, &device_list_srcu); device_p;
+	     device_p = srcu_dereference(device_p->next, &device_list_srcu)) {
+		 seq_printf(m,
+			    "%02u:%02u with mount_count = %u\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id),
+			    device_p->mount_count);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int acl_devices_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, acl_devices_proc_show, NULL);
+}
+
+static const struct file_operations acl_devices_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = acl_devices_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *acl_devices;
+
+static int
+stats_acl_proc_show(struct seq_file *m, void *v)
+{
+	u_int item_count = 0;
+	u_int member_count = 0;
+	struct rsbac_acl_device_list_head_t *head_p;
+	struct rsbac_acl_device_list_item_t *device_p;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "stats_acl_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_acl, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "ACL Status\n-----------\n");
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		item_count = rsbac_list_lol_count(device_p->handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->handle);
+		seq_printf(m,
+			    "device %02u:%02u has %i file ACLs, sum of %i members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), item_count,
+			    member_count);
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	/* dev list */
+	seq_printf(m,
+		    "%li device ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(dev_handle),
+		    rsbac_list_lol_all_subcount(dev_handle));
+	seq_printf(m,
+		    "%li device major ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(dev_major_handle),
+		    rsbac_list_lol_all_subcount(dev_major_handle));
+
+	/* SCD list */
+	seq_printf(m,
+		    "%li scd ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(scd_handle),
+		    rsbac_list_lol_all_subcount(scd_handle));
+
+	/* user list */
+	seq_printf(m,
+		    "%li user ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(u_handle),
+		    rsbac_list_lol_all_subcount(u_handle));
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	/* Linux group list */
+	seq_printf(m,
+		    "%li Linux group ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(g_handle),
+		    rsbac_list_lol_all_subcount(g_handle));
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	/* netdev list */
+	seq_printf(m,
+		    "%li network device ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(netdev_handle),
+		    rsbac_list_lol_all_subcount(netdev_handle));
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	/* nettemp_nt list */
+	seq_printf(m,
+		    "%li network template NT ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(nettemp_nt_handle),
+		    rsbac_list_lol_all_subcount(nettemp_nt_handle));
+	/* nettemp list */
+	seq_printf(m,
+		    "%li network template ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(nettemp_handle),
+		    rsbac_list_lol_all_subcount(nettemp_handle));
+	/* netobj list */
+	seq_printf(m,
+		    "%li network object ACL items, sum of %li members\n",
+		    rsbac_list_lol_count(netobj_handle),
+		    rsbac_list_lol_all_subcount(netobj_handle));
+#endif
+
+	seq_printf(m, "%li groups, last new is %u\n",
+		       rsbac_list_count(group_handle), group_last_new);
+
+	/* protect gm list */
+	seq_printf(m,
+		    "%li group member items, sum of %li group memberships\n",
+		    rsbac_list_lol_count(gm_handle),
+		    rsbac_list_lol_all_subcount(gm_handle));
+	return 0;
+}
+
+static int stats_acl_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_acl_proc_show, NULL);
+}
+
+static const struct file_operations stats_acl_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = stats_acl_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *stats_acl;
+
+static int
+acl_acllist_proc_show(struct seq_file *m, void *v)
+{
+	u_int i, j, k;
+	char tmp1[80], tmp2[80];
+	u_int count = 0;
+	int tmp_count;
+	int tmp_sub_count;
+	u_int member_count = 0;
+	struct rsbac_acl_device_list_head_t *head_p;
+	struct rsbac_acl_device_list_item_t *device_p;
+	rsbac_old_inode_nr_t *fd_desc_p;
+	struct rsbac_dev_desc_t *dev_desc_p;
+	__u8 *scd_desc_p;
+	rsbac_uid_t *u_desc_p;
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	rsbac_gid_t *g_desc_p;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	rsbac_netdev_id_t *netdev_desc_p;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	rsbac_net_temp_id_t *nettemp_desc_p;
+	rsbac_net_obj_id_t *netobj_desc_p;
+#endif
+	struct rsbac_acl_entry_desc_t *sub_desc_p;
+	rsbac_acl_rights_vector_t rights;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "acl_acllist_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_acl, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "ACL Lists\n----------\n");
+
+	seq_printf(m,
+		       "Default FD ACL:          %li members:",
+		       rsbac_list_count(default_fd_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_fd_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+
+	/* default_dev list */
+	seq_printf(m,
+		    "\nDefault Device ACL:      %li members:",
+		    rsbac_list_count(default_dev_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_dev_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+
+	/* default_ipc_list */
+	seq_printf(m,
+		    "\nDefault IPC ACL:         %li members:",
+		    rsbac_list_count(default_ipc_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_ipc_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+
+	/* default_scd_list */
+	seq_printf(m,
+		    "\nDefault SCD ACL:         %li members:",
+		    rsbac_list_count(default_scd_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_scd_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+
+	/* default_u_list */
+	seq_printf(m,
+		    "\nDefault User ACL:        %li members:",
+		    rsbac_list_count(default_u_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_u_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+
+	/* default_p list */
+	seq_printf(m,
+		    "\nDefault Process ACL:     %li members:",
+		    rsbac_list_count(default_p_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_p_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	/* default_g_list */
+	seq_printf(m,
+		    "\nDefault Linux Group ACL: %li members:",
+		    rsbac_list_count(default_g_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_g_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	/* default_netdev list */
+	seq_printf(m,
+		    "\nDefault Network Device ACL:      %li members:",
+		    rsbac_list_count(default_netdev_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_netdev_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	/* default_netdev list */
+	seq_printf(m,
+		    "\nDefault Network Template NT ACL: %li members:",
+		    rsbac_list_count(default_nettemp_nt_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_nettemp_nt_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+	/* default_netobj list */
+	seq_printf(m,
+		    "\nDefault Network Object ACL:      %li members:",
+		    rsbac_list_count(default_netobj_handle));
+	tmp_count =
+	    rsbac_list_get_all_desc(default_netobj_handle,
+				    (void **) &sub_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (RSBAC_UID_SET(sub_desc_p[i].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[i].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+			else
+				seq_printf(m, " %s %u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [i].
+								 subj_type),
+				       RSBAC_UID_NUM(sub_desc_p[i].subj_id));
+		}
+		rsbac_kfree(sub_desc_p);
+	}
+#endif
+
+	seq_printf(m, "\n\nFile/Dir/Fifo/Symlink ACLs:\n");
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		/* reset counters */
+		count = 0;
+		member_count = 0;
+		    seq_printf(m,
+			    "\nDevice %02u:%02u\n inode  count   mask+members",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id));
+		tmp_count = rsbac_list_lol_get_all_desc(device_p->handle,
+							(void **) &fd_desc_p);
+		if (tmp_count > 0) {
+			for (j = 0; j < tmp_count; j++) {
+				    seq_printf(m,
+					    "\n%6u\t  %li\t",
+					    fd_desc_p[j],
+					    rsbac_list_lol_subcount
+					    (device_p->handle,
+					     &fd_desc_p[j]));
+				}
+				if (!rsbac_list_lol_get_data
+				    (device_p->handle,
+				     &fd_desc_p[j], &rights)) {
+					    seq_printf(m,
+						    "%s\n\t\t",
+						    u64tostracl
+						    (tmp1,
+						     rights));
+				}
+					tmp_sub_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->handle,
+				     &fd_desc_p[j],
+				     (void **) &sub_desc_p);
+				if (tmp_sub_count > 0) {
+					for (k = 0;
+					     k < tmp_sub_count;
+					     k++) {
+			if (RSBAC_UID_SET(sub_desc_p[k].subj_id))
+				seq_printf(m, " %s %u/%u,",
+				       get_acl_subject_type_name(tmp1,
+								 sub_desc_p
+								 [k].
+								 subj_type),
+				       RSBAC_UID_SET(sub_desc_p[k].subj_id),
+				       RSBAC_UID_NUM(sub_desc_p[k].subj_id));
+			else
+						    seq_printf(m,
+							    "%s %u, ",
+							    get_acl_subject_type_name
+							    (tmp1,
+							     sub_desc_p
+							     [k].
+							     subj_type),
+							    RSBAC_UID_NUM(sub_desc_p
+							    [k].
+							    subj_id));
+					}
+					rsbac_kfree(sub_desc_p);
+					member_count +=
+					    tmp_sub_count;
+				}
+			count += tmp_count;
+			rsbac_kfree(fd_desc_p);
+		}
+		seq_printf(m,
+			    "\n%u file ACLs, sum of %u members\n", count,
+			    member_count);
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	/* unprotect device list */
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	/* dev list */
+	seq_printf(m,
+		    "\nDevice ACLs:\ntype+id  count  mask+members");
+
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(dev_handle, (void **) &dev_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (dev_handle, &dev_desc_p[i], &rights)) {
+				    seq_printf(m,
+					    "\n%c%02u:%02u\t  %3li\t%s\n\t\t",
+					    'B' + dev_desc_p[i].type,
+					    dev_desc_p[i].major,
+					    dev_desc_p[i].minor,
+					    rsbac_list_lol_subcount
+					    (dev_handle, &dev_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(dev_handle,
+							   &dev_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(dev_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i device ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+
+	/* dev major list */
+	seq_printf(m,
+		    "\nDevice major ACLs:\ntype+id  count  mask+members");
+
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(dev_major_handle,
+					(void **) &dev_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (dev_major_handle, &dev_desc_p[i], &rights)) {
+				    seq_printf(m,
+					    "\n%c%02u\t  %3li\t%s\n\t\t",
+					    'B' + dev_desc_p[i].type,
+					    dev_desc_p[i].major,
+					    rsbac_list_lol_subcount
+					    (dev_major_handle,
+					     &dev_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (dev_major_handle, &dev_desc_p[i],
+			     (void **) &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(dev_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i device major ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+	/* scd list */
+	member_count = 0;
+	seq_printf(m,
+		    "\nSCD ACLs:\nname             count  mask+members");
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(scd_handle, (void **) &scd_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (scd_handle, &scd_desc_p[i], &rights)) {
+				    seq_printf(m,
+					    "\n%-16s  %3li\t%s\n\t\t\t",
+					    get_acl_scd_type_name(tmp1,
+								  scd_desc_p
+								  [i]),
+					    rsbac_list_lol_subcount
+					    (scd_handle, &scd_desc_p[i]),
+					    u64tostracl(tmp2, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(scd_handle,
+							   &scd_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(scd_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%u SCD ACL items, sum of %u members\n", tmp_count,
+		    member_count);
+
+	/* user list */
+	seq_printf(m,
+		    "\nUser ACLs:\nuid      count  mask+members");
+
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(u_handle, (void **) &u_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (u_handle, &u_desc_p[i], &rights)) {
+			        if (RSBAC_UID_SET(u_desc_p[i]))
+					    seq_printf(m,
+					    "\n%u/%u\t  %3li\t%s\n\t\t",
+					    RSBAC_UID_SET(u_desc_p[i]),
+					    RSBAC_UID_NUM(u_desc_p[i]),
+					    rsbac_list_lol_subcount
+					    (u_handle, &u_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			        else
+					    seq_printf(m,
+					    "\n%u\t  %3li\t%s\n\t\t",
+					    RSBAC_UID_NUM(u_desc_p[i]),
+					    rsbac_list_lol_subcount
+					    (u_handle, &u_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(u_handle,
+							   &u_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(u_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i user ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	/* Linux group list */
+	seq_printf(m,
+		    "\nLinux group ACLs:\ngid      count  mask+members");
+
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(g_handle, (void **) &g_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (g_handle, &g_desc_p[i], &rights)) {
+			        if (RSBAC_GID_SET(g_desc_p[i]))
+					    seq_printf(m,
+					    "\n%u/%u\t  %3li\t%s\n\t\t",
+					    RSBAC_GID_SET(g_desc_p[i]),
+					    RSBAC_GID_NUM(g_desc_p[i]),
+					    rsbac_list_lol_subcount
+					    (g_handle, &g_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			        else
+					    seq_printf(m,
+					    "\n%u\t  %3li\t%s\n\t\t",
+					    RSBAC_GID_NUM(g_desc_p[i]),
+					    rsbac_list_lol_subcount
+					    (g_handle, &g_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(g_handle,
+							   &g_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_GID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_GID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_GID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(g_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i Linux group ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	/* netdev list */
+	seq_printf(m,
+		    "\nNetwork Device ACLs:\nname\t\t count  mask+members");
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(netdev_handle,
+					(void **) &netdev_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (netdev_handle, &netdev_desc_p[i], &rights)) {
+				    seq_printf(m,
+					    "\n%-16s  %3li\t  %s\n\t\t",
+					    netdev_desc_p[i],
+					    rsbac_list_lol_subcount
+					    (netdev_handle,
+					     &netdev_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(netdev_handle,
+							   &netdev_desc_p
+							   [i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(netdev_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i network device ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	/* nettemp_nt list */
+	seq_printf(m,
+		    "\nNetwork Template NT (template protection) ACLs:\nTemplate   count  mask+members");
+
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(nettemp_nt_handle,
+					(void **) &nettemp_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (nettemp_nt_handle, &nettemp_desc_p[i],
+			     &rights)) {
+				    seq_printf(m,
+					    "\n%10u %3li\t%s\n\t\t",
+					    nettemp_desc_p[i],
+					    rsbac_list_lol_subcount
+					    (nettemp_nt_handle,
+					     &nettemp_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (nettemp_nt_handle, &nettemp_desc_p[i],
+			     (void **) &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(nettemp_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i network template NT ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+
+	/* nettemp list */
+	seq_printf(m,
+		    "\nNetwork Template (netobj protection) ACLs:\nTemplate   count  mask+members");
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(nettemp_handle,
+					(void **) &nettemp_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (nettemp_handle, &nettemp_desc_p[i],
+			     &rights)) {
+				    seq_printf(m,
+					    "\n%10u %3li\t%s\n\t\t",
+					    nettemp_desc_p[i],
+					    rsbac_list_lol_subcount
+					    (nettemp_handle,
+					     &nettemp_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(nettemp_handle,
+							   &nettemp_desc_p
+							   [i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(nettemp_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i network template ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+
+	/* netobj list */
+	seq_printf(m,
+		    "\nNetwork Object ACLs:\nObject-ID count  mask+members");
+
+	member_count = 0;
+	tmp_count =
+	    rsbac_list_lol_get_all_desc(netobj_handle,
+					(void **) &netobj_desc_p);
+	if (tmp_count > 0) {
+		for (i = 0; i < tmp_count; i++) {
+			if (!rsbac_list_lol_get_data
+			    (netobj_handle, &netobj_desc_p[i], &rights)) {
+				 seq_printf(m,
+					    "\n%p   %3li\t%s\n\t\t",
+					    netobj_desc_p[i],
+					    rsbac_list_lol_subcount
+					    (netobj_handle,
+					     &netobj_desc_p[i]),
+					    u64tostracl(tmp1, rights));
+			}
+			tmp_sub_count =
+			    rsbac_list_lol_get_all_subdesc(netobj_handle,
+							   &netobj_desc_p
+							   [i],
+							   (void **)
+							   &sub_desc_p);
+			if (tmp_sub_count > 0) {
+				for (j = 0; j < tmp_sub_count; j++) {
+					if (RSBAC_UID_SET(sub_desc_p[j].subj_id))
+						seq_printf(m, " %s %u/%u,",
+						       get_acl_subject_type_name(tmp1,
+									 sub_desc_p
+									 [j].
+									 subj_type),
+						       RSBAC_UID_SET(sub_desc_p[j].subj_id),
+						       RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+					else
+					    seq_printf(m,
+						    "%s %u, ",
+						    get_acl_subject_type_name
+						    (tmp1,
+						     sub_desc_p[j].
+						     subj_type),
+						    RSBAC_UID_NUM(sub_desc_p[j].subj_id));
+				}
+				rsbac_kfree(sub_desc_p);
+				member_count += tmp_sub_count;
+			}
+		}
+		rsbac_kfree(netobj_desc_p);
+	}
+	seq_printf(m,
+		    "\n\n%i network object ACL items, sum of %u members\n",
+		    tmp_count, member_count);
+#endif
+
+	return 0;
+}
+
+static int acl_acllist_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, acl_acllist_proc_show, NULL);
+}
+
+static const struct file_operations acl_acllist_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = acl_acllist_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *acl_acllist;
+
+static int
+acl_grouplist_proc_show(struct seq_file *m, void *v)
+{
+	char type;
+	int count, sub_count;
+	int i, j;
+	u_int member_count = 0;
+	struct rsbac_acl_group_entry_t *entry_p;
+	rsbac_uid_t *user_p;
+	rsbac_acl_group_id_t *group_p;
+	rsbac_time_t *ttl_p;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "acl_grouplist_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_acl, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "ACL Groups\n----------\n");
+
+	/* group list */
+	seq_printf(m,
+		    "Group list:  %li groups, last new is %u\nID\ttype name\t\towner\n",
+		    rsbac_list_count(group_handle), group_last_new);
+
+	count = rsbac_list_get_all_data(group_handle, (void **) &entry_p);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			if (entry_p[i].type == ACLG_GLOBAL)
+				type = 'G';
+			else
+				type = 'P';
+			if (RSBAC_UID_SET(entry_p[i].owner))
+				    seq_printf(m, "%u\t%c    %-18s %u/%u\n",
+					    entry_p[i].id, type, entry_p[i].name,
+					    RSBAC_UID_SET(entry_p[i].owner),
+					    RSBAC_UID_NUM(entry_p[i].owner));
+			else
+				    seq_printf(m, "%u\t%c    %-18s %u\n",
+					    entry_p[i].id, type, entry_p[i].name,
+					    RSBAC_UID_NUM(entry_p[i].owner));
+		}
+		rsbac_kfree(entry_p);
+	}
+
+	/* group member list */
+	member_count = 0;
+	seq_printf(m,
+		    "\nGroup memberships:\nuser   count\tgroups");
+
+	count = rsbac_list_lol_get_all_desc(gm_handle, (void **) &user_p);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			sub_count =
+			    rsbac_list_lol_get_all_subdesc_ttl(gm_handle,
+							       &user_p[i],
+							       (void **)
+							       &group_p,
+							       &ttl_p);
+			if (RSBAC_UID_SET(user_p[i]))
+				    seq_printf(m, "\n%u/%u\t%i\t",
+					    RSBAC_UID_SET(user_p[i]),
+					    RSBAC_UID_NUM(user_p[i]),
+					    sub_count);
+			else
+				    seq_printf(m, "\n%u\t%i\t",
+					    RSBAC_UID_NUM(user_p[i]),
+					    sub_count);
+			if (sub_count > 0) {
+				for (j = 0; j < sub_count; j++) {
+					if (ttl_p[j])
+						    seq_printf(m,
+							    "%u(ttl:%i) ",
+							    group_p[j],
+							    ttl_p[j]);
+					else
+						    seq_printf(m,
+							    "%u ",
+							    group_p[j]);
+				}
+				member_count += sub_count;
+				rsbac_kfree(group_p);
+				rsbac_kfree(ttl_p);
+			}
+		}
+		rsbac_kfree(user_p);
+	}
+	seq_printf(m,
+		    "\n\n%u user items, sum of %u memberships\n", count,
+		    member_count);
+	return 0;
+}
+
+static int acl_grouplist_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, acl_grouplist_proc_show, NULL);
+}
+
+static const struct file_operations acl_grouplist_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = acl_grouplist_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *acl_grouplist;
+
+#endif
+
+
+/************************************************* */
+/*               Init functions                    */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac/error.h.                 */
+
+/************************************************************************** */
+/* Initialization of all ACL data structures. After this call, all ACL    */
+/* data is kept in memory for performance reasons, but is written to disk   */
+/* on every change. */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static void registration_error(int err, char *listname)
+#else
+static void __init registration_error(int err, char *listname)
+#endif
+{
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_acl(): Registering ACL %s list failed with error %s\n",
+				     listname, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+}
+
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+void acl_create_def(void)
+#else
+void __init acl_create_def(void)
+#endif
+{
+	if (!rsbac_list_count(default_fd_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_FD_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_FD_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_FD_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): File/Dir default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_fd_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_fd_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_fd_handle, &desc,
+			       &gen_entry.rights);
+	}
+	if (!rsbac_list_count(default_dev_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_DEV_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_DEV_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_DEV_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Device default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_dev_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_dev_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_dev_handle, &desc,
+			       &gen_entry.rights);
+	}
+	if (!rsbac_list_count(default_ipc_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_IPC_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_IPC_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_IPC_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): IPC default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_ipc_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_ipc_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_ipc_handle, &desc,
+			       &gen_entry.rights);
+	}
+	if (!rsbac_list_count(default_scd_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_SCD_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): SCD default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_scd_handle, &desc,
+			       &acman_entry.rights);
+	}
+	if (!rsbac_list_lol_count(scd_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		rsbac_acl_rights_vector_t mask =
+		    RSBAC_ACL_DEFAULT_SCD_MASK;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_SCD_ENTRY;
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+		struct rsbac_acl_entry_t gen_ioports_entry =
+		    RSBAC_ACL_GENERAL_SCD_IOPORTS_ENTRY;
+#endif
+		struct rsbac_acl_entry_t gen_other_entry =
+		    RSBAC_ACL_GENERAL_SCD_OTHER_ENTRY;
+		struct rsbac_acl_entry_t gen_network_entry =
+		    RSBAC_ACL_GENERAL_SCD_NETWORK_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_SCD_ENTRY;
+		struct rsbac_acl_entry_t sysadm_other_entry =
+		    RSBAC_ACL_SYSADM_SCD_OTHER_ENTRY;
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+		struct rsbac_acl_entry_t sysadm_kmem_entry =
+		    RSBAC_ACL_SYSADM_SCD_KMEM_ENTRY;
+#endif
+		struct rsbac_acl_entry_t acman_other_entry =
+		    RSBAC_ACL_ACMAN_SCD_OTHER_ENTRY;
+		struct rsbac_acl_entry_t auditor_rsbaclog_entry =
+		    RSBAC_ACL_AUDITOR_SCD_RSBACLOG_ENTRY;
+		__u8 scd;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): SCD ACLs empty on dev %02u:%02u, generating standard entries!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		scd = ST_rlimit;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = gen_entry.subj_type;
+			desc.subj_id = gen_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &gen_entry.rights);
+		}
+		for (scd = ST_time_strucs; scd <= ST_rsbac; scd++) {
+			if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+				desc.subj_type = sysadm_entry.subj_type;
+				desc.subj_id = sysadm_entry.subj_id;
+				rsbac_list_lol_subadd(scd_handle, &scd,
+						      &desc,
+						      &sysadm_entry.
+						      rights);
+			}
+		}
+		scd = ST_rsbac_log;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = auditor_rsbaclog_entry.subj_type;
+			desc.subj_id = auditor_rsbaclog_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &auditor_rsbaclog_entry.
+					      rights);
+		}
+		scd = ST_network;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = sysadm_entry.subj_type;
+			desc.subj_id = sysadm_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &sysadm_entry.rights);
+			desc.subj_type = gen_network_entry.subj_type;
+			desc.subj_id = gen_network_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &gen_network_entry.rights);
+		}
+		scd = ST_firewall;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = sysadm_entry.subj_type;
+			desc.subj_id = sysadm_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &sysadm_entry.rights);
+			desc.subj_type = gen_network_entry.subj_type;
+			desc.subj_id = gen_network_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &gen_network_entry.rights);
+		}
+		scd = ST_priority;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = sysadm_entry.subj_type;
+			desc.subj_id = sysadm_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &sysadm_entry.rights);
+		}
+		scd = ST_sysfs;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = sysadm_entry.subj_type;
+			desc.subj_id = sysadm_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &sysadm_entry.rights);
+		}
+		for (scd = ST_quota; scd < ST_none; scd++)
+			if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+				desc.subj_type = sysadm_entry.subj_type;
+				desc.subj_id = sysadm_entry.subj_id;
+				rsbac_list_lol_subadd(scd_handle, &scd,
+						      &desc,
+						      &sysadm_entry.
+						      rights);
+			}
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+		scd = ST_ioports;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = gen_ioports_entry.subj_type;
+			desc.subj_id = gen_ioports_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &gen_ioports_entry.rights);
+		}
+		scd = ST_kmem;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = sysadm_kmem_entry.subj_type;
+			desc.subj_id = sysadm_kmem_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &sysadm_kmem_entry.rights);
+		}
+#endif
+
+		scd = ST_other;
+		if (!rsbac_list_lol_add(scd_handle, &scd, &mask)) {
+			desc.subj_type = sysadm_other_entry.subj_type;
+			desc.subj_id = sysadm_other_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &sysadm_other_entry.rights);
+			desc.subj_type = acman_other_entry.subj_type;
+			desc.subj_id = acman_other_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &acman_other_entry.rights);
+			desc.subj_type = gen_other_entry.subj_type;
+			desc.subj_id = gen_other_entry.subj_id;
+			rsbac_list_lol_subadd(scd_handle, &scd, &desc,
+					      &gen_other_entry.rights);
+		}
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+void acl_create_def2(void)
+#else
+void __init acl_create_def2(void)
+#endif
+{
+	if (!rsbac_list_count(default_u_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_U_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_U_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_U_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): User default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_u_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_u_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_u_handle, &desc, &gen_entry.rights);
+	}
+	if (!rsbac_list_count(default_p_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_P_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_P_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_P_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Process default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_p_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_p_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_p_handle, &desc, &gen_entry.rights);
+	}
+	if (!rsbac_list_lol_count(gm_handle)) {
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Group membership list empty on dev %02u:%02u!\n",
+		     RSBAC_MAJOR(rsbac_root_dev),
+		     RSBAC_MINOR(rsbac_root_dev));
+	}
+	if (!rsbac_list_count(group_handle)) {
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Group list empty on dev %02u:%02u!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+	} else {
+		rsbac_list_get_max_desc(group_handle, &group_last_new);
+	}
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	if (!rsbac_list_count(default_g_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_G_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_G_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_G_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Linux group default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_g_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_g_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_g_handle, &desc, &gen_entry.rights);
+	}
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	if (!rsbac_list_count(default_netdev_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_NETDEV_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_NETDEV_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_NETDEV_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Network Device default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_netdev_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_netdev_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_netdev_handle, &desc,
+			       &gen_entry.rights);
+	}
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	if (!rsbac_no_defaults
+	    && !rsbac_list_count(default_nettemp_nt_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_NETTEMP_NT_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_NETTEMP_NT_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_NETTEMP_NT_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Network Template NT (template protection) default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_nettemp_nt_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_nettemp_nt_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_nettemp_nt_handle, &desc,
+			       &gen_entry.rights);
+	}
+	if (!rsbac_list_count(default_netobj_handle)) {
+		struct rsbac_acl_entry_desc_t desc;
+		struct rsbac_acl_entry_t acman_entry =
+		    RSBAC_ACL_ACMAN_NETOBJ_ENTRY;
+		struct rsbac_acl_entry_t sysadm_entry =
+		    RSBAC_ACL_SYSADM_NETOBJ_ENTRY;
+		struct rsbac_acl_entry_t gen_entry =
+		    RSBAC_ACL_GENERAL_NETOBJ_ENTRY;
+
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): Network Object default ACL empty on dev %02u:%02u, generating standard ACL!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev));
+		desc.subj_type = acman_entry.subj_type;
+		desc.subj_id = acman_entry.subj_id;
+		rsbac_list_add(default_netobj_handle, &desc,
+			       &acman_entry.rights);
+		desc.subj_type = sysadm_entry.subj_type;
+		desc.subj_id = sysadm_entry.subj_id;
+		rsbac_list_add(default_netobj_handle, &desc,
+			       &sysadm_entry.rights);
+		desc.subj_type = gen_entry.subj_type;
+		desc.subj_id = gen_entry.subj_id;
+		rsbac_list_add(default_netobj_handle, &desc,
+			       &gen_entry.rights);
+	}
+#endif
+}
+
+/* Because there can be no access to aci data structures before init, */
+/* rsbac_init_acl() will initialize all rw-spinlocks to unlocked. */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_acl(void)
+#else
+int __init rsbac_init_acl(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p = NULL;
+	char tmp[80];
+	struct rsbac_list_lol_info_t lol_info;
+	struct rsbac_list_info_t list_info;
+	rsbac_acl_rights_vector_t def_mask;
+
+	if (rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+
+	/* set rw-spinlocks to unlocked status and init data structures */
+	rsbac_printk(KERN_INFO "rsbac_init_acl(): Initializing RSBAC: ACL subsystem\n");
+
+	acl_device_item_slab = rsbac_slab_create_rcu("rsbac_acl_device_item",
+				sizeof(struct rsbac_acl_device_list_item_t));
+
+	/* Init device list */
+	device_list_head_p = kmalloc(sizeof(*device_list_head_p), GFP_KERNEL);
+	if (!device_list_head_p) {
+		rsbac_printk(KERN_WARNING
+			"rsbac_init_acl(): Failed to allocate device_list_head\n");
+		return -ENOMEM;
+	}
+	spin_lock_init(&device_list_lock);
+	init_srcu_struct(&device_list_srcu);
+	lockdep_set_class(&device_list_lock, &device_list_lock_class);
+	device_list_head_p->head = NULL;
+	device_list_head_p->tail = NULL;
+	device_list_head_p->curr = NULL;
+	device_list_head_p->count = 0;
+
+	/* register ACL lists */
+	rsbac_pr_debug(ds_acl, "Registering lists\n");
+	device_p = create_device_item(rsbac_root_dev);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_init_acl(): Could not create device!\n");
+		return -RSBAC_ECOULDNOTADDDEVICE;
+	}
+	if ((err = acl_register_fd_lists(device_p, rsbac_root_dev))) {
+		rsbac_printk(KERN_WARNING "rsbac_init_acl(): File/Dir ACL registration failed for dev %02u:%02u, err %s!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev),
+			     get_error_name(tmp, err));
+	}
+	device_p = add_device_item(device_p);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_init_acl(): Could not add device!\n");
+		return -RSBAC_ECOULDNOTADDDEVICE;
+	}
+
+	list_info.version = RSBAC_ACL_DEF_FD_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_fd_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_fd_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_FD_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default fd");
+	}
+
+	lol_info.version = RSBAC_ACL_DEV_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(struct rsbac_dev_desc_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_DEV_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &dev_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST |
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+				      dev_compare,
+				      entry_compare, dev_get_conv,
+				      dev_get_subconv, &def_mask, NULL,
+				      RSBAC_ACL_DEV_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_dev,
+					NULL);
+	if (err) {
+		registration_error(err, "dev");
+	}
+	lol_info.version = RSBAC_ACL_DEV_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(struct rsbac_dev_desc_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_DEV_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &dev_major_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST |
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+				      dev_major_compare, entry_compare,
+				      dev_get_conv, dev_get_subconv,
+				      &def_mask, NULL,
+				      RSBAC_ACL_DEV_MAJOR_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_dev,
+					NULL);
+	if (err) {
+		registration_error(err, "dev major");
+	}
+	list_info.version = RSBAC_ACL_DEF_DEV_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_dev_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_dev_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_DEV_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default dev");
+	}
+
+	list_info.version = RSBAC_ACL_DEF_IPC_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_ipc_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_ipc_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_IPC_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default ipc");
+	}
+
+	lol_info.version = RSBAC_ACL_SCD_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(__u8);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_SCD_MASK;
+	err = rsbac_list_lol_register(RSBAC_LIST_VERSION,
+				      &scd_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST |
+				      RSBAC_LIST_DEF_DATA, NULL,
+				      entry_compare, scd_get_conv,
+				      scd_get_subconv, &def_mask, NULL,
+				      RSBAC_ACL_SCD_FILENAME,
+				      RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "scd");
+	}
+
+	list_info.version = RSBAC_ACL_DEF_SCD_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_scd_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_scd_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_SCD_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default scd");
+	}
+
+	lol_info.version = RSBAC_ACL_U_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_uid_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_U_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &u_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      entry_compare,
+				      u_get_conv,
+				      u_get_subconv,
+				      &def_mask,
+				      NULL,
+				      RSBAC_ACL_U_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_uid,
+					NULL);
+	if (err) {
+		registration_error(err, "user");
+	}
+	list_info.version = RSBAC_ACL_DEF_U_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_u_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_u_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_U_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default user");
+	}
+
+	list_info.version = RSBAC_ACL_DEF_P_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_p_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_p_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_P_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default process");
+	}
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	lol_info.version = RSBAC_ACL_G_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_gid_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_G_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &g_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      entry_compare,
+				      g_get_conv,
+				      g_get_subconv,
+				      &def_mask,
+				      NULL,
+				      RSBAC_ACL_G_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_gid,
+					NULL);
+	if (err) {
+		registration_error(err, "Linux group");
+	}
+	list_info.version = RSBAC_ACL_DEF_G_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_g_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_g_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_G_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default Linux group");
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	lol_info.version = RSBAC_ACL_NETDEV_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_netdev_id_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_NETDEV_MASK;
+	err = rsbac_list_lol_register(RSBAC_LIST_VERSION,
+				      &netdev_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST |
+				      RSBAC_LIST_DEF_DATA, netdev_compare,
+				      entry_compare, netdev_get_conv,
+				      netdev_get_subconv, &def_mask, NULL,
+				      RSBAC_ACL_NETDEV_FILENAME,
+				      RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "netdev");
+	}
+	list_info.version = RSBAC_ACL_DEF_NETDEV_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_netdev_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_netdev_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_NETDEV_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default netdev");
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	lol_info.version = RSBAC_ACL_NETTEMP_NT_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_net_temp_id_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_NETTEMP_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &nettemp_nt_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      entry_compare,
+				      nettemp_nt_get_conv,
+				      nettemp_nt_get_subconv,
+				      &def_mask,
+				      NULL,
+				      RSBAC_ACL_NETTEMP_NT_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_nettemp,
+					NULL);
+	if (err) {
+		registration_error(err, "nettemp_nt");
+	}
+	list_info.version = RSBAC_ACL_DEF_NETTEMP_NT_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_nettemp_nt_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_nettemp_nt_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_NETTEMP_NT_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default nettemp_nt");
+	}
+	lol_info.version = RSBAC_ACL_NETTEMP_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_net_temp_id_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &nettemp_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      entry_compare,
+				      nettemp_get_conv,
+				      nettemp_get_subconv,
+				      &def_mask,
+				      NULL,
+				      RSBAC_ACL_NETTEMP_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_nettemp,
+					NULL);
+	if (err) {
+		registration_error(err, "nettemp");
+	}
+	lol_info.version = RSBAC_ACL_NETOBJ_LIST_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_net_obj_id_t);
+	lol_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* mask */
+	lol_info.subdesc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	lol_info.subdata_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	lol_info.max_age = 0;
+	def_mask = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &netobj_handle,
+				      &lol_info,
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      entry_compare,
+				      netobj_get_conv,
+				      netobj_get_subconv,
+				      &def_mask,
+				      NULL,
+				      RSBAC_ACL_NETOBJ_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_netobj,
+					NULL);
+	if (err) {
+		registration_error(err, "netobj");
+	}
+	list_info.version = RSBAC_ACL_DEF_NETOBJ_LIST_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(struct rsbac_acl_entry_desc_t);	/* subj_type + subj_id */
+	list_info.data_size = sizeof(rsbac_acl_rights_vector_t);	/* rights */
+	list_info.max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  &default_netobj_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST,
+				  entry_compare,
+				  def_netobj_get_conv,
+				  NULL,
+				  RSBAC_ACL_DEF_NETOBJ_FILENAME,
+				  RSBAC_AUTO_DEV);
+	if (err) {
+		registration_error(err, "default netobj");
+	}
+#endif				/* NET_OBJ_PROT */
+
+	/* groups */
+	list_info.version = RSBAC_ACL_GROUP_VERSION;
+	list_info.key = RSBAC_ACL_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_acl_group_id_t);
+	list_info.data_size = sizeof(struct rsbac_acl_group_entry_t);
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &group_handle, &list_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				  NULL,
+				  NULL,
+				  NULL,
+				  RSBAC_ACL_GROUP_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  1,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "group");
+	}
+
+	/* group memberships */
+	lol_info.version = RSBAC_ACL_GM_VERSION;
+	lol_info.key = RSBAC_ACL_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_uid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_acl_group_id_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &gm_handle, &lol_info,
+#if defined(CONFIG_RSBAC_ACL_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST |
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      NULL,
+				      gm_get_conv,
+				      gm_get_subconv,
+				      NULL, NULL, RSBAC_ACL_GM_FILENAME,
+				      RSBAC_AUTO_DEV,
+					1,
+					rsbac_list_hash_uid,
+					NULL);
+	if (err) {
+		registration_error(err, "gm");
+	}
+
+/* Create default lists */
+	if (!rsbac_no_defaults) {
+		acl_create_def();
+		acl_create_def2();
+	}
+#if defined(CONFIG_RSBAC_PROC)
+	acl_devices = proc_create("acl_devices",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p, &acl_devices_proc_fops);
+	stats_acl = proc_create("stats_acl",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p, &stats_acl_proc_fops);
+	acl_acllist = proc_create("acl_acllist",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p, &acl_acllist_proc_fops);
+	acl_grouplist = proc_create("acl_grouplist",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p, &acl_grouplist_proc_fops);
+#endif
+
+	rsbac_pr_debug(ds_acl, "Ready.\n");
+	return err;
+}
+
+int rsbac_mount_acl(kdev_t kdev)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	struct rsbac_acl_device_list_item_t *new_device_p;
+	int srcu_idx;
+
+	rsbac_pr_debug(ds_acl, "mounting device %02u:%02u\n",
+		       RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = acl_lookup_device(kdev);
+	/* repeated mount? */
+	if (device_p) {
+		rsbac_printk(KERN_INFO "rsbac_mount_acl: repeated mount %u of device %02u:%02u\n",
+			     device_p->mount_count, RSBAC_MAJOR(kdev),
+			     RSBAC_MINOR(kdev));
+		device_p->mount_count++;
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return 0;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	/* OK, go on */
+	new_device_p = create_device_item(kdev);
+	if (!new_device_p)
+		return -RSBAC_ECOULDNOTADDDEVICE;
+
+	if ((err = acl_register_fd_lists(new_device_p, kdev))) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_mount_acl(): File/Dir ACL registration failed for dev %02u:%02u, err %s!\n",
+				     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev),
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	/* make sure to only add, if this device item has not been added in the meantime */
+	device_p = acl_lookup_device(kdev);
+	if (device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mount_acl(): mount race for device %02u:%02u detected!\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+		device_p->mount_count++;
+		/* also detaches lists */
+		clear_device_item(new_device_p);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+	} else {
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		device_p = add_device_item(new_device_p);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_mount_acl: adding device %02u:%02u failed!\n",
+				     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+			/* also detaches lists */
+			clear_device_item(new_device_p);
+			err = -RSBAC_ECOULDNOTADDDEVICE;
+		}
+	}
+
+	return err;
+}
+
+/* When umounting a device, its file/dir ACLs must be removed. */
+
+int rsbac_umount_acl(kdev_t kdev)
+{
+	struct rsbac_acl_device_list_item_t *device_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_umount(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(ds_acl, "umounting device %02u:%02u\n",
+		     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+	/* sync of attribute lists was done in rsbac_umount */
+	spin_lock(&device_list_lock);
+	/* OK, nobody else is working on it... */
+	device_p = acl_lookup_device_locked(kdev);
+	if (device_p) {
+		if (device_p->mount_count == 1)
+			remove_device_item(kdev);
+		else {
+			if (device_p->mount_count > 1) {
+				device_p->mount_count--;
+				spin_unlock(&device_list_lock);
+			} else {
+				spin_unlock(&device_list_lock);
+				rsbac_printk(KERN_WARNING "rsbac_umount_acl: device %02u:%02u has mount_count < 1!\n",
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev));
+			}
+		}
+	}
+	else
+		spin_unlock(&device_list_lock);
+	return 0;
+}
+
+/***************************************************/
+/* We also need some status information...         */
+
+int rsbac_stats_acl(void)
+{
+	struct rsbac_acl_device_list_head_t *head_p;
+	struct rsbac_acl_device_list_item_t *device_p;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_stats_acl(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_acl, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	rsbac_printk(KERN_INFO "ACL Status\n-----------\n");
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		rsbac_printk(KERN_INFO "device %02u:%02u has %u file ACLs, sum of %u members\n",
+			     RSBAC_MAJOR(device_p->id),
+			     RSBAC_MINOR(device_p->id),
+			     rsbac_list_lol_count(device_p->handle),
+			     rsbac_list_lol_all_subcount(device_p->handle));
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	/* unprotect device list */
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	/* dev list */
+	rsbac_printk(KERN_INFO "%li device major ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(dev_major_handle),
+		     rsbac_list_lol_all_subcount(dev_major_handle));
+	rsbac_printk(KERN_INFO "%li device ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(dev_handle),
+		     rsbac_list_lol_all_subcount(dev_handle));
+
+	/* SCD list */
+	rsbac_printk(KERN_INFO "%li scd ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(scd_handle),
+		     rsbac_list_lol_all_subcount(scd_handle));
+
+	/* user list */
+	rsbac_printk(KERN_INFO "%li user ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(u_handle),
+		     rsbac_list_lol_all_subcount(u_handle));
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	/* Linux group list */
+	rsbac_printk(KERN_INFO "%li Linux group ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(g_handle),
+		     rsbac_list_lol_all_subcount(g_handle));
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	/* netdev list */
+	rsbac_printk(KERN_INFO "%li network device ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(netdev_handle),
+		     rsbac_list_lol_all_subcount(netdev_handle));
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	/* nettemp_nt list */
+	rsbac_printk(KERN_INFO "%li network template NT ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(nettemp_nt_handle),
+		     rsbac_list_lol_all_subcount(nettemp_nt_handle));
+	/* nettemp list */
+	rsbac_printk(KERN_INFO "%li network template ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(nettemp_handle),
+		     rsbac_list_lol_all_subcount(nettemp_handle));
+	/* netobj list */
+	rsbac_printk(KERN_INFO "%li network object ACL items, sum of %li members\n",
+		     rsbac_list_lol_count(netobj_handle),
+		     rsbac_list_lol_all_subcount(netobj_handle));
+#endif
+
+	rsbac_printk(KERN_INFO "%li groups, last new is %u\n",
+		     rsbac_list_count(group_handle), group_last_new);
+
+	/* protect gm list */
+	rsbac_printk(KERN_INFO "%li group member items, sum of %li group memberships\n",
+		     rsbac_list_lol_count(gm_handle),
+		     rsbac_list_lol_all_subcount(gm_handle));
+
+	return 0;
+}
+
+/***************************************************/
+/* consistency checking (as far as possible)       */
+
+int rsbac_check_acl(int correct)
+{
+	struct rsbac_acl_device_list_head_t *head_p;
+	struct rsbac_acl_device_list_item_t *device_p;
+	u_long f_count = 0, f_sum = 0, tmp_count,
+	    r_count, u_count, b_count, no_member_count;
+	long desc_count;
+	long sub_desc_count;
+	rsbac_old_inode_nr_t *fd_desc_p;
+	struct rsbac_dev_desc_t *dev_desc_p;
+	__u8 *scd_desc_p;
+	rsbac_uid_t *u_desc_p;
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	rsbac_gid_t *g_desc_p;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	rsbac_netdev_id_t *netdev_desc_p;
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	rsbac_net_temp_id_t *nettemp_desc_p;
+	rsbac_net_obj_id_t *netobj_desc_p;
+#endif
+	struct rsbac_acl_entry_desc_t *sub_desc_p;
+	rsbac_uid_t *user_p;
+	rsbac_acl_group_id_t *group_p;
+	u_int i, j;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_check_acl(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+
+	/* group membership list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(gm_handle, (void **) &user_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(gm_handle,
+							   &user_p[i],
+							   (void **)
+							   &group_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if (!rsbac_list_exist
+					    (group_handle, &group_p[j])) {
+						rsbac_printk(KERN_WARNING "rsbac_check_acl(): removing user %u membership in non-existent group %u!\n",
+							     user_p[i],
+							     group_p[j]);
+						rsbac_list_lol_subremove
+						    (gm_handle, &user_p[i],
+						     &group_p[j]);
+					}
+				}
+				rsbac_kfree(group_p);
+			} else {
+				/* remove empty membership list */
+				if (!sub_desc_count)
+					rsbac_list_lol_remove(gm_handle,
+							      &user_p[i]);
+			}
+		}
+		rsbac_kfree(user_p);
+	}
+	/* recalculated values! */
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li group membership items\n",
+		     rsbac_list_lol_count(gm_handle));
+
+	/* group list */
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li group items\n",
+		     rsbac_list_count(group_handle));
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {	/* for all sublists */
+		f_count = 0;
+		r_count = 0;
+		u_count = 0;
+		b_count = 0;
+		no_member_count = 0;
+
+		tmp_count = 0;
+		desc_count = rsbac_list_lol_get_all_desc(device_p->handle,
+							(void **)
+							&fd_desc_p);
+		if (desc_count > 0) {
+			for (i = 0; i < desc_count; i++) {
+				/* check for group existence of all ACL entries for groups */
+				sub_desc_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->handle,
+				     &fd_desc_p[i],
+				     (void **) &sub_desc_p);
+				if (sub_desc_count > 0) {
+					for (j = 0;
+					     j < sub_desc_count;
+					     j++) {
+						if ((sub_desc_p[j].
+						     subj_type ==
+						     ACLS_GROUP)
+						    &&
+						    sub_desc_p[j].
+						    subj_id
+						    &&
+						    !rsbac_list_exist
+						    (group_handle,
+						     &sub_desc_p
+						     [j].
+						     subj_id)) {
+							if (correct) {
+								/* remove sub item and complain */
+								rsbac_pr_debug(ds, "fd_item for inode %u on device %02u:%02u has invalid group %u in ACL -> removing entry!\n",
+									       fd_desc_p[i],
+									       RSBAC_MAJOR(device_p->id),
+									       RSBAC_MINOR(device_p->id),
+									       sub_desc_p[j].subj_id);
+								rsbac_list_lol_subremove
+								    (device_p->handle,
+								     &fd_desc_p
+								     [i],
+								     &sub_desc_p
+								     [j]);
+							} else /* complain */
+								rsbac_pr_debug(ds, "fd_item for inode %u on device %02u:%02u has invalid group %u in ACL!\n",
+									       fd_desc_p[i],
+									       RSBAC_MAJOR(device_p->id),
+									       RSBAC_MINOR(device_p->id),
+									       sub_desc_p[j].subj_id);
+						}
+#if defined(CONFIG_RSBAC_RC)
+						else if ((sub_desc_p[j].subj_type == ACLS_ROLE)
+							 &&
+							 (sub_desc_p
+							  [j].
+							  subj_id >
+							  RC_role_max_value)
+						    ) {
+							if (correct) {
+								/* remove sub item and complain */
+								rsbac_pr_debug(ds, "fd_item for inode %u on device %02u:%02u has invalid RC role %u in ACL -> removing entry!\n",
+									       fd_desc_p[i],
+									       RSBAC_MAJOR(device_p->id),
+									       RSBAC_MINOR(device_p->id),
+									       sub_desc_p[j].subj_id);
+								rsbac_list_lol_subremove
+								    (device_p->handle,
+								     &fd_desc_p
+								     [i],
+								     &sub_desc_p
+								     [j]);
+							} else /* complain */
+								rsbac_pr_debug(ds, "fd_item for inode %u on device %02u:%02u has invalid role %u in ACL!\n",
+									       fd_desc_p[i],
+									       RSBAC_MAJOR(device_p->id),
+									       RSBAC_MINOR(device_p->id),
+									       sub_desc_p[j].subj_id);
+						}
+#endif
+					}
+					rsbac_kfree(sub_desc_p);
+				}
+			}
+			tmp_count++;
+			rsbac_kfree(fd_desc_p);
+			f_count += desc_count;
+		}
+
+		switch (correct) {
+		case 2:
+			rsbac_printk(KERN_INFO "rsbac_check_acl(): Device %02u:%02u has %lu file/dir ACLs (%lu removed (%lu bad inodes, %lu dtimed inodes, %lu unlinked inodes, %lu had no members and default mask))\n",
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id), f_count,
+				     b_count + r_count + u_count +
+				     no_member_count, b_count, r_count,
+				     u_count, no_member_count);
+			break;
+		case 1:
+			rsbac_printk(KERN_INFO "rsbac_check_acl(): Device %02u:%02u has %lu file/dir ACLs (%lu removed (%lu bad inodes, %lu dtimed inodes, %lu had no members and default mask), %lu unlinked inodes)\n",
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id), f_count,
+				     b_count + r_count + no_member_count,
+				     b_count, r_count, no_member_count,
+				     u_count);
+			break;
+		default:
+			rsbac_printk(KERN_INFO "rsbac_check_acl(): Device %02u:%02u has %lu file/dir ACLs (%lu with bad inodes, %lu with dtimed inodes, %lu unlinked inodes, %lu without members and with default mask)\n",
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id), f_count,
+				     b_count, r_count, u_count,
+				     no_member_count);
+		}
+		f_sum += f_count;
+		/* go on */
+		device_p = device_p->next;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): Sum of %u Devices with %lu file/dir ACLs\n",
+		     device_list_head_p->count, f_sum);
+	/* free access to device_list_head */
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	/* dev list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(dev_handle, (void **) &dev_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(dev_handle,
+							   &dev_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid group %u in ACL -> removing entry!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (dev_handle,
+							     &dev_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid group %u in ACL!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid role %u in ACL -> removing entry!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (dev_handle,
+							     &dev_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid role %u in ACL!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(dev_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li device items\n",
+		     desc_count);
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(dev_major_handle,
+					(void **) &dev_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (dev_major_handle, &dev_desc_p[i],
+			     (void **) &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid group %u in ACL -> removing entry!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (dev_major_handle,
+							     &dev_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid group %u in ACL!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid role %u in ACL -> removing entry!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (dev_major_handle,
+							     &dev_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "dev_item %c%02u:%02u, has invalid role %u in ACL!\n",
+								       'B' + dev_desc_p[i].type,
+								       dev_desc_p[i].major,
+								       dev_desc_p[i].minor,
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(dev_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li device items\n",
+		     desc_count);
+
+	/* SCD list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(scd_handle, (void **) &scd_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(scd_handle,
+							   &scd_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "scd_item %u has invalid group %u in ACL -> removing entry!\n",
+								       scd_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (scd_handle,
+							     &scd_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "scd_item %u has invalid group %u in ACL!\n",
+								       scd_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "scd_item %u has invalid role %u in ACL -> removing entry!\n",
+								       scd_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (scd_handle,
+							     &scd_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "scd_item %u has invalid role %u in ACL!\n",
+								       scd_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(scd_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li SCD items\n",
+		     desc_count);
+
+	/* User list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(u_handle, (void **) &u_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(u_handle,
+							   &u_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "u_item %u has invalid group %u in ACL -> removing entry!\n",
+								       u_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (u_handle,
+							     &u_desc_p[i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "u_item %u has invalid group %u in ACL!\n",
+								       u_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "u_item %u has invalid role %u in ACL -> removing entry!\n",
+								       u_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (u_handle,
+							     &u_desc_p[i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "u_item %u has invalid role %u in ACL!\n",
+								       u_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(u_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li user items\n",
+		     desc_count);
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	/* User list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(g_handle, (void **) &g_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(g_handle,
+							   &g_desc_p[i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "g_item %u has invalid group %u in ACL -> removing entry!\n",
+								       g_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (g_handle,
+							     &g_desc_p[i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "g_item %u has invalid group %u in ACL!\n",
+								       g_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "g_item %u has invalid role %u in ACL -> removing entry!\n",
+								       g_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (g_handle,
+							     &g_desc_p[i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "g_item %u has invalid role %u in ACL!\n",
+								       g_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(g_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li Linux group items\n",
+		     desc_count);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	/* netdev list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(netdev_handle,
+					(void **) &netdev_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(netdev_handle,
+							   &netdev_desc_p
+							   [i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "netdev_item %s has invalid group %u in ACL -> removing entry!\n",
+								       netdev_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (netdev_handle,
+							     &netdev_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "netdev_item %s has invalid group %u in ACL!\n",
+								       netdev_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "netdev_item %s has invalid role %u in ACL -> removing entry!\n",
+								       netdev_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (netdev_handle,
+							     &netdev_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "netdev_item %s has invalid role %u in ACL!\n",
+								       netdev_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(netdev_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li network device items\n",
+		     desc_count);
+#endif				/* NET_DEV_PROT */
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	/* nettemp_nt list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(nettemp_nt_handle,
+					(void **) &nettemp_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (nettemp_nt_handle, &nettemp_desc_p[i],
+			     (void **) &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "nettemp_nt_item %u has invalid group %u in ACL -> removing entry!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (nettemp_nt_handle,
+							     &nettemp_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "nettemp_nt_item %u has invalid group %u in ACL!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "nettemp_nt_item %u has invalid role %u in ACL -> removing entry!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (nettemp_nt_handle,
+							     &nettemp_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "nettemp_nt_item %u has invalid role %u in ACL!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(nettemp_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li network template NT items\n",
+		     desc_count);
+
+	/* nettemp list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(nettemp_handle,
+					(void **) &nettemp_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(nettemp_handle,
+							   &nettemp_desc_p
+							   [i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "nettemp_item %u has invalid group %u in ACL -> removing entry!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (nettemp_handle,
+							     &nettemp_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "nettemp_item %u has invalid group %u in ACL!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "nettemp_item %u has invalid role %u in ACL -> removing entry!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (nettemp_handle,
+							     &nettemp_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "nettemp_item %u has invalid role %u in ACL!\n",
+								       nettemp_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(nettemp_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li network template items\n",
+		     desc_count);
+
+	/* netobj list */
+	tmp_count = 0;
+	desc_count =
+	    rsbac_list_lol_get_all_desc(netobj_handle,
+					(void **) &netobj_desc_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			/* check for group existence of all ACL entries for groups */
+			sub_desc_count =
+			    rsbac_list_lol_get_all_subdesc(netobj_handle,
+							   &netobj_desc_p
+							   [i],
+							   (void **)
+							   &sub_desc_p);
+			if (sub_desc_count > 0) {
+				for (j = 0; j < sub_desc_count; j++) {
+					if ((sub_desc_p[j].subj_type ==
+					     ACLS_GROUP)
+					    && sub_desc_p[j].subj_id
+					    &&
+					    !rsbac_list_exist(group_handle,
+							      &sub_desc_p
+							      [j].
+							      subj_id)) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "netobj_item %p has invalid group %u in ACL -> removing entry!\n",
+								       netobj_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (netobj_handle,
+							     &netobj_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "netobj_item %p has invalid group %u in ACL!\n",
+								       netobj_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#if defined(CONFIG_RSBAC_RC)
+					else if ((sub_desc_p[j].
+						  subj_type == ACLS_ROLE)
+						 && (sub_desc_p[j].
+						     subj_id >
+						     RC_role_max_value)
+					    ) {
+						if (correct) {
+							/* remove sub item and complain */
+							rsbac_pr_debug(ds, "netobj_item %p has invalid role %u in ACL -> removing entry!\n",
+								       netobj_desc_p[i],
+								       sub_desc_p[j].subj_id);
+							rsbac_list_lol_subremove
+							    (netobj_handle,
+							     &netobj_desc_p
+							     [i],
+							     &sub_desc_p
+							     [j]);
+						} else /* complain */
+							rsbac_pr_debug(ds, "netobj_item %p has invalid role %u in ACL!\n",
+								       netobj_desc_p[i],
+								       sub_desc_p[j].subj_id);
+					}
+#endif
+				}
+				rsbac_kfree(sub_desc_p);
+			}
+		}
+		rsbac_kfree(netobj_desc_p);
+		f_sum += desc_count;
+	}
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): %li network object items\n",
+		     desc_count);
+#endif				/* NET_OBJ_PROT */
+
+	rsbac_printk(KERN_INFO "rsbac_check_acl(): Total of %lu registered ACLs\n",
+		     f_sum);
+
+	return 0;
+}
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the spinlocks to protect the targets during */
+/* access.                                                                 */
+
+/* rsbac_acl_set_acl_entry
+ * Set ACL entry for given target and subject to given rights. If entry does
+ * not exist, it is created, thus cutting the inheritance from default/parent.
+ */
+
+int rsbac_acl_set_acl_entry(rsbac_list_ta_number_t ta_number,
+			    enum rsbac_target_t target,
+			    union rsbac_target_id_t tid,
+			    enum rsbac_acl_subject_type_t subj_type,
+			    rsbac_acl_subject_id_t subj_id,
+			    rsbac_acl_rights_vector_t rights,
+			    rsbac_time_t ttl)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	struct rsbac_acl_entry_desc_t desc;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_set_acl_entry(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (subj_type >= ACLS_NONE)
+		return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_set_acl_entry(): called from interrupt!\n");
+	}
+#endif
+	desc.subj_type = subj_type;
+	desc.subj_id = subj_id;
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		rsbac_pr_debug(ds_acl, "Setting file/dir/fifo/symlink ACL for device %02u:%02u, inode %lu\n",
+			       RSBAC_MAJOR(tid.file.device),
+			       RSBAC_MINOR(tid.file.device), tid.file.inode);
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_fd_handle,
+						     ttl, &desc, &rights);
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_set_acl_entry(): Could not lookup device!\n");
+			/* free read lock */
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, device_p->handle,
+		     &inode_nr)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_FD_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							device_p->handle,
+							0, &inode_nr,
+							&mask);
+			if (err) {
+				srcu_read_unlock(&device_list_srcu, srcu_idx);
+				return err;
+			}
+		}
+		err =
+		    rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->handle, ttl,
+						 &inode_nr, &desc,
+						 &rights);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		/* ready. */
+		return err;
+
+	case T_DEV:
+		rsbac_pr_debug(ds_acl, "Setting device ACL for dev %c %02u:%02u\n",
+			       'B' + tid.dev.type, tid.dev.major,
+			       tid.dev.minor);
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev))
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_dev_handle,
+						     ttl, &desc, &rights);
+
+		{
+			switch (tid.dev.type) {
+			case D_char:
+			case D_block:
+				if (!rsbac_ta_list_lol_exist
+				    (ta_number, dev_handle, &tid.dev)) {
+					rsbac_acl_rights_vector_t mask =
+					    RSBAC_ACL_DEFAULT_DEV_MASK;
+
+					err =
+					    rsbac_ta_list_lol_add_ttl
+					    (ta_number, dev_handle, 0,
+					     &tid.dev, &mask);
+					if (err)
+						return err;
+				}
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 dev_handle,
+								 ttl,
+								 &tid.dev,
+								 &desc,
+								 &rights);
+
+			case D_char_major:
+			case D_block_major:
+				tid.dev.type -= (D_block_major - D_block);
+				if (!rsbac_ta_list_lol_exist
+				    (ta_number, dev_major_handle,
+				     &tid.dev)) {
+					rsbac_acl_rights_vector_t mask =
+					    RSBAC_ACL_DEFAULT_DEV_MASK;
+
+					err =
+					    rsbac_ta_list_lol_add_ttl
+					    (ta_number, dev_major_handle,
+					     0, &tid.dev, &mask);
+					if (err)
+						return err;
+				}
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 dev_major_handle,
+								 ttl,
+								 &tid.dev,
+								 &desc,
+								 &rights);
+
+			default:
+				return -RSBAC_EINVALIDTARGET;
+			}
+		}
+
+	case T_IPC:
+		/* default entry? */
+		if (tid.ipc.type == I_none)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_ipc_handle,
+						     ttl, &desc, &rights);
+		else
+			return -RSBAC_EINVALIDTARGET;
+
+	case T_SCD:
+		/* default entry? */
+		if (tid.scd == AST_none)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_scd_handle,
+						     ttl, &desc, &rights);
+
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, scd_handle, &tid.scd)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_SCD_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							scd_handle,
+							0,
+							&tid.scd, &mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number, scd_handle,
+						    ttl, &tid.scd, &desc,
+						    &rights);
+
+	case T_USER:
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_u_handle, ttl,
+						     &desc, &rights);
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, u_handle, &tid.user)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_U_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							u_handle,
+							0,
+							&tid.user, &mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number, u_handle,
+						    ttl, &tid.user, &desc,
+						    &rights);
+
+
+	case T_PROCESS:
+		/* default entry? */
+		if (!tid.process)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_p_handle, ttl,
+						     &desc, &rights);
+		else
+			return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_g_handle, ttl,
+						     &desc, &rights);
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, g_handle, &tid.group)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_G_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							g_handle,
+							0,
+							&tid.group, &mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number, g_handle,
+						    ttl, &tid.group, &desc,
+						    &rights);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		rsbac_pr_debug(ds_acl, "Setting network device ACL for netdev %s\n",
+			       tid.netdev);
+		/* default entry? */
+		if (!tid.netdev[0])
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_netdev_handle,
+						     ttl, &desc, &rights);
+
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, netdev_handle, &tid.netdev)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETDEV_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							netdev_handle,
+							0,
+							&tid.netdev,
+							&mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    netdev_handle, ttl,
+						    &tid.netdev, &desc,
+						    &rights);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		rsbac_pr_debug(ds_acl, "Setting network template NT ACL for "
+			       "nettemp_nt %u\n", tid.nettemp);
+		/* default entry? */
+		if (!tid.nettemp)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_nettemp_nt_handle,
+						     ttl, &desc, &rights);
+
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, nettemp_nt_handle, &tid.nettemp)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETTEMP_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							nettemp_nt_handle,
+							0,
+							&tid.nettemp,
+							&mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    nettemp_nt_handle, ttl,
+						    &tid.nettemp, &desc,
+						    &rights);
+
+	case T_NETTEMP:
+		rsbac_pr_debug(ds_acl, "Setting network template ACL for nettemp %u\n",
+			       tid.nettemp);
+		/* default entry? */
+		if (!tid.nettemp)
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, nettemp_handle, &tid.nettemp)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							nettemp_handle,
+							0,
+							&tid.nettemp,
+							&mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    nettemp_handle, ttl,
+						    &tid.nettemp, &desc,
+						    &rights);
+
+	case T_NETOBJ:
+		rsbac_pr_debug(ds_acl, "Setting network object ACL for netobj %p\n",
+			       tid.netobj.sock_p);
+		/* default entry? */
+		if (!tid.netobj.sock_p)
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_netobj_handle,
+						     ttl, &desc, &rights);
+
+		if (!rsbac_ta_list_lol_exist
+		    (ta_number, netobj_handle, &tid.netobj.sock_p)) {
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+
+			err = rsbac_ta_list_lol_add_ttl(ta_number,
+							netobj_handle,
+							0,
+							&tid.netobj.sock_p,
+							&mask);
+			if (err)
+				return err;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    netobj_handle, ttl,
+						    &tid.netobj.sock_p,
+						    &desc, &rights);
+#endif				/* NET_OBJ_PROT */
+
+
+	default:
+		err = -RSBAC_EINVALIDTARGET;
+	}
+	return err;
+}
+
+/* rsbac_acl_remove_acl_entry
+ * Remove ACL entry for given target and subject. This reactivates the
+ * inheritance from default/parent.
+ */
+
+int rsbac_acl_remove_acl_entry(rsbac_list_ta_number_t ta_number,
+			       enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_acl_subject_type_t subj_type,
+			       rsbac_acl_subject_id_t subj_id)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	struct rsbac_acl_entry_desc_t desc;
+#ifdef CONFIG_RSBAC_DEBUG
+	char tmp[RSBAC_MAXNAMELEN];
+#endif
+	rsbac_acl_rights_vector_t mask;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_remove_acl_entry(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (subj_type >= ACLS_NONE)
+		return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_remove_acl_entry(): called from interrupt!\n");
+	}
+#endif
+	desc.subj_type = subj_type;
+	desc.subj_id = subj_id;
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		rsbac_pr_debug(ds_acl, "Removing file/dir/fifo/symlink ACL entry %s %u for device %02u:%02u, inode %lu\n",
+			       get_acl_subject_type_name(tmp, desc.subj_type),
+			       desc.subj_id,
+			       RSBAC_MAJOR(tid.file.device),
+			       RSBAC_MINOR(tid.file.device), tid.file.inode);
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p)
+			return rsbac_ta_list_remove(ta_number,
+						    default_fd_handle,
+						    &desc);
+
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_remove_acl_entry(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->handle,
+						&inode_nr, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number,
+						   device_p->handle,
+						   &inode_nr)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number,
+						       device_p->handle,
+						       NULL,
+						       &inode_nr,
+						       &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_FD_MASK)
+		    ) {
+			err = rsbac_ta_list_lol_remove(ta_number,
+						     device_p->handle,
+						     &inode_nr);
+		}
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return err;
+
+	case T_DEV:
+		rsbac_pr_debug(ds_acl, "Removing device ACL entry for dev %c %02u:%02u\n",
+			       'B' + tid.dev.type, tid.dev.major,
+			       tid.dev.minor);
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev))
+			return rsbac_ta_list_remove(ta_number,
+						    default_dev_handle,
+						    &desc);
+
+		{
+			switch (tid.dev.type) {
+			case D_char:
+			case D_block:
+				err =
+				    rsbac_ta_list_lol_subremove(ta_number,
+								dev_handle,
+								&tid.dev,
+								&desc);
+				/* if ACL is empty, remove it */
+				if (!err
+				    &&
+				    !rsbac_ta_list_lol_subcount(ta_number,
+								dev_handle,
+								&tid.dev)
+				    &&
+				    !rsbac_ta_list_lol_get_data_ttl
+				    (ta_number, dev_handle, NULL, &tid.dev,
+				     &mask)
+				    && (mask == RSBAC_ACL_DEFAULT_DEV_MASK)
+				    ) {
+					err =
+					    rsbac_ta_list_lol_remove
+					    (ta_number, dev_handle,
+					     &tid.dev);
+				}
+				return err;
+
+			case D_char_major:
+			case D_block_major:
+				tid.dev.type -= (D_block_major - D_block);
+				err =
+				    rsbac_ta_list_lol_subremove(ta_number,
+								dev_major_handle,
+								&tid.dev,
+								&desc);
+				/* if ACL is empty, remove it */
+				if (!err
+				    &&
+				    !rsbac_ta_list_lol_subcount(ta_number,
+								dev_major_handle,
+								&tid.dev)
+				    &&
+				    !rsbac_ta_list_lol_get_data_ttl
+				    (ta_number, dev_major_handle, NULL,
+				     &tid.dev, &mask)
+				    && (mask == RSBAC_ACL_DEFAULT_DEV_MASK)
+				    ) {
+					err =
+					    rsbac_ta_list_lol_remove
+					    (ta_number, dev_major_handle,
+					     &tid.dev);
+				}
+				return err;
+
+			default:
+				return -RSBAC_EINVALIDTARGET;
+			}
+		}
+
+	case T_IPC:
+		rsbac_pr_debug(ds_acl, "Removing IPC ACL for type %u\n", tid.ipc.type);
+		/* default entry? */
+		if (tid.ipc.type == I_none)
+			return rsbac_ta_list_remove(ta_number,
+						    default_ipc_handle,
+						    &desc);
+		else
+			return -RSBAC_EINVALIDTARGET;
+
+	case T_SCD:
+		rsbac_pr_debug(ds_acl, "Removing SCD ACL entry for %s\n",
+			       get_acl_scd_type_name(tmp, tid.scd));
+		/* default entry? */
+		if (tid.scd == AST_none)
+			return rsbac_ta_list_remove(ta_number,
+						    default_scd_handle,
+						    &desc);
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number, scd_handle,
+						&tid.scd, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number, scd_handle,
+						   &tid.scd)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number,
+						       scd_handle, NULL,
+						       &tid.scd, &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_SCD_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number, scd_handle,
+						     &tid.scd);
+		}
+		return err;
+
+	case T_USER:
+		rsbac_pr_debug(ds_acl, "Removing user ACL for user %u\n",
+			       tid.user);
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER)
+			return rsbac_ta_list_remove(ta_number,
+						    default_u_handle,
+						    &desc);
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number, u_handle,
+						&tid.user, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number, u_handle,
+						   &tid.user)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number, u_handle,
+						       NULL, &tid.user,
+						       &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_U_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number, u_handle,
+						     &tid.user);
+		}
+		return err;
+
+	case T_PROCESS:
+		rsbac_pr_debug(ds_acl, "Removing process ACL for pid %u\n",
+			       tid.process);
+		/* default entry? */
+		if (!tid.process)
+			return rsbac_ta_list_remove(ta_number,
+						    default_p_handle,
+						    &desc);
+		else
+			return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		rsbac_pr_debug(ds_acl, "Removing Linux group ACL for group %u\n",
+			       tid.group);
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP)
+			return rsbac_ta_list_remove(ta_number,
+						    default_g_handle,
+						    &desc);
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number, g_handle,
+						&tid.group, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number, g_handle,
+						   &tid.group)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number, g_handle,
+						       NULL, &tid.group,
+						       &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_G_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number, g_handle,
+						     &tid.group);
+		}
+		return err;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		rsbac_pr_debug(ds_acl, "Removing network device ACL entry for netdev %s\n",
+			       tid.netdev);
+		/* default entry? */
+		if (!tid.netdev[0])
+			return rsbac_ta_list_remove(ta_number,
+						    default_netdev_handle,
+						    &desc);
+
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number, netdev_handle,
+						&tid.netdev, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number,
+						   netdev_handle,
+						   &tid.netdev)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number,
+						       netdev_handle, NULL,
+						       &tid.netdev, &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_NETDEV_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number,
+						     netdev_handle,
+						     &tid.netdev);
+		}
+		return err;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		rsbac_pr_debug(ds_acl, "Removing network template NT ACL entry for "
+			       "nettemp_nt %u\n", tid.nettemp);
+		/* default entry? */
+		if (!tid.nettemp)
+			return rsbac_ta_list_remove(ta_number,
+						    default_nettemp_nt_handle,
+						    &desc);
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number,
+						nettemp_nt_handle,
+						&tid.nettemp, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number,
+						   nettemp_nt_handle,
+						   &tid.nettemp)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number,
+						       nettemp_nt_handle,
+						       NULL, &tid.nettemp,
+						       &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_NETTEMP_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number,
+						     nettemp_nt_handle,
+						     &tid.nettemp);
+		}
+		return err;
+
+	case T_NETTEMP:
+		rsbac_pr_debug(ds_acl, "Removing network template ACL entry for nettemp_nt %u\n",
+			       tid.nettemp);
+		/* default entry? */
+		if (!tid.nettemp)
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number, nettemp_handle,
+						&tid.nettemp, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number,
+						   nettemp_handle,
+						   &tid.nettemp)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number,
+						       nettemp_handle,
+						       NULL, &tid.nettemp,
+						       &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_NETOBJ_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number,
+						     nettemp_handle,
+						     &tid.nettemp);
+		}
+		return err;
+
+	case T_NETOBJ:
+		rsbac_pr_debug(ds_acl, "Removing network object ACL entry for netobj %p\n",
+			       tid.netobj.sock_p);
+		/* default entry? */
+		if (!tid.netobj.sock_p)
+			return rsbac_ta_list_remove(ta_number,
+						    default_netobj_handle,
+						    &desc);
+
+		err =
+		    rsbac_ta_list_lol_subremove(ta_number, netobj_handle,
+						&tid.netobj.sock_p, &desc);
+		/* if ACL is empty, remove it */
+		if (!err
+		    && !rsbac_ta_list_lol_subcount(ta_number,
+						   netobj_handle,
+						   &tid.netobj.sock_p)
+		    && !rsbac_ta_list_lol_get_data_ttl(ta_number,
+						       netobj_handle, NULL,
+						       &tid.netobj, &mask)
+		    && (mask == RSBAC_ACL_DEFAULT_NETOBJ_MASK)
+		    ) {
+			err =
+			    rsbac_ta_list_lol_remove(ta_number,
+						     netobj_handle,
+						     &tid.netobj.sock_p);
+		}
+		return err;
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+/* rsbac_acl_remove_acl
+ * Remove ACL for given target. For cleanup on delete.
+ */
+
+int rsbac_acl_remove_acl(rsbac_list_ta_number_t ta_number,
+			 enum rsbac_target_t target,
+			 union rsbac_target_id_t tid)
+{
+	int err = 0;
+#ifdef CONFIG_RSBAC_DEBUG
+	char tmp[RSBAC_MAXNAMELEN];
+#endif
+	struct rsbac_acl_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_remove_acl(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_remove_acl(): called from interrupt!\n");
+	}
+#endif
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		rsbac_pr_debug(ds_acl, "Removing file/dir/fifo/symlink ACL for device %02u:%02u, inode %lu\n",
+			       RSBAC_MAJOR(tid.file.device),
+			       RSBAC_MINOR(tid.file.device), tid.file.inode);
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p)
+			return -RSBAC_EINVALIDTARGET;
+
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_remove_acl(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		err = rsbac_ta_list_lol_remove(ta_number,
+					     device_p->handle,
+					     &inode_nr);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return err;
+
+	case T_DEV:
+		rsbac_pr_debug(ds_acl, "Removing device ACL for dev %c %02u:%02u\n",
+			       'B' + tid.dev.type, tid.dev.major,
+			       tid.dev.minor);
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev))
+			return -RSBAC_EINVALIDTARGET;
+		switch (tid.dev.type) {
+		case D_char:
+		case D_block:
+			return rsbac_ta_list_lol_remove(ta_number,
+							dev_handle,
+							&tid.dev);
+
+		case D_char_major:
+		case D_block_major:
+			tid.dev.type -= (D_block_major - D_block);
+			return rsbac_ta_list_lol_remove(ta_number,
+							dev_major_handle,
+							&tid.dev);
+
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case T_SCD:
+		rsbac_pr_debug(ds_acl, "Removing SCD ACL for %s\n",
+			       get_acl_scd_type_name(tmp, tid.scd));
+		/* default entry? */
+		if (tid.scd == AST_none)
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							scd_handle,
+							&tid.scd);
+
+	case T_USER:
+		rsbac_pr_debug(ds_acl, "Removing user ACL for user %u\n",
+			       tid.user);
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER)
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							u_handle,
+							&tid.user);
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		rsbac_pr_debug(ds_acl, "Removing Linux group ACL for group %u\n",
+			       tid.group);
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP)
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							g_handle,
+							&tid.group);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		rsbac_pr_debug(ds_acl, "Removing network device ACL for netdev %s\n",
+			       tid.netdev);
+		/* default entry? */
+		if (!tid.netdev[0])
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							netdev_handle,
+							&tid.netdev);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		rsbac_pr_debug(ds_acl, "Removing network template NT ACL for nettemp_nt %u\n",
+			       tid.nettemp);
+		/* default entry? */
+		if (!tid.nettemp)
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							nettemp_nt_handle,
+							&tid.nettemp);
+	case T_NETTEMP:
+		rsbac_pr_debug(ds_acl, "Removing network template ACL for nettemp %u\n",
+			       tid.nettemp);
+		/* default entry? */
+		if (!tid.nettemp)
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							nettemp_handle,
+							&tid.nettemp);
+	case T_NETOBJ:
+		rsbac_pr_debug(ds_acl, "Removing network object ACL for netobj %p\n",
+			       tid.netobj.sock_p);
+		/* default entry? */
+		if (!tid.netobj.sock_p)
+			return -RSBAC_EINVALIDTARGET;
+		else
+			return rsbac_ta_list_lol_remove(ta_number,
+							netobj_handle,
+							&tid.netobj.
+							sock_p);
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDTARGET;
+	}
+	return err;
+}
+
+/* rsbac_acl_add_to_acl_entry
+ * Add given rights to ACL entry for given target and subject. If entry does
+ * not exist, behaviour is exactly like rsbac_acl_set_acl_entry.
+ */
+
+int rsbac_acl_add_to_acl_entry(rsbac_list_ta_number_t ta_number,
+			       enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_acl_subject_type_t subj_type,
+			       rsbac_acl_subject_id_t subj_id,
+			       rsbac_acl_rights_vector_t rights,
+			       rsbac_time_t ttl)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	rsbac_acl_rights_vector_t old_rights;
+	struct rsbac_acl_entry_desc_t desc;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_add_to_acl_entry(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (subj_type >= ACLS_NONE)
+		return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_add_to_acl_entry(): called from interrupt!\n");
+	}
+#endif
+	desc.subj_type = subj_type;
+	desc.subj_id = subj_id;
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_fd_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_fd_handle,
+						     ttl, &desc, &rights);
+		}
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_set_acl_entry(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		/* protect this list */
+		if (!rsbac_ta_list_lol_exist(ta_number, device_p->handle, &inode_nr)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_FD_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number,
+						      device_p->handle, 0,
+						      &inode_nr,
+						      &mask);
+			if (err) {
+				srcu_read_unlock(&device_list_srcu, srcu_idx);
+				return err;
+			}
+		} else {	/* old entry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       device_p->handle,
+							       NULL,
+							       &inode_nr,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						   device_p->handle, ttl,
+						   &inode_nr, &desc,
+						   &rights);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return err;
+
+	case T_DEV:
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev)) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_dev_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_dev_handle,
+						     ttl, &desc, &rights);
+		}
+		switch (tid.dev.type) {
+		case D_char:
+		case D_block:
+			if (!rsbac_ta_list_lol_exist(ta_number, dev_handle, &tid.dev)) {	/* new acl */
+				rsbac_acl_rights_vector_t mask =
+				    RSBAC_ACL_DEFAULT_DEV_MASK;
+
+				err =
+				    rsbac_ta_list_lol_add_ttl(ta_number,
+							      dev_handle,
+							      0, &tid.dev,
+							      &mask);
+				if (err)
+					return err;
+			} else {	/* old entry? */
+				if (!rsbac_ta_list_lol_get_subdata_ttl
+				    (ta_number, dev_handle, NULL, &tid.dev,
+				     &desc, &old_rights))
+					rights |= old_rights;
+			}
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    dev_handle,
+							    ttl, &tid.dev,
+							    &desc,
+							    &rights);
+
+		case D_char_major:
+		case D_block_major:
+			tid.dev.type -= (D_block_major - D_block);
+			if (!rsbac_ta_list_lol_exist(ta_number, dev_major_handle, &tid.dev)) {	/* new acl */
+				rsbac_acl_rights_vector_t mask =
+				    RSBAC_ACL_DEFAULT_DEV_MASK;
+
+				err =
+				    rsbac_ta_list_lol_add_ttl(ta_number,
+							      dev_major_handle,
+							      0, &tid.dev,
+							      &mask);
+				if (err)
+					return err;
+			} else {	/* old entry? */
+				if (!rsbac_ta_list_lol_get_subdata_ttl
+				    (ta_number, dev_major_handle, NULL,
+				     &tid.dev, &desc, &old_rights))
+					rights |= old_rights;
+			}
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    dev_major_handle,
+							    ttl, &tid.dev,
+							    &desc,
+							    &rights);
+
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case T_IPC:
+		/* default entry? */
+		if (tid.ipc.type == I_none) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_ipc_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_ipc_handle,
+						     ttl, &desc, &rights);
+		} else
+			return -RSBAC_EINVALIDTARGET;
+
+	case T_SCD:
+		/* default entry? */
+		if (tid.scd == AST_none) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_scd_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_scd_handle,
+						     ttl, &desc, &rights);
+		}
+		if (!rsbac_ta_list_lol_exist(ta_number, scd_handle, &tid.scd)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_SCD_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number,
+						      scd_handle, 0,
+						      &tid.scd, &mask);
+			if (err)
+				return err;
+		} else {	/* old entry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       scd_handle,
+							       NULL,
+							       &tid.scd,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    scd_handle,
+						    ttl,
+						    &tid.scd,
+						    &desc, &rights);
+
+	case T_USER:
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_u_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_u_handle, ttl,
+						     &desc, &rights);
+		}
+		if (!rsbac_ta_list_lol_exist(ta_number, u_handle, &tid.user)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_U_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number, u_handle,
+						      0, &tid.user, &mask);
+			if (err)
+				return err;
+		} else {	/* old subentry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       u_handle,
+							       NULL,
+							       &tid.user,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    u_handle,
+						    ttl,
+						    &tid.user,
+						    &desc, &rights);
+
+	case T_PROCESS:
+		/* default entry? */
+		if (!tid.process) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_p_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_p_handle, ttl,
+						     &desc, &rights);
+		} else
+			return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_g_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_g_handle, ttl,
+						     &desc, &rights);
+		}
+		if (!rsbac_ta_list_lol_exist(ta_number, g_handle, &tid.group)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_G_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number, g_handle,
+						      0, &tid.group,
+						      &mask);
+			if (err)
+				return err;
+		} else {	/* old subentry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       g_handle,
+							       NULL,
+							       &tid.group,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    g_handle,
+						    ttl,
+						    &tid.group,
+						    &desc, &rights);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		/* default entry? */
+		if (!tid.netdev[0]) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netdev_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_netdev_handle,
+						     ttl, &desc, &rights);
+		}
+		if (!rsbac_ta_list_lol_exist(ta_number, netdev_handle, &tid.netdev)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETDEV_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number,
+						      netdev_handle, 0,
+						      &tid.netdev, &mask);
+			if (err)
+				return err;
+		} else {	/* old entry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       netdev_handle,
+							       NULL,
+							       &tid.netdev,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    netdev_handle,
+						    ttl,
+						    &tid.netdev,
+						    &desc, &rights);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		/* default entry? */
+		if (!tid.nettemp) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_nettemp_nt_handle, NULL,
+			     &desc, &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_nettemp_nt_handle,
+						     ttl, &desc, &rights);
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_list_lol_exist(ta_number, nettemp_nt_handle, &tid.nettemp)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETTEMP_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number,
+						      nettemp_nt_handle, 0,
+						      &tid.nettemp, &mask);
+			if (err)
+				return err;
+		} else {	/* old entry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       nettemp_nt_handle,
+							       NULL,
+							       &tid.
+							       nettemp,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    nettemp_nt_handle,
+						    ttl,
+						    &tid.nettemp,
+						    &desc, &rights);
+	case T_NETTEMP:
+		/* default entry? */
+		if (!tid.nettemp) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_list_lol_exist(ta_number, nettemp_handle, &tid.nettemp)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number,
+						      nettemp_handle, 0,
+						      &tid.nettemp, &mask);
+			if (err)
+				return err;
+		} else {	/* old entry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl
+			    (ta_number, nettemp_handle, NULL, &tid.nettemp,
+			     &desc, &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    nettemp_handle, ttl,
+						    &tid.nettemp, &desc,
+						    &rights);
+	case T_NETOBJ:
+		/* default entry? */
+		if (!tid.netobj.sock_p) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netobj_handle, NULL, &desc,
+			     &old_rights))
+				rights |= old_rights;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     default_netobj_handle,
+						     ttl, &desc, &rights);
+		}
+		if (!rsbac_ta_list_lol_exist(ta_number, netobj_handle, &tid.netobj.sock_p)) {	/* new acl */
+			rsbac_acl_rights_vector_t mask =
+			    RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+
+			err =
+			    rsbac_ta_list_lol_add_ttl(ta_number,
+						      netobj_handle, 0,
+						      &tid.netobj.sock_p,
+						      &mask);
+			if (err)
+				return err;
+		} else {	/* old entry? */
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       netobj_handle,
+							       NULL,
+							       &tid.netobj.
+							       sock_p,
+							       &desc,
+							       &old_rights))
+				rights |= old_rights;
+		}
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    netobj_handle,
+						    ttl,
+						    &tid.netobj.sock_p,
+						    &desc, &rights);
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+/* rsbac_acl_remove_from_acl_entry
+ * Remove given rights from ACL entry for given target and subject. If entry does
+ * not exist, nothing happens.
+ * This function does NOT remove the ACL entry, so removing all rights results in
+ * NO rights for this subject/target combination!
+ */
+
+int rsbac_acl_remove_from_acl_entry(rsbac_list_ta_number_t ta_number,
+				    enum rsbac_target_t target,
+				    union rsbac_target_id_t tid,
+				    enum rsbac_acl_subject_type_t
+				    subj_type,
+				    rsbac_acl_subject_id_t subj_id,
+				    rsbac_acl_rights_vector_t rights)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	rsbac_acl_rights_vector_t old_rights;
+	struct rsbac_acl_entry_desc_t desc;
+	rsbac_time_t ttl;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_remove_from_acl_entry(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (subj_type >= ACLS_NONE)
+		return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_remove_from_acl_entry(): called from interrupt!\n");
+	}
+#endif
+	desc.subj_type = subj_type;
+	desc.subj_id = subj_id;
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_fd_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_fd_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_remove_from_acl_entry(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       device_p->handle,
+						       &ttl,
+						       &inode_nr,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+							   device_p->handle,
+							   ttl,
+							   &inode_nr,
+							   &desc,
+							   &old_rights);
+		} else
+			err = 0;
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return err;
+
+	case T_DEV:
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev)) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_dev_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_dev_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		switch (tid.dev.type) {
+		case D_char:
+		case D_block:
+			if (!rsbac_ta_list_lol_get_subdata_ttl
+			    (ta_number, dev_handle, &ttl, &tid.dev, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 dev_handle,
+								 ttl,
+								 &tid.dev,
+								 &desc,
+								 &old_rights);
+			} else
+				return 0;
+
+		case D_char_major:
+		case D_block_major:
+			tid.dev.type -= (D_block_major - D_block);
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       dev_major_handle,
+							       &ttl,
+							       &tid.dev,
+							       &desc,
+							       &old_rights))
+			{
+				old_rights &= ~rights;
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 dev_major_handle,
+								 ttl,
+								 &tid.dev,
+								 &desc,
+								 &old_rights);
+			} else
+				return 0;
+
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case T_IPC:
+		/* default entry? */
+		if (tid.ipc.type == I_none) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_ipc_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_ipc_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		} else
+			return -RSBAC_EINVALIDTARGET;
+
+	case T_SCD:
+		/* default entry? */
+		if (tid.scd == AST_none) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_scd_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_scd_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       scd_handle,
+						       &ttl,
+						       &tid.scd,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    scd_handle,
+							    ttl,
+							    &tid.scd,
+							    &desc,
+							    &old_rights);
+		} else
+			return 0;
+
+	case T_USER:
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_u_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_u_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       u_handle,
+						       &ttl,
+						       &tid.user,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    u_handle,
+							    ttl,
+							    &tid.user,
+							    &desc,
+							    &old_rights);
+		} else
+			return 0;
+
+	case T_PROCESS:
+		/* default entry? */
+		if (!tid.process) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_p_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_p_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		} else
+			return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_g_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_g_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       g_handle,
+						       &ttl,
+						       &tid.group,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    g_handle,
+							    ttl,
+							    &tid.group,
+							    &desc,
+							    &old_rights);
+		} else
+			return 0;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		/* default entry? */
+		if (!tid.netdev[0]) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netdev_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_netdev_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       netdev_handle,
+						       &ttl,
+						       &tid.netdev,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    netdev_handle,
+							    ttl,
+							    &tid.netdev,
+							    &desc,
+							    &old_rights);
+		} else
+			return 0;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		/* default entry? */
+		if (!tid.nettemp) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_nettemp_nt_handle, &ttl,
+			     &desc, &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_nettemp_nt_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       nettemp_nt_handle,
+						       &ttl,
+						       &tid.nettemp,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    nettemp_nt_handle,
+							    ttl,
+							    &tid.nettemp,
+							    &desc,
+							    &old_rights);
+		} else
+			return 0;
+	case T_NETTEMP:
+		/* default entry? */
+		if (!tid.nettemp) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       nettemp_handle,
+						       &ttl,
+						       &tid.nettemp,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    nettemp_handle,
+							    ttl,
+							    &tid.nettemp,
+							    &desc,
+							    &old_rights);
+		} else
+			return 0;
+	case T_NETOBJ:
+		/* default entry? */
+		if (!tid.netobj.sock_p) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netobj_handle, &ttl, &desc,
+			     &old_rights)) {
+				old_rights &= ~rights;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     default_netobj_handle,
+							     ttl, &desc,
+							     &old_rights);
+			} else
+				return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       netobj_handle,
+						       &ttl,
+						       &tid.netobj.sock_p,
+						       &desc,
+						       &old_rights)) {
+			old_rights &= ~rights;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    netobj_handle,
+							    ttl,
+							    &tid.netobj.
+							    sock_p, &desc,
+							    &old_rights);
+		} else
+			return 0;
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+/* rsbac_acl_set_mask
+ * Set inheritance mask for given target to given rights. If item does
+ * not exist, it is created.
+ */
+
+int rsbac_acl_set_mask(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_target_t target,
+		       union rsbac_target_id_t tid,
+		       rsbac_acl_rights_vector_t mask)
+{
+	int err = 0;
+#ifdef CONFIG_RSBAC_DEBUG
+	char tmp[80];
+#endif
+	struct rsbac_acl_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_set_mask(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (target >= T_NONE)
+		return -RSBAC_EINVALIDTARGET;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_set_mask(): called from interrupt!\n");
+	}
+#endif
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev)) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting file/dir/fifo/symlink inheritance mask for device %02u:%02u, inode %lu\n",
+			       RSBAC_MAJOR(tid.file.device),
+			       RSBAC_MINOR(tid.file.device), tid.file.inode);
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_set_mask(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		err = rsbac_ta_list_lol_add_ttl(ta_number,
+					      device_p->handle,
+					      0, &inode_nr, &mask);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return err;
+
+	case T_DEV:
+		/* default entry? */
+		if (tid.dev.type == D_none) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting device inheritance mask for dev %c %02u:%02u\n",
+			       'B' + tid.dev.type,
+			       tid.dev.major, tid.dev.minor);
+		switch (tid.dev.type) {
+		case D_char:
+		case D_block:
+			return rsbac_ta_list_lol_add_ttl(ta_number,
+							 dev_handle, 0,
+							 &tid.dev, &mask);
+
+		case D_char_major:
+		case D_block_major:
+			tid.dev.type -= (D_block_major - D_block);
+			return rsbac_ta_list_lol_add_ttl(ta_number,
+							 dev_major_handle,
+							 0, &tid.dev,
+							 &mask);
+
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+	case T_SCD:
+		/* default entry? */
+		if (tid.scd == AST_none) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting SCD inheritance mask for %s\n",
+			       get_acl_scd_type_name(tmp, tid.scd));
+		return rsbac_ta_list_lol_add_ttl(ta_number, scd_handle, 0,
+						 &tid.scd, &mask);
+
+	case T_USER:
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting user inheritance mask for user %u\n",
+			       tid.user);
+		return rsbac_ta_list_lol_add_ttl(ta_number, u_handle, 0,
+						 &tid.user, &mask);
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting Linux group inheritance mask for group %u\n",
+			       tid.group);
+		return rsbac_ta_list_lol_add_ttl(ta_number, g_handle, 0,
+						 &tid.group, &mask);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		/* default entry? */
+		if (!tid.netdev[0]) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting network device inheritance mask for netdev %s\n",
+			       tid.netdev);
+		return rsbac_ta_list_lol_add_ttl(ta_number, netdev_handle,
+						 0, &tid.netdev, &mask);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		/* default entry? */
+		if (!tid.nettemp) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		rsbac_pr_debug(ds_acl, "Setting network template NT inheritance mask for nettemp %u\n",
+			       tid.nettemp);
+		return rsbac_ta_list_lol_add_ttl(ta_number,
+						 nettemp_nt_handle, 0,
+						 &tid.nettemp, &mask);
+
+	case T_NETTEMP:
+		/* default entry? */
+		if (!tid.nettemp) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		rsbac_pr_debug(ds_acl, "Setting network template inheritance mask for nettemp %u\n",
+			       tid.nettemp);
+		return rsbac_ta_list_lol_add_ttl(ta_number, nettemp_handle,
+						 0, &tid.nettemp, &mask);
+
+	case T_NETOBJ:
+		/* default entry? */
+		if (!tid.netobj.sock_p) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		rsbac_pr_debug(ds_acl, "Setting network object inheritance mask for netobj %p\n",
+			       tid.netobj.sock_p);
+		return rsbac_ta_list_lol_add_ttl(ta_number, netobj_handle,
+						 0, &tid.netobj.sock_p,
+						 &mask);
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		err = -RSBAC_EINVALIDTARGET;
+	}
+	return err;
+}
+
+/* rsbac_acl_get_mask
+ * Get inheritance mask for given target. If item does
+ * not exist, default mask is returned.
+ */
+
+int rsbac_acl_get_mask(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_target_t target,
+		       union rsbac_target_id_t tid,
+		       rsbac_acl_rights_vector_t * mask_p)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_mask(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (target >= T_NONE)
+		return -RSBAC_EINVALIDTARGET;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_mask(): called from interrupt!\n");
+	}
+#endif
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+	        inode_nr = tid.file.inode;
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_get_mask(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		err = rsbac_ta_list_lol_get_data_ttl(ta_number,
+						   device_p->handle, NULL,
+						   &inode_nr,
+						   mask_p);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_FD_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+
+	case T_DEV:
+		/* default entry? */
+		if (tid.dev.type == D_none) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+		switch (tid.dev.type) {
+		case D_char:
+		case D_block:
+			err =
+			    rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   dev_handle,
+							   NULL, &tid.dev,
+							   mask_p);
+			break;
+
+		case D_char_major:
+		case D_block_major:
+			tid.dev.type -= (D_block_major - D_block);
+			err =
+			    rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   dev_major_handle,
+							   NULL, &tid.dev,
+							   mask_p);
+			break;
+
+		default:
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_DEV_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+
+	case T_SCD:
+		/* default entry? */
+		if (tid.scd == AST_none) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number, scd_handle,
+						   NULL, &tid.scd, mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_SCD_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+
+	case T_USER:
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number, u_handle,
+						   NULL, &tid.user,
+						   mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_U_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number, g_handle,
+						   NULL, &tid.group,
+						   mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_G_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		/* default entry? */
+		if (!tid.netdev[0]) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number,
+						   netdev_handle, NULL,
+						   &tid.netdev, mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_NETDEV_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	case T_NETTEMP_NT:
+		/* default entry? */
+		if (!tid.nettemp) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number,
+						   nettemp_nt_handle, NULL,
+						   &tid.nettemp, mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_NETTEMP_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+	case T_NETTEMP:
+		/* default entry? */
+		if (!tid.nettemp) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number,
+						   nettemp_handle, NULL,
+						   &tid.nettemp, mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+	case T_NETOBJ:
+		/* default entry? */
+		if (!tid.netobj.sock_p) {
+			return -RSBAC_EINVALIDTARGET;
+		}
+
+		err =
+		    rsbac_ta_list_lol_get_data_ttl(ta_number,
+						   netobj_handle, NULL,
+						   &tid.netobj.sock_p,
+						   mask_p);
+		if (err == -RSBAC_ENOTFOUND) {
+			*mask_p = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+			err = 0;
+		}
+		/* ready. */
+		return err;
+#endif
+
+	default:
+		err = -RSBAC_EINVALIDTARGET;
+	}
+	return err;
+}
+
+/* rsbac_acl_get_rights
+ * Get rights from ACL entry for given target and subject.
+ * If entry does not exist and inherit is on, inherited rights are used.
+ * If there is no parent, the default rights vector for this target type is returned.
+ * This function does NOT add role or group rights to user rights!
+ */
+
+int rsbac_acl_get_rights(rsbac_list_ta_number_t ta_number,
+			 enum rsbac_target_t target,
+			 union rsbac_target_id_t tid,
+			 enum rsbac_acl_subject_type_t subj_type,
+			 rsbac_acl_subject_id_t subj_id,
+			 rsbac_acl_rights_vector_t * rights_p,
+			 rsbac_boolean_t inherit)
+{
+	int err = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	struct rsbac_acl_entry_desc_t desc;
+	rsbac_acl_rights_vector_t i_rights = 0;
+	rsbac_acl_rights_vector_t mask = -1;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_rights(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (!rights_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (subj_type >= ACLS_NONE)
+		return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_rights(): called from interrupt!\n");
+	}
+#endif
+	desc.subj_type = subj_type;
+	desc.subj_id = subj_id;
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_fd_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_fd_rights;
+			}
+			return 0;
+		}
+		*rights_p = 0;
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* use loop for inheritance - used to be recursive calls */
+		for (;;) {
+			/* lookup device */
+			device_p = acl_lookup_device(tid.file.device);
+			if (!device_p) {
+				rsbac_printk(KERN_WARNING "rsbac_acl_get_rights(): Could not lookup device %02u:%02u!\n",
+					     RSBAC_MAJOR(tid.file.
+							 device),
+					     RSBAC_MINOR(tid.file.
+							 device));
+				srcu_read_unlock(&device_list_srcu, srcu_idx);
+				return -RSBAC_EINVALIDDEV;
+			}
+			inode_nr = tid.file.inode;
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+								device_p->handle,
+								NULL,
+								&inode_nr,
+								&desc,
+								&i_rights))
+			{
+				*rights_p |= (i_rights & mask);
+				/* leave loop */
+				break;
+			} else if (inherit) {
+				enum rsbac_target_t parent_target;
+				union rsbac_target_id_t parent_tid;
+				rsbac_acl_rights_vector_t i_mask;
+
+				/* get mask to filter through in next round */
+				if (rsbac_ta_list_lol_get_data_ttl
+				    (ta_number, device_p->handle,
+				     NULL, &inode_nr, &i_mask)) {
+					/* no mask found, set default */
+					i_mask = RSBAC_ACL_DEFAULT_FD_MASK;
+				}
+				/* mask into cumulative mask */
+				mask &= i_mask;
+
+				/* inheritance possible? */
+				if (!rsbac_get_parent
+				    (target, tid, &parent_target,
+				     &parent_tid)) {
+					target = parent_target;
+					tid = parent_tid;
+					/* next round */
+					continue;
+				} else {
+					/* no inheritance possible -> try default_fd_acl */
+					if (!rsbac_ta_list_get_data_ttl
+					    (ta_number, default_fd_handle,
+					     NULL, &desc, &i_rights)) {
+						/* found, use it */
+						*rights_p |=
+						    (i_rights & mask);
+					} else {
+						/* last resort: default rights */
+						*rights_p |=
+						    (default_fd_rights &
+						     mask);
+					}
+				}
+				/* leave loop */
+				break;
+			} else {	/* do not inherit */
+
+				/* last resort: default rights */
+				*rights_p |= default_fd_rights;
+				/* leave loop */
+				break;
+			}
+		}		/* end of for(;;) inheritance loop */
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return err;
+
+	case T_DEV:
+		/* default entry? */
+
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev)) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_dev_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_dev_rights;
+			}
+			return 0;
+		}
+		if ((tid.dev.type >= D_char_major)
+		    || (tid.dev.type == D_block_major)
+		    ) {
+			tid.dev.type -= (D_block_major - D_block);
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       dev_major_handle,
+							       NULL,
+							       &tid.dev,
+							       &desc,
+							       &i_rights))
+			{
+				*rights_p |= i_rights;
+			} else {
+				rsbac_acl_rights_vector_t mask2;
+
+				/* get mask to filter through */
+				if (rsbac_ta_list_lol_get_data_ttl
+				    (ta_number, dev_major_handle, NULL,
+				     &tid.dev, &mask2)) {
+					/* no mask found, set default */
+					mask2 = RSBAC_ACL_DEFAULT_DEV_MASK;
+				}
+				/* try default_dev_acl */
+				if (!rsbac_ta_list_get_data_ttl
+				    (ta_number, default_dev_handle, NULL,
+				     &desc, rights_p)) {
+					*rights_p &= mask2;
+				} else {
+					/* last resort: default rights */
+					*rights_p =
+					    default_dev_rights & mask2;
+				}
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       dev_handle,
+						       NULL,
+						       &tid.dev,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   dev_handle,
+							   NULL,
+							   &tid.dev,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_DEV_MASK;
+			}
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       dev_major_handle,
+							       NULL,
+							       &tid.dev,
+							       &desc,
+							       &i_rights))
+			{
+				i_rights &= mask;
+				*rights_p |= i_rights;
+			} else {
+				rsbac_acl_rights_vector_t mask2;
+
+				/* get mask to filter through */
+				if (rsbac_ta_list_lol_get_data_ttl
+				    (ta_number, dev_major_handle, NULL,
+				     &tid.dev, &mask2)) {
+					/* no mask found, set default */
+					mask2 = RSBAC_ACL_DEFAULT_DEV_MASK;
+				}
+				/* try default_dev_acl */
+				if (!rsbac_ta_list_get_data_ttl
+				    (ta_number, default_dev_handle, NULL,
+				     &desc, rights_p)) {
+					*rights_p &= mask;
+					*rights_p &= mask2;
+				} else {
+					/* last resort: default rights */
+					*rights_p =
+					    default_dev_rights & mask &
+					    mask2;
+				}
+			}
+		}
+		return 0;
+
+	case T_IPC:
+
+		/* Use default ACL */
+		if (rsbac_ta_list_get_data_ttl
+		    (ta_number, default_ipc_handle, NULL, &desc,
+		     rights_p)) {
+			/* last resort: default rights */
+			*rights_p = default_ipc_rights;
+		}
+		return 0;
+
+	case T_SCD:
+		/* default entry? */
+		if ((tid.scd == AST_none)
+		    || (tid.scd == ST_none)
+		    ) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_scd_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_scd_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       scd_handle,
+						       NULL,
+						       &tid.scd,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   scd_handle,
+							   NULL,
+							   &tid.scd,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_SCD_MASK;
+			}
+			/* try default_dev_acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_scd_handle, NULL, &desc,
+			     rights_p)) {
+				*rights_p &= mask;
+			} else {
+				/* last resort: default rights */
+				*rights_p = default_scd_rights & mask;
+			}
+		}
+		return 0;
+
+	case T_USER:
+		/* default entry? */
+		if (tid.user == RSBAC_NO_USER) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_u_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_u_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       u_handle,
+						       NULL,
+						       &tid.user,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   u_handle,
+							   NULL,
+							   &tid.user,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_U_MASK;
+			}
+			/* try default_u_acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_u_handle, NULL, &desc,
+			     rights_p)) {
+				*rights_p &= mask;
+			} else {
+				/* last resort: default rights */
+				*rights_p = default_u_rights & mask;
+			}
+		}
+		return 0;
+
+	case T_PROCESS:
+
+		/* Use default entry */
+		if (rsbac_ta_list_get_data_ttl(ta_number, default_p_handle,
+					       NULL, &desc, rights_p)) {
+			/* last resort: default rights */
+			*rights_p = default_p_rights;
+		}
+		return 0;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		/* default entry? */
+		if (tid.group == RSBAC_NO_GROUP) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_g_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_g_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       g_handle,
+						       NULL,
+						       &tid.group,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   g_handle,
+							   NULL,
+							   &tid.group,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_G_MASK;
+			}
+			/* try default_u_acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_g_handle, NULL, &desc,
+			     rights_p)) {
+				*rights_p &= mask;
+			} else {
+				/* last resort: default rights */
+				*rights_p = default_g_rights & mask;
+			}
+		}
+		return 0;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	case T_NETDEV:
+		/* default entry? */
+
+		if (!tid.netdev[0]) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netdev_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_netdev_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       netdev_handle,
+						       NULL,
+						       &tid.netdev,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   netdev_handle,
+							   NULL,
+							   &tid.netdev,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_NETDEV_MASK;
+			}
+			/* try default_dev_acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netdev_handle, NULL, &desc,
+			     rights_p)) {
+				*rights_p &= mask;
+			} else {
+				/* last resort: default rights */
+				*rights_p = default_netdev_rights & mask;
+			}
+		}
+		return 0;
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+		/* rights to template itself */
+	case T_NETTEMP_NT:
+		/* default entry? */
+
+		if (!tid.nettemp) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_nettemp_nt_handle, NULL,
+			     &desc, rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_nettemp_nt_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       nettemp_nt_handle,
+						       NULL,
+						       &tid.nettemp,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   nettemp_nt_handle,
+							   NULL,
+							   &tid.nettemp,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_NETTEMP_MASK;
+			}
+			/* try default_dev_acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_nettemp_nt_handle, NULL,
+			     &desc, rights_p)) {
+				*rights_p &= mask;
+			} else {
+				/* last resort: default rights */
+				*rights_p =
+				    default_nettemp_nt_rights & mask;
+			}
+		}
+		return 0;
+
+		/* rights to netobjs fitting this template */
+	case T_NETTEMP:
+		/* default entry? */
+
+		if (!tid.nettemp) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netobj_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_netobj_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       nettemp_handle,
+						       NULL,
+						       &tid.nettemp,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   nettemp_handle,
+							   NULL,
+							   &tid.nettemp,
+							   &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+			}
+			/* try default_dev_acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netobj_handle, NULL, &desc,
+			     rights_p)) {
+				*rights_p &= mask;
+			} else {
+				/* last resort: default rights */
+				*rights_p = default_netobj_rights & mask;
+			}
+		}
+		return 0;
+
+	case T_NETOBJ:
+		/* default entry? */
+
+		if (!tid.nettemp) {
+			if (rsbac_ta_list_get_data_ttl
+			    (ta_number, default_netobj_handle, NULL, &desc,
+			     rights_p)) {
+				/* last resort: default rights */
+				*rights_p = default_netobj_rights;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+						       netobj_handle,
+						       NULL,
+						       &tid.netobj.sock_p,
+						       &desc, &i_rights)) {
+			*rights_p |= i_rights;
+		} else {
+			rsbac_acl_rights_vector_t mask;
+			rsbac_net_temp_id_t temp = 0;
+
+			/* get mask to filter through */
+			if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+							   nettemp_handle,
+							   NULL,
+							   &temp, &mask)) {
+				/* no mask found, set default */
+				mask = RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+			}
+			/* try nettemp_acl */
+			if(!ta_number && tid.netobj.local_temp)
+				temp = tid.netobj.local_temp;
+			else
+				rsbac_ta_net_lookup_templates(ta_number,
+						      &tid.netobj,
+						      &temp, NULL);
+
+			if (temp
+			    &&
+			    !rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       nettemp_handle,
+							       NULL, &temp,
+							       &desc,
+							       &i_rights))
+			{
+				*rights_p |= i_rights;
+			} else {
+				/* get mask to filter through */
+				if (temp
+				    &&
+				    rsbac_ta_list_lol_get_data_ttl
+				    (ta_number, nettemp_handle, NULL,
+				     &temp, &mask)) {
+					/* no mask found, set default */
+					mask =
+					    RSBAC_ACL_DEFAULT_NETOBJ_MASK;
+				}
+				/* try default_netobj_acl */
+				if (!rsbac_ta_list_get_data_ttl
+				    (ta_number, default_netobj_handle,
+				     NULL, &desc, rights_p)) {
+					*rights_p &= mask;
+				} else {
+					/* last resort: default rights */
+					*rights_p =
+					    default_netobj_rights & mask;
+				}
+			}
+		}
+		return 0;
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+/* rsbac_acl_get_single_right
+ * Show, whether individual right is set for given target and subject.
+ * If right is not set, it is checked at all parents, unless it has been
+ * masked out. (Special case SUPERVISOR: unless
+ * CONFIG_RSBAC_ACL_SUPER_FILTER is set *and* supervisor has been masked out)
+ */
+
+int rsbac_acl_get_single_right(enum rsbac_target_t target,
+			       union rsbac_target_id_t tid,
+			       enum rsbac_acl_subject_type_t subj_type,
+			       rsbac_acl_subject_id_t subj_id,
+			       enum rsbac_adf_request_t right,
+			       rsbac_boolean_t * result)
+{
+	struct rsbac_acl_device_list_item_t *device_p;
+	rsbac_acl_rights_vector_t i_rvec;
+	rsbac_acl_rights_vector_t i_rights;
+	struct rsbac_acl_entry_desc_t desc;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_single_right(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (!result)
+		return -RSBAC_EINVALIDPOINTER;
+	if ((subj_type >= ACLS_NONE)
+	    || ((enum rsbac_acl_special_rights_t) right >= ACLR_NONE)
+	    )
+		return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_single_right(): called from interrupt!\n");
+	}
+#endif
+	i_rvec = (rsbac_acl_rights_vector_t) 1 << right;
+
+	desc.subj_type = subj_type;
+	desc.subj_id = subj_id;
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_fd_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_fd_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* use loop for inheritance - used to be recursive calls */
+		for (;;) {
+			/* lookup device */
+			device_p = acl_lookup_device(tid.file.device);
+			if (!device_p) {
+				rsbac_printk(KERN_WARNING "rsbac_acl_get_single_right(): Could not lookup device, blindly granting access!\n");
+				srcu_read_unlock(&device_list_srcu, srcu_idx);
+				*result = TRUE;
+				return 0;
+			}
+		        inode_nr = tid.file.inode;
+			if (!rsbac_ta_list_lol_get_subdata_ttl(0,
+							       device_p->handle,
+							       NULL,
+							       &inode_nr,
+							       &desc,
+							       &i_rights)
+			    ) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+				srcu_read_unlock(&device_list_srcu, srcu_idx);
+				return 0;
+			}
+
+			{
+				enum rsbac_target_t parent_target;
+				union rsbac_target_id_t parent_tid;
+
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+				if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+				{
+					rsbac_acl_rights_vector_t mask;
+
+					/* get mask to filter through */
+					if (!rsbac_ta_list_lol_get_data_ttl
+					    (0, device_p->handle,
+					     NULL, &inode_nr, &mask)
+					    && !(mask & i_rvec)
+					    ) {
+						srcu_read_unlock(&device_list_srcu, srcu_idx);
+						*result = FALSE;
+						return 0;
+					}
+				}
+
+				/* inheritance possible? */
+				if (!rsbac_get_parent
+				    (target, tid, &parent_target,
+				     &parent_tid)) {
+					target = parent_target;
+					tid = parent_tid;
+					continue;
+				} else {
+					/* no inheritance possible -> try default_fd_acl */
+					if (!rsbac_ta_list_get_data_ttl
+					    (0, default_fd_handle, NULL,
+					     &desc, &i_rights)
+					    ) {
+						if (i_rights & i_rvec)
+							*result = TRUE;
+						else
+							*result = FALSE;
+					} else {
+						if (default_fd_rights &
+						    i_rvec)
+							*result = TRUE;
+						else
+							*result = FALSE;
+					}
+					/* free access to device_list_head - see above */
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+					return 0;
+				}
+			}
+		}		/* end of for(;;) for inheritance */
+
+	case T_DEV:
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev)) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_dev_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_dev_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		if (tid.dev.type >= D_block_major) {
+			tid.dev.type -= (D_block_major - D_block);
+			if (!rsbac_ta_list_lol_get_subdata_ttl
+			    (0, dev_major_handle, NULL, &tid.dev, &desc,
+			     &i_rights)
+			    ) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+				return 0;
+			}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+			if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+			{
+				rsbac_acl_rights_vector_t mask;
+
+				/* get mask to filter through */
+				if (!rsbac_ta_list_lol_get_data_ttl
+				    (0, dev_major_handle, NULL, &tid.dev,
+				     &mask)
+				    && !(mask & i_rvec)
+				    ) {
+					*result = FALSE;
+					return 0;
+				}
+			}
+			/* no inheritance possible -> try default acl */
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_dev_handle, NULL, &desc, &i_rights)
+			    ) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_dev_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, dev_handle,
+						       NULL,
+						       &tid.dev,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl(0, dev_handle,
+							    NULL,
+							    &tid.dev,
+							    &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, dev_major_handle,
+						       NULL,
+						       &tid.dev,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl
+			    (0, dev_major_handle, NULL, &tid.dev, &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl(0, default_dev_handle,
+						NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_dev_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+
+	case T_IPC:
+		/* Use default entry */
+		if (!rsbac_ta_list_get_data_ttl(0, default_ipc_handle,
+						NULL, &desc, &i_rights)) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_ipc_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+
+	case T_SCD:
+		if (tid.scd == AST_none) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_scd_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_scd_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, scd_handle,
+						       NULL,
+						       &tid.scd,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl(0, scd_handle,
+							    NULL,
+							    &tid.scd,
+							    &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl(0, default_scd_handle,
+						NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_scd_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+
+	case T_USER:
+		if (tid.user == RSBAC_NO_USER) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_u_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_u_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, u_handle,
+						       NULL,
+						       &tid.user,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl(0, u_handle,
+							    NULL,
+							    &tid.user,
+							    &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl(0, default_u_handle,
+						NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_u_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+
+	case T_PROCESS:
+		/* Use default entry */
+		if (!rsbac_ta_list_get_data_ttl(0, default_p_handle,
+						NULL, &desc, &i_rights)) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_p_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		if (tid.group == RSBAC_NO_GROUP) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_g_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_g_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, g_handle,
+						       NULL,
+						       &tid.group,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl(0, g_handle,
+							    NULL,
+							    &tid.group,
+							    &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl(0, default_g_handle,
+						NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_g_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_NET_DEV_PROT)
+	case T_NETDEV:
+		if (!tid.netdev[0]) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_netdev_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_netdev_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, netdev_handle,
+						       NULL,
+						       &tid.netdev,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl
+			    (0, netdev_handle, NULL, &tid.netdev, &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl(0, default_netdev_handle,
+						NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_netdev_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_NET_OBJ_PROT)
+	case T_NETTEMP_NT:
+	case T_NETTEMP:
+		if (!tid.nettemp) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_nettemp_nt_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_nettemp_nt_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		/* There should be no template, which is to be created, so skip nettemp_nt list */
+		if (right != R_CREATE) {
+			if (!rsbac_net_template_exist(tid.nettemp))
+				return FALSE;
+			if (!rsbac_ta_list_lol_get_subdata_ttl
+			    (0, nettemp_nt_handle, NULL, &tid.nettemp,
+			     &desc, &i_rights)
+			    && (i_rights & i_rvec)
+			    ) {
+				*result = TRUE;
+				return 0;
+			}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+			if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+			{
+				rsbac_acl_rights_vector_t mask;
+
+				/* get mask to filter through */
+				if (!rsbac_ta_list_lol_get_data_ttl
+				    (0, nettemp_nt_handle, NULL,
+				     &tid.nettemp, &mask)
+				    && !(mask & i_rvec)
+				    ) {
+					*result = FALSE;
+					return 0;
+				}
+			}
+		}
+
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl
+		    (0, default_nettemp_nt_handle, NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_nettemp_nt_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+
+	case T_NETOBJ:
+		if (!tid.netobj.sock_p) {
+			if (!rsbac_ta_list_get_data_ttl
+			    (0, default_netobj_handle, NULL, &desc,
+			     &i_rights)) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			} else {
+				if (default_netobj_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+			}
+			return 0;
+		}
+
+		if (!rsbac_ta_list_lol_get_subdata_ttl(0, netobj_handle,
+						       NULL,
+						       &tid.netobj.sock_p,
+						       &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+			return 0;
+		}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+		if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+		{
+			rsbac_acl_rights_vector_t mask;
+
+			/* get mask to filter through */
+			if (!rsbac_ta_list_lol_get_data_ttl
+			    (0, netobj_handle, NULL, &tid.netobj.sock_p,
+			     &mask)
+			    && !(mask & i_rvec)
+			    ) {
+				*result = FALSE;
+				return 0;
+			}
+		}
+		/* Try net template */
+		{
+			rsbac_net_temp_id_t temp = 0;
+
+			if (rsbac_net_remote_request(right)) {
+				if(tid.netobj.remote_temp)
+					temp = tid.netobj.remote_temp;
+				else
+					rsbac_ta_net_lookup_templates(0,
+							      &tid.netobj,
+							      NULL, &temp);
+			} else {
+				if(tid.netobj.local_temp)
+					temp = tid.netobj.local_temp;
+				else
+					rsbac_ta_net_lookup_templates(0,
+							      &tid.netobj,
+							      &temp, NULL);
+			}
+			if (temp
+			    && !rsbac_ta_list_lol_get_subdata_ttl(0,
+								  nettemp_handle,
+								  NULL,
+								  &temp,
+								  &desc,
+								  &i_rights)
+			    ) {
+				if (i_rights & i_rvec)
+					*result = TRUE;
+				else
+					*result = FALSE;
+				return 0;
+			}
+#ifndef CONFIG_RSBAC_ACL_SUPER_FILTER
+			if ((enum rsbac_acl_special_rights_t) right != ACLR_SUPERVISOR)
+#endif
+			{
+				rsbac_acl_rights_vector_t mask;
+
+				/* get mask from template to filter through */
+				if (!rsbac_ta_list_lol_get_data_ttl
+				    (0, nettemp_handle, NULL, &temp, &mask)
+				    && !(mask & i_rvec)
+				    ) {
+					*result = FALSE;
+					return 0;
+				}
+			}
+		}
+
+		/* no inheritance possible -> try default acl */
+		if (!rsbac_ta_list_get_data_ttl(0, default_netobj_handle,
+						NULL, &desc, &i_rights)
+		    ) {
+			if (i_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		} else {
+			if (default_netobj_rights & i_rvec)
+				*result = TRUE;
+			else
+				*result = FALSE;
+		}
+		return 0;
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+/*************************************************
+ * rsbac_acl_get_tlist
+ * Get subjects from ACL entries for given target.
+ */
+
+int rsbac_acl_get_tlist(rsbac_list_ta_number_t ta_number,
+			enum rsbac_target_t target,
+			union rsbac_target_id_t tid,
+			struct rsbac_acl_entry_t **entry_pp,
+			rsbac_time_t ** ttl_pp)
+{
+	int count = 0;
+	struct rsbac_acl_device_list_item_t *device_p;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_tlist(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (!entry_pp)
+		return -RSBAC_EINVALIDPOINTER;
+#ifdef CONFIG_RSBAC_DEBUG
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_acl_get_tlist(): called from interrupt!\n");
+	}
+#endif
+	switch (target) {
+	case T_FD:
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_UNIXSOCK:
+		/* default entry? */
+		if (RSBAC_IS_ZERO_DEV(tid.file.device) && !tid.file.inode
+		    && !tid.file.dentry_p)
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_fd_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		srcu_idx = srcu_read_lock(&device_list_srcu);
+		/* lookup device */
+		device_p = acl_lookup_device(tid.file.device);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_acl_get_tlist(): Could not lookup device!\n");
+			srcu_read_unlock(&device_list_srcu, srcu_idx);
+			return -RSBAC_EINVALIDDEV;
+		}
+		/* protect this list */
+		count = rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+							       device_p->
+							       handle,
+							       &tid.file.
+							       inode,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return count;
+
+	case T_DEV:
+		if (RSBAC_IS_ZERO_DEV_DESC(tid.dev))
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_dev_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		else
+			switch (tid.dev.type) {
+			case D_char:
+			case D_block:
+				return
+				    rsbac_ta_list_lol_get_all_subitems_ttl
+				    (ta_number, dev_handle, &tid.dev,
+				     (void **) entry_pp, ttl_pp);
+
+			case D_char_major:
+			case D_block_major:
+				tid.dev.type -= (D_block_major - D_block);
+				return
+				    rsbac_ta_list_lol_get_all_subitems_ttl
+				    (ta_number, dev_major_handle, &tid.dev,
+				     (void **) entry_pp, ttl_pp);
+
+			default:
+				return -RSBAC_EINVALIDTARGET;
+			}
+
+	case T_IPC:
+		/* default entry */
+		return rsbac_ta_list_get_all_items_ttl(ta_number,
+						       default_ipc_handle,
+						       (void **) entry_pp,
+						       ttl_pp);
+
+	case T_SCD:
+		if ((tid.scd == AST_none)
+		    || (tid.scd == ST_none)
+		    )
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_scd_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		else
+			return
+			    rsbac_ta_list_lol_get_all_subitems_ttl
+			    (ta_number, scd_handle, &tid.scd,
+			     (void **) entry_pp, ttl_pp);
+
+	case T_USER:
+		if (tid.user == RSBAC_NO_USER)
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_u_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		else
+			return
+			    rsbac_ta_list_lol_get_all_subitems_ttl
+			    (ta_number, u_handle, &tid.user,
+			     (void **) entry_pp, ttl_pp);
+
+	case T_PROCESS:
+		return rsbac_ta_list_get_all_items_ttl(ta_number,
+						       default_p_handle,
+						       (void **) entry_pp,
+						       ttl_pp);
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	case T_GROUP:
+		if (tid.group == RSBAC_NO_GROUP)
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_g_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		else
+			return
+			    rsbac_ta_list_lol_get_all_subitems_ttl
+			    (ta_number, g_handle, &tid.group,
+			     (void **) entry_pp, ttl_pp);
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_NET_DEV_PROT)
+	case T_NETDEV:
+		if (!tid.netdev[0])
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_netdev_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		else
+			return
+			    rsbac_ta_list_lol_get_all_subitems_ttl
+			    (ta_number, netdev_handle, &tid.netdev,
+			     (void **) entry_pp, ttl_pp);
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_NET_OBJ_PROT)
+	case T_NETTEMP_NT:
+		if (!tid.nettemp)
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_nettemp_nt_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		return rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+							      nettemp_nt_handle,
+							      &tid.nettemp,
+							      (void **)
+							      entry_pp,
+							      ttl_pp);
+
+	case T_NETTEMP:
+		if (!tid.nettemp)
+			return -RSBAC_EINVALIDTARGET;
+		if (!rsbac_ta_net_template_exist(ta_number, tid.nettemp))
+			return -RSBAC_EINVALIDTARGET;
+		return rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+							      nettemp_handle,
+							      &tid.nettemp,
+							      (void **)
+							      entry_pp,
+							      ttl_pp);
+
+	case T_NETOBJ:
+		if (!tid.nettemp)
+			return rsbac_ta_list_get_all_items_ttl(ta_number,
+							       default_netobj_handle,
+							       (void **)
+							       entry_pp,
+							       ttl_pp);
+		else
+			return
+			    rsbac_ta_list_lol_get_all_subitems_ttl
+			    (ta_number, netobj_handle, &tid.netobj.sock_p,
+			     (void **) entry_pp, ttl_pp);
+#endif				/* NET_OBJ_PROT */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+/* Remove a subject from all acls (but not from group memberships, see remove_user) */
+int rsbac_acl_remove_subject(rsbac_list_ta_number_t ta_number,
+			     struct rsbac_acl_entry_desc_t desc)
+{
+	struct rsbac_acl_device_list_head_t *head_p;
+	struct rsbac_acl_device_list_item_t *device_p;
+	int srcu_idx;
+
+	if (desc.subj_type >= ACLS_NONE)
+		return -RSBAC_EINVALIDVALUE;
+
+	/* remove from default ACLs */
+	rsbac_ta_list_remove(ta_number, default_fd_handle, &desc);
+	rsbac_ta_list_remove(ta_number, default_dev_handle, &desc);
+	rsbac_ta_list_remove(ta_number, default_ipc_handle, &desc);
+	rsbac_ta_list_remove(ta_number, default_scd_handle, &desc);
+	rsbac_ta_list_remove(ta_number, default_u_handle, &desc);
+	rsbac_ta_list_remove(ta_number, default_p_handle, &desc);
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	rsbac_ta_list_remove(ta_number, default_g_handle, &desc);
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	rsbac_ta_list_remove(ta_number, default_netdev_handle, &desc);
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	rsbac_ta_list_remove(ta_number, default_nettemp_nt_handle, &desc);
+	rsbac_ta_list_remove(ta_number, default_netobj_handle, &desc);
+#endif
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		rsbac_ta_list_lol_subremove_from_all(ta_number,
+						     device_p->handle,
+						     &desc);
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	/* dev list */
+	rsbac_ta_list_lol_subremove_from_all(ta_number, dev_major_handle,
+					     &desc);
+	rsbac_ta_list_lol_subremove_from_all(ta_number, dev_handle, &desc);
+
+	/* scd list */
+	rsbac_ta_list_lol_subremove_from_all(ta_number, scd_handle, &desc);
+
+	/* user list */
+	rsbac_ta_list_lol_subremove_from_all(ta_number, u_handle, &desc);
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+	/* Linux group list */
+	rsbac_ta_list_lol_subremove_from_all(ta_number, g_handle, &desc);
+#endif
+
+#ifdef CONFIG_RSBAC_ACL_NET_DEV_PROT
+	/* netdev list */
+	rsbac_ta_list_lol_subremove_from_all(ta_number, netdev_handle,
+					     &desc);
+#endif
+#ifdef CONFIG_RSBAC_ACL_NET_OBJ_PROT
+	rsbac_ta_list_lol_subremove_from_all(ta_number, nettemp_nt_handle,
+					     &desc);
+	rsbac_ta_list_lol_subremove_from_all(ta_number, nettemp_handle,
+					     &desc);
+	rsbac_ta_list_lol_subremove_from_all(ta_number, netobj_handle,
+					     &desc);
+#endif
+
+	return 0;
+}
+
+/* add a group with new id and fill this id into *group_id_p */
+/* if old content of group_id_p is 0, make new id, else try given id */
+int rsbac_acl_add_group(rsbac_list_ta_number_t ta_number,
+			rsbac_uid_t owner,
+			enum rsbac_acl_group_type_t type,
+			const char *name, rsbac_acl_group_id_t * group_id_p)
+{
+	struct rsbac_acl_group_entry_t entry;
+	int err = 0;
+
+	if (type >= ACLG_NONE)
+		return -RSBAC_EINVALIDVALUE;
+	if (!name || !group_id_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!name[0])
+		return -RSBAC_EINVALIDVALUE;
+	entry.owner = owner;
+	entry.type = type;
+	strncpy(entry.name, name, RSBAC_ACL_GROUP_NAMELEN - 1);
+	entry.name[RSBAC_ACL_GROUP_NAMELEN - 1] = 0;
+	if (!*group_id_p) {
+		/* step new group counter */
+		group_last_new++;
+		/* Just in case the counter has wrapped. It is almost impossible that all IDs are in use. */
+		while (!group_last_new
+		       || rsbac_ta_list_exist(ta_number, group_handle,
+					      &group_last_new))
+			group_last_new++;
+
+		entry.id = group_last_new;
+	} else {
+		if (rsbac_ta_list_exist
+		    (ta_number, group_handle, group_id_p)) {
+			return -RSBAC_EEXISTS;
+		} else
+			entry.id = *group_id_p;
+	}
+	if (rsbac_ta_list_add_ttl
+	    (ta_number, group_handle, 0, &entry.id, &entry))
+		err = -RSBAC_ECOULDNOTADDITEM;
+	else {
+		*group_id_p = entry.id;
+	}
+	return err;
+}
+
+int rsbac_acl_change_group(rsbac_list_ta_number_t ta_number,
+			   rsbac_acl_group_id_t id,
+			   rsbac_uid_t owner,
+			   enum rsbac_acl_group_type_t type, const char *name)
+{
+	struct rsbac_acl_group_entry_t entry;
+
+	if (!id)
+		return -RSBAC_EINVALIDVALUE;
+	if (!rsbac_ta_list_exist(ta_number, group_handle, &id))
+		return -RSBAC_ENOTFOUND;
+	if (!name)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!name[0])
+		return -RSBAC_EINVALIDVALUE;
+	entry.id = id;
+	entry.owner = owner;
+	entry.type = type;
+	strncpy(entry.name, name, RSBAC_ACL_GROUP_NAMELEN);
+	entry.name[RSBAC_ACL_GROUP_NAMELEN - 1] = 0;
+	return rsbac_ta_list_add_ttl(ta_number, group_handle, 0, &entry.id,
+				     &entry);
+}
+
+int rsbac_acl_remove_group(rsbac_list_ta_number_t ta_number,
+			   rsbac_acl_group_id_t id)
+{
+	int err = 0;
+
+	if (!id)
+		return -RSBAC_EINVALIDVALUE;
+
+	err = rsbac_ta_list_remove(ta_number, group_handle, &id);
+	if (!err) {
+		struct rsbac_acl_entry_desc_t desc;
+
+		/* cleanup group memberships */
+		rsbac_ta_list_lol_subremove_from_all(ta_number, gm_handle,
+						     &id);
+		desc.subj_type = ACLS_GROUP;
+		desc.subj_id = id;
+		err = rsbac_acl_remove_subject(ta_number, desc);
+	}
+	return err;
+}
+
+int rsbac_acl_get_group_entry(rsbac_list_ta_number_t ta_number,
+			      rsbac_acl_group_id_t group,
+			      struct rsbac_acl_group_entry_t *entry_p)
+{
+	if (!group)
+		return -RSBAC_EINVALIDVALUE;
+	if (!entry_p)
+		return -RSBAC_EINVALIDPOINTER;
+	return rsbac_ta_list_get_data_ttl(ta_number, group_handle, NULL,
+					  &group, entry_p);
+}
+
+int rsbac_acl_list_groups(rsbac_list_ta_number_t ta_number,
+			  rsbac_uid_t owner,
+			  rsbac_boolean_t include_global,
+			  struct rsbac_acl_group_entry_t **entry_pp)
+{
+	long count;
+	struct rsbac_acl_group_entry_t *local_entry_p;
+
+	if (!entry_pp)
+		return -RSBAC_EINVALIDPOINTER;
+	count =
+	    rsbac_ta_list_get_all_data(ta_number, group_handle,
+				       (void **) &local_entry_p);
+	if (count > 0) {
+		long i;
+		long rescount = 0;
+
+		*entry_pp = rsbac_kmalloc(count * sizeof(**entry_pp));
+		if (!*entry_pp) {
+			rsbac_kfree(local_entry_p);
+			return -RSBAC_ENOMEM;
+		}
+		for (i = 0; i < count; i++) {
+			if ((local_entry_p[i].owner == owner)
+			    || (include_global
+				&& (local_entry_p[i].type == ACLG_GLOBAL)
+			    )
+			    ) {
+				memcpy(&(*entry_pp)[rescount],
+				       &local_entry_p[i],
+				       sizeof(local_entry_p[i]));
+				rescount++;
+			}
+		}
+		rsbac_kfree(local_entry_p);
+		count = rescount;
+	}
+	return count;
+}
+
+/* check group existence */
+rsbac_boolean_t rsbac_acl_group_exist(rsbac_acl_group_id_t group)
+{
+	if (!group)
+		return TRUE;
+	return rsbac_ta_list_exist(0, group_handle, &group);
+}
+
+int rsbac_acl_add_group_member(rsbac_list_ta_number_t ta_number,
+			       rsbac_acl_group_id_t group,
+			       rsbac_uid_t user, rsbac_time_t ttl)
+{
+	int err = 0;
+
+	if (!group)
+		return -RSBAC_EINVALIDVALUE;
+	if (!rsbac_ta_list_exist(ta_number, group_handle, &group))
+		return -RSBAC_EINVALIDVALUE;
+
+	if (!rsbac_ta_list_lol_exist(ta_number, gm_handle, &user)) {
+		err =
+		    rsbac_ta_list_lol_add_ttl(ta_number, gm_handle, 0,
+					      &user, NULL);
+		if (err)
+			return err;
+	}
+	return rsbac_ta_list_lol_subadd_ttl(ta_number, gm_handle, ttl,
+					    &user, &group, NULL);
+}
+
+int rsbac_acl_remove_group_member(rsbac_list_ta_number_t ta_number,
+				  rsbac_acl_group_id_t group,
+				  rsbac_uid_t user)
+{
+	int err;
+
+	if (!group)
+		return -RSBAC_EINVALIDVALUE;
+	if (!rsbac_ta_list_exist(ta_number, group_handle, &group))
+		return -RSBAC_EINVALIDVALUE;
+
+	err =
+	    rsbac_ta_list_lol_subremove(ta_number, gm_handle, &user,
+					&group);
+	/* cleanup empty gm items */
+	if (!err
+	    && !rsbac_ta_list_lol_subcount(ta_number, gm_handle, &user)
+	    )
+		err =
+		    rsbac_ta_list_lol_remove(ta_number, gm_handle, &user);
+
+	return err;
+}
+
+/* check membership */
+rsbac_boolean_t rsbac_acl_group_member(rsbac_acl_group_id_t group,
+				       rsbac_uid_t user)
+{
+	return rsbac_ta_list_lol_subexist(0, gm_handle, &user, &group);
+}
+
+/* build rsbac_kmalloc'd array of all group memberships of the given user */
+/* returns number of groups or negative error */
+/* Attention: memory deallocation with rsbac_kfree (if result > 0) must be done by caller! */
+int rsbac_acl_get_user_groups(rsbac_list_ta_number_t ta_number,
+			      rsbac_uid_t user,
+			      rsbac_acl_group_id_t ** group_pp,
+			      rsbac_time_t ** ttl_pp)
+{
+	return rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+						     gm_handle,
+						     &user,
+						     (void **) group_pp,
+						     ttl_pp);
+}
+
+/* Returns number of members or negative error */
+int rsbac_acl_get_group_members(rsbac_list_ta_number_t ta_number,
+				rsbac_acl_group_id_t group,
+				rsbac_uid_t user_array[],
+				rsbac_time_t ttl_array[], int maxnum)
+{
+	long desc_count;
+	long i;
+	rsbac_uid_t *user_p;
+	int err = 0;
+
+	if (!group || (maxnum <= 0))
+		return -RSBAC_EINVALIDVALUE;
+	if (!rsbac_ta_list_exist(ta_number, group_handle, &group))
+		return -RSBAC_EINVALIDVALUE;
+	if (!user_array)
+		return -RSBAC_EINVALIDPOINTER;
+
+	/* traverse group memberships */
+	desc_count =
+	    rsbac_ta_list_lol_get_all_desc(ta_number, gm_handle,
+					   (void **) &user_p);
+	if (desc_count > 0) {
+		rsbac_time_t ttl;
+
+		for (i = 0; i < desc_count; i++) {
+			if (!rsbac_ta_list_lol_get_subdata_ttl
+			    (ta_number, gm_handle, &ttl, &user_p[i],
+			     &group, NULL)) {
+				user_array[err] = user_p[i];
+				if (ttl_array)
+					ttl_array[err] = ttl;
+				err++;
+				if (err >= maxnum)
+					break;
+			}
+		}
+		rsbac_kfree(user_p);
+	}
+	return err;
+}
+
+int rsbac_acl_list_all_dev(rsbac_list_ta_number_t ta_number,
+			   struct rsbac_dev_desc_t **id_pp)
+{
+	if (id_pp)
+		return rsbac_ta_list_lol_get_all_desc(ta_number,
+						      dev_handle,
+						      (void **) id_pp);
+	else
+		return rsbac_ta_list_lol_count(ta_number, dev_handle);
+}
+
+int rsbac_acl_list_all_major_dev(rsbac_list_ta_number_t ta_number,
+				 struct rsbac_dev_desc_t **id_pp)
+{
+	if (id_pp) {
+		int count;
+
+		count =
+		    rsbac_ta_list_lol_get_all_desc(ta_number,
+						   dev_major_handle,
+						   (void **) id_pp);
+		if (count > 0) {
+			u_int i;
+			struct rsbac_dev_desc_t *tmp_p;
+
+			tmp_p = *id_pp;
+			for (i = 0; i < count; i++)
+				tmp_p[i].type += (D_block_major - D_block);
+		}
+		return count;
+	} else
+		return rsbac_ta_list_lol_count(ta_number,
+					       dev_major_handle);
+}
+
+int rsbac_acl_list_all_user(rsbac_list_ta_number_t ta_number,
+			    rsbac_uid_t ** id_pp)
+{
+	if (id_pp)
+		return rsbac_ta_list_lol_get_all_desc(ta_number, u_handle,
+						      (void **) id_pp);
+	else
+		return rsbac_ta_list_lol_count(ta_number, u_handle);
+}
+
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+int rsbac_acl_list_all_group(rsbac_list_ta_number_t ta_number,
+			     rsbac_gid_t ** id_pp)
+{
+	if (id_pp)
+		return rsbac_ta_list_lol_get_all_desc(ta_number, g_handle,
+						      (void **) id_pp);
+	else
+		return rsbac_ta_list_lol_count(ta_number, g_handle);
+}
+#endif
+
+/********************************************/
+/* remove user from all groups and all ACLs */
+int rsbac_acl_remove_user(rsbac_list_ta_number_t ta_number,
+			  rsbac_uid_t user)
+{
+	u_long i;
+	struct rsbac_acl_group_entry_t *entry_p;
+	long desc_count;
+	struct rsbac_acl_entry_desc_t desc;
+
+	rsbac_ta_list_lol_remove(ta_number, gm_handle, &user);
+	/* traverse groups for this owner */
+	desc_count =
+	    rsbac_ta_list_get_all_data(ta_number, group_handle,
+				       (void **) &entry_p);
+	if (desc_count > 0) {
+		for (i = 0; i < desc_count; i++) {
+			if (entry_p[i].owner == user) {
+				rsbac_ta_list_remove(ta_number,
+						     group_handle,
+						     &entry_p[i].id);
+				/* cleanup group memberships */
+				rsbac_ta_list_lol_subremove_from_all
+				    (ta_number, gm_handle, &entry_p[i].id);
+			}
+		}
+		rsbac_kfree(entry_p);
+	}
+
+	desc.subj_type = ACLS_USER;
+	desc.subj_id = user;
+
+	return rsbac_acl_remove_subject(ta_number, desc);
+}
diff --git a/rsbac/data_structures/auth_data_structures.c b/rsbac/data_structures/auth_data_structures.c
new file mode 100644
index 0000000..76cb7f6
--- /dev/null
+++ b/rsbac/data_structures/auth_data_structures.c
@@ -0,0 +1,4071 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of AUTH data structures            */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 25/Jan/2016                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/auth_data_structures.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/auth.h>
+#include <rsbac/lists.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/getname.h>
+#include <linux/string.h>
+#include <linux/srcu.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+/* The following global variables are needed for access to AUTH data.       */
+
+static struct rsbac_auth_device_list_head_t * device_list_head_p;
+static spinlock_t device_list_lock;
+static struct srcu_struct device_list_srcu;
+static struct lock_class_key device_list_lock_class;
+
+static rsbac_list_handle_t process_handle = NULL;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+static rsbac_list_handle_t process_eff_handle = NULL;
+static rsbac_list_handle_t process_fs_handle = NULL;
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+static rsbac_list_handle_t process_group_handle = NULL;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+static rsbac_list_handle_t process_group_eff_handle = NULL;
+static rsbac_list_handle_t process_group_fs_handle = NULL;
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+rsbac_list_ta_number_t auth_learn_ta = CONFIG_RSBAC_AUTH_LEARN_TA;
+#else
+rsbac_list_ta_number_t auth_learn_ta = 0;
+#endif
+#endif
+
+static struct kmem_cache * auth_device_item_slab = NULL;
+
+/**************************************************/
+/*       Declarations of external functions       */
+/**************************************************/
+
+rsbac_boolean_t writable(struct super_block *sb_p);
+
+/**************************************************/
+/*       Declarations of internal functions       */
+/**************************************************/
+
+/************************************************* */
+/*               Internal Help functions           */
+/************************************************* */
+
+static u_int nr_fd_hash_bits = RSBAC_AUTH_NR_CAP_FD_LIST_HASH_BITS;
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+static u_int nr_eff_fd_hash_bits = RSBAC_AUTH_NR_CAP_EFF_FD_LIST_HASH_BITS;
+static u_int nr_fs_fd_hash_bits = RSBAC_AUTH_NR_CAP_FS_FD_LIST_HASH_BITS;
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+static u_int nr_group_fd_hash_bits = RSBAC_AUTH_NR_CAP_GROUP_FD_LIST_HASH_BITS;
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+static u_int nr_group_eff_fd_hash_bits = RSBAC_AUTH_NR_CAP_GROUP_EFF_FD_LIST_HASH_BITS;
+static u_int nr_group_fs_fd_hash_bits = RSBAC_AUTH_NR_CAP_GROUP_FS_FD_LIST_HASH_BITS;
+#endif
+#endif
+
+static int cap_compare(void *desc1, void *desc2)
+{
+	struct rsbac_auth_cap_range_t *range1 = desc1;
+	struct rsbac_auth_cap_range_t *range2 = desc2;
+
+	if (!desc1 || !desc2)
+		return 0;
+	if (range1->first < range2->first)
+		return -1;
+	if (range1->first > range2->first)
+		return 1;
+	if (range1->last < range2->last)
+		return -1;
+	if (range1->last > range2->last)
+		return 1;
+	return 0;
+}
+
+static int single_cap_compare(void *desc1, void *desc2)
+{
+	struct rsbac_auth_cap_range_t *range = desc1;
+	rsbac_uid_t *uid = desc2;
+
+	if (!desc1 || !desc2)
+		return 0;
+	if ((*uid < range->first)
+	    || (*uid > range->last)
+	    )
+		return 1;
+	else
+		return 0;
+}
+
+static int auth_subconv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_auth_cap_range_t *tmp_new_desc = new_desc;
+        struct rsbac_auth_old_cap_range_t *tmp_old_desc = old_desc;
+
+        tmp_new_desc->first = tmp_old_desc->first;
+        tmp_new_desc->last = tmp_old_desc->last;
+	return 0;
+}
+
+static rsbac_list_conv_function_t *auth_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_AUTH_FD_OLD_LIST_VERSION:
+		return auth_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static int auth_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *auth_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_AUTH_FD_OLD_LIST_VERSION:
+		return auth_conv;
+	default:
+		return NULL;
+	}
+}
+
+
+/* auth_register_fd_lists() */
+/* register fd ACL lists for device */
+
+static int auth_register_fd_lists(struct rsbac_auth_device_list_item_t
+				  *device_p, kdev_t kdev)
+{
+	int err = 0;
+	int tmperr;
+	struct rsbac_list_lol_info_t lol_info;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	lol_info.version = RSBAC_AUTH_FD_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size =
+	    sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					 NULL,
+					 cap_compare,
+					 auth_get_conv, auth_get_subconv,
+					 NULL, NULL,
+					 RSBAC_AUTH_FD_FILENAME, kdev,
+					 nr_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_AUTH_FD_OLD_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	/* register all the AUTH DAC lists of lists */
+	lol_info.version = RSBAC_AUTH_FD_EFF_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size =
+	    sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->eff_handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					 NULL,
+					 cap_compare,
+					 auth_get_conv, auth_get_subconv,
+					 NULL, NULL,
+					 RSBAC_AUTH_FD_EFF_FILENAME, kdev,
+					 nr_eff_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_AUTH_FD_OLD_EFF_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_EFF_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	lol_info.version = RSBAC_AUTH_FD_FS_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size =
+	    sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->fs_handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					 NULL,
+					 cap_compare,
+					 auth_get_conv, auth_get_subconv,
+					 NULL, NULL,
+					 RSBAC_AUTH_FD_FS_FILENAME, kdev,
+					 nr_fs_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_AUTH_FD_OLD_FS_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_FS_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	lol_info.version = RSBAC_AUTH_FD_GROUP_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size =
+	    sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->group_handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					 NULL,
+					 cap_compare,
+					 auth_get_conv, auth_get_subconv,
+					 NULL, NULL,
+					 RSBAC_AUTH_FD_GROUP_FILENAME, kdev,
+					 nr_group_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_AUTH_FD_OLD_GROUP_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_GROUP_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	lol_info.version = RSBAC_AUTH_FD_GROUP_EFF_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size =
+	    sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->group_eff_handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					 NULL,
+					 cap_compare,
+					 auth_get_conv, auth_get_subconv,
+					 NULL, NULL,
+					 RSBAC_AUTH_FD_GROUP_EFF_FILENAME, kdev,
+					 nr_group_eff_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_AUTH_FD_OLD_GROUP_EFF_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_GROUP_EFF_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	lol_info.version = RSBAC_AUTH_FD_GROUP_FS_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size =
+	    sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->group_fs_handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE,
+					 NULL,
+					 cap_compare,
+					 auth_get_conv, auth_get_subconv,
+					 NULL, NULL,
+					 RSBAC_AUTH_FD_GROUP_FS_FILENAME, kdev,
+					 nr_group_fs_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_AUTH_FD_OLD_GROUP_FS_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_GROUP_FS_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+#endif				/* AUTH_GROUP */
+
+	return err;
+}
+
+/* auth_detach_fd_lists() */
+/* detach from fd AUTH lists for device */
+
+static int auth_detach_fd_lists(struct rsbac_auth_device_list_item_t
+				*device_p)
+{
+	int err = 0;
+	int tmperr;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	/* detach all the AUTH lists of lists */
+	tmperr = rsbac_list_lol_detach(&device_p->handle,
+					       RSBAC_AUTH_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	tmperr = rsbac_list_lol_detach(&device_p->eff_handle,
+					  RSBAC_AUTH_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_EFF_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	tmperr = rsbac_list_lol_detach(&device_p->fs_handle,
+					  RSBAC_AUTH_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_FS_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	tmperr = rsbac_list_lol_detach(&device_p->group_handle,
+					  RSBAC_AUTH_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_GROUP_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	tmperr = rsbac_list_lol_detach(&device_p->group_eff_handle,
+					  RSBAC_AUTH_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_GROUP_EFF_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	tmperr = rsbac_list_lol_detach(&device_p->group_fs_handle,
+					  RSBAC_AUTH_LIST_KEY);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "auth_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_AUTH_FD_GROUP_FS_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+#endif
+#endif				/* AUTH_GROUP */
+
+	return err;
+}
+
+/************************************************************************** */
+/* The lookup functions return NULL, if the item is not found, and a        */
+/* pointer to the item otherwise.                                           */
+
+/* first the device item lookup */
+static struct rsbac_auth_device_list_item_t *lookup_device(kdev_t kdev)
+{
+        struct rsbac_auth_device_list_head_t *head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	struct rsbac_auth_device_list_item_t *curr = srcu_dereference(head_p->curr, &device_list_srcu);
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!(curr && (RSBAC_MAJOR(curr->id) == RSBAC_MAJOR(kdev))
+	      && (RSBAC_MINOR(curr->id) == RSBAC_MINOR(kdev))
+	    )
+	    ) {
+		curr = srcu_dereference(head_p->head, &device_list_srcu);
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = srcu_dereference(curr->next, &device_list_srcu);
+		}
+		if (curr)
+			device_list_head_p->curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_auth_device_list_item_t *lookup_device_locked(kdev_t kdev)
+{
+	struct rsbac_auth_device_list_item_t *curr = device_list_head_p->curr;
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!(curr && (RSBAC_MAJOR(curr->id) == RSBAC_MAJOR(kdev))
+	      && (RSBAC_MINOR(curr->id) == RSBAC_MINOR(kdev))
+	    )
+	    ) {
+		curr = device_list_head_p->head;
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = curr->next;
+		}
+		if (curr)
+			device_list_head_p->curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/************************************************************************** */
+/* The add_item() functions add an item to the list, set head.curr to it,   */
+/* and return a pointer to the item.                                        */
+/* These functions will NOT check, if there is already an item under the    */
+/* same ID! If this happens, the lookup functions will return the old item! */
+/* All list manipulation is protected by rw-spinlocks to prevent inconsistency */
+/* and undefined behaviour in other concurrent functions.                   */
+
+/* Create a device item without adding to list. No locking needed. */
+static struct rsbac_auth_device_list_item_t
+*create_device_item(kdev_t kdev)
+{
+	struct rsbac_auth_device_list_item_t *new_item_p;
+
+	/* allocate memory for new device, return NULL, if failed */
+	if (!(new_item_p = rsbac_smalloc_clear_unlocked(auth_device_item_slab)))
+		return NULL;
+
+	new_item_p->id = kdev;
+	new_item_p->mount_count = 1;
+	return new_item_p;
+}
+
+/* Add an existing device item to list. Locking needed. */
+static struct rsbac_auth_device_list_item_t
+*add_device_item(struct rsbac_auth_device_list_item_t *device_p)
+{
+	struct rsbac_auth_device_list_head_t * new_p;
+	struct rsbac_auth_device_list_head_t * old_p;
+
+	if (!device_p)
+		return NULL;
+
+	spin_lock(&device_list_lock);
+	old_p = device_list_head_p;
+	new_p = rsbac_kmalloc(sizeof(*new_p));
+	*new_p = *old_p;
+	/* add new device to device list */
+	if (!new_p->head) {	/* first device */
+		new_p->head = device_p;
+		new_p->tail = device_p;
+		new_p->curr = device_p;
+		new_p->count = 1;
+		device_p->prev = NULL;
+		device_p->next = NULL;
+	} else {		/* there is another device -> hang to tail */
+		device_p->prev = new_p->tail;
+		device_p->next = NULL;
+		new_p->tail->next = device_p;
+		new_p->tail = device_p;
+		new_p->curr = device_p;
+		new_p->count++;
+	}
+	rcu_assign_pointer(device_list_head_p, new_p);
+	spin_unlock(&device_list_lock);
+	synchronize_srcu(&device_list_srcu);
+	rsbac_kfree(old_p);
+	return device_p;
+}
+
+/************************************************************************** */
+/* The remove_item() functions remove an item from the list. If this item   */
+/* is head, tail or curr, these pointers are set accordingly.               */
+/* To speed up removing several subsequent items, curr is set to the next   */
+/* item, if possible.                                                       */
+/* If the item is not found, nothing is done.                               */
+
+static void clear_device_item(struct rsbac_auth_device_list_item_t *item_p)
+{
+	if (!item_p)
+		return;
+
+	auth_detach_fd_lists(item_p);
+	rsbac_sfree(auth_device_item_slab, item_p);
+}
+
+static void remove_device_item(kdev_t kdev)
+{
+	struct rsbac_auth_device_list_item_t *item_p;
+	struct rsbac_auth_device_list_head_t * new_p;
+	struct rsbac_auth_device_list_head_t * old_p;
+     
+	old_p = device_list_head_p;
+	new_p = rsbac_kmalloc(sizeof(*new_p));
+	*new_p = *old_p;
+	/* first we must locate the item. */
+	if ((item_p = lookup_device_locked(kdev))) {	/* ok, item was found */
+		if (new_p->head == item_p) {	/* item is head */
+			if (new_p->tail == item_p) {	/* item is head and tail = only item -> list will be empty */
+				new_p->head = NULL;
+				new_p->tail = NULL;
+			} else {	/* item is head, but not tail -> next item becomes head */
+				item_p->next->prev = NULL;
+				new_p->head = item_p->next;
+			}
+		} else {	/* item is not head */
+			if (new_p->tail == item_p) {	/*item is not head, but tail -> previous item becomes tail */
+				item_p->prev->next = NULL;
+				new_p->tail = item_p->prev;
+			} else {	/* item is neither head nor tail -> item is cut out */
+				item_p->prev->next = item_p->next;
+				item_p->next->prev = item_p->prev;
+			}
+		}
+
+		/* curr is no longer valid -> reset.                              */
+		new_p->curr = NULL;
+		/* adjust counter */
+		new_p->count--;
+		rcu_assign_pointer(device_list_head_p, new_p);
+		spin_unlock(&device_list_lock);
+		synchronize_srcu(&device_list_srcu);
+		rsbac_kfree(old_p);
+
+		/* now we can remove the item from memory. This means cleaning up */
+		/* everything below. */
+		clear_device_item(item_p);
+	}			/* end of if: item was found */
+	else
+		spin_unlock(&device_list_lock);
+}
+
+/************************************************************************** */
+/* The copy_fp_cap_set_item() function copies a file cap set to a process   */
+/* cap set */
+
+static int copy_fp_cap_set_item(struct rsbac_auth_device_list_item_t
+				*device_p, rsbac_auth_file_t file,
+				rsbac_pid_t pid)
+{
+	struct rsbac_auth_cap_range_t *cap_item_p;
+	rsbac_time_t *ttl_p;
+	int i;
+	long count;
+	enum rsbac_target_t target = T_FILE;
+	union rsbac_target_id_t tid;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	rsbac_list_lol_remove(process_handle, &pid);
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->handle,
+					       &inode_nr,
+					       (void **) &cap_item_p,
+					       &ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+			inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->handle,
+							       &inode_nr,
+							       (void **) &cap_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_handle,
+						  ttl_p[i],
+						  &pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	rsbac_list_lol_remove(process_eff_handle, &pid);
+	inode_nr = file.inode;
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->eff_handle,
+					       &inode_nr,
+					       (void **) &cap_item_p,
+					       &ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+			inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->eff_handle,
+							       &inode_nr,
+							       (void **)
+							       &cap_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_eff_handle,
+						  ttl_p[i],
+						  &pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+	rsbac_list_lol_remove(process_fs_handle, &pid);
+	inode_nr = file.inode;
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->fs_handle,
+					       &inode_nr,
+					       (void **) &cap_item_p,
+					       &ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+			inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->fs_handle,
+							       &inode_nr,
+							       (void **)
+							       &cap_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_fs_handle,
+						  ttl_p[i],
+						  &pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	rsbac_list_lol_remove(process_group_handle, &pid);
+	inode_nr = file.inode;
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->
+					       group_handle,
+					       &inode_nr,
+					       (void **) &cap_item_p,
+					       &ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+			inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->group_handle,
+							       &inode_nr,
+							       (void **)
+							       &cap_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_group_handle,
+						  ttl_p[i],
+						  &pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	rsbac_list_lol_remove(process_group_eff_handle, &pid);
+	inode_nr = file.inode;
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->group_eff_handle,
+						&inode_nr,
+						(void **) &cap_item_p,
+						&ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+			inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->group_eff_handle,
+							       &inode_nr,
+							       (void **)
+							       &cap_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_group_eff_handle,
+						  ttl_p[i],
+						  &pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+	rsbac_list_lol_remove(process_group_fs_handle, &pid);
+	inode_nr = file.inode;
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->group_fs_handle,
+						&inode_nr,
+						(void **) &cap_item_p,
+						&ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+			inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->group_fs_handle,
+							       &inode_nr,
+							       (void **)
+							       &cap_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_group_fs_handle,
+						  ttl_p[i],
+						  &pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+#endif
+#endif				/* AUTH_GROUP */
+
+	return 0;
+}				/* end of copy_fp_cap_set_item() */
+
+/************************************************************************** */
+/* The copy_pp_cap_set_item() function copies a process cap set to another  */
+
+static int copy_pp_cap_set_item_handle(rsbac_list_handle_t handle,
+				       rsbac_pid_t old_pid,
+				       rsbac_pid_t new_pid)
+{
+	struct rsbac_auth_cap_range_t *cap_item_p;
+	rsbac_time_t *ttl_p;
+	int i;
+	long count;
+
+	rsbac_list_lol_remove(handle, &new_pid);
+	count = rsbac_list_lol_get_all_subdesc_ttl(handle,
+						   &old_pid,
+						   (void **) &cap_item_p,
+						   &ttl_p);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(handle,
+						  ttl_p[i],
+						  &new_pid,
+						  &cap_item_p[i], NULL);
+		}
+		rsbac_kfree(cap_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if (count < 0)
+			return count;
+	}
+	return 0;
+}
+
+static int copy_pp_cap_set_item(rsbac_pid_t old_pid, rsbac_pid_t new_pid)
+{
+	int res;
+
+	res =
+	    copy_pp_cap_set_item_handle(process_handle, old_pid, new_pid);
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	if (res)
+		return res;
+	res =
+	    copy_pp_cap_set_item_handle(process_eff_handle, old_pid,
+					new_pid);
+	if (res)
+		return res;
+	res =
+	    copy_pp_cap_set_item_handle(process_fs_handle, old_pid,
+					new_pid);
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	res =
+	    copy_pp_cap_set_item_handle(process_group_handle, old_pid,
+					new_pid);
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	if (res)
+		return res;
+	res =
+	    copy_pp_cap_set_item_handle(process_group_eff_handle, old_pid,
+					new_pid);
+	if (res)
+		return res;
+	res =
+	    copy_pp_cap_set_item_handle(process_group_fs_handle, old_pid,
+					new_pid);
+#endif
+#endif
+
+	return res;
+}				/* end of copy_pp_cap_set_item() */
+
+/************************************************* */
+/*               proc functions                    */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+static int
+auth_devices_proc_show(struct seq_file *m, void *v)
+{
+        struct rsbac_auth_device_list_head_t *head_p;
+	struct rsbac_auth_device_list_item_t *device_p;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized())
+		return -ENOSYS;
+
+	seq_printf(m,
+		    "%u RSBAC AUTH Devices\n--------------------\n",
+		    device_list_head_p->count);
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+        head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	for (device_p = srcu_dereference(head_p->head, &device_list_srcu); device_p;
+	     device_p = srcu_dereference(device_p->next, &device_list_srcu)) {
+		seq_printf(m,
+			    "%02u:%02u with mount_count = %u\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id),
+			    device_p->mount_count);
+	}
+
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int auth_devices_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, auth_devices_proc_show, NULL);
+}
+
+static const struct file_operations auth_devices_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = auth_devices_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *auth_devices;
+
+static int
+stats_auth_proc_show(struct seq_file *m, void *v)
+{
+	u_int cap_set_count = 0;
+	u_int member_count = 0;
+        struct rsbac_auth_device_list_head_t *head_p;
+	struct rsbac_auth_device_list_item_t *device_p;
+	int srcu_idx;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "stats_auth_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_auth, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "AUTH Status\n-----------\n");
+
+	seq_printf(m,
+		    "%lu process cap set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_handle),
+		    rsbac_list_lol_all_subcount(process_handle));
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	seq_printf(m,
+		    "%lu process eff cap set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_eff_handle),
+		    rsbac_list_lol_all_subcount(process_eff_handle));
+	seq_printf(m,
+		    "%lu process fs cap set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_fs_handle),
+		    rsbac_list_lol_all_subcount(process_fs_handle));
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	seq_printf(m,
+		    "%lu process group cap set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_group_handle),
+		    rsbac_list_lol_all_subcount(process_group_handle));
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	seq_printf(m,
+		    "%lu process group eff cap set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_group_eff_handle),
+		    rsbac_list_lol_all_subcount(process_group_eff_handle));
+	seq_printf(m,
+		    "%lu process group fs cap set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_group_fs_handle),
+		    rsbac_list_lol_all_subcount(process_group_fs_handle));
+#endif
+#endif				/* AUTH_GROUP */
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+        head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		/* reset counters */
+		cap_set_count = rsbac_list_lol_count(device_p->handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->handle);
+		seq_printf(m,
+			    "device %02u:%02u has %u file cap set items, sum of %u members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), cap_set_count,
+			    member_count);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+		cap_set_count = rsbac_list_lol_count(device_p->eff_handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->eff_handle);
+		seq_printf(m,
+			    "device %02u:%02u has %u file eff cap set items, sum of %u members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), cap_set_count,
+			    member_count);
+		cap_set_count = rsbac_list_lol_count(device_p->fs_handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->fs_handle);
+		seq_printf(m,
+			    "device %02u:%02u has %u file fs cap set items, sum of %u members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), cap_set_count,
+			    member_count);
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+		cap_set_count = rsbac_list_lol_count(device_p->group_handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->group_handle);
+		seq_printf(m,
+			    "device %02u:%02u has %u file group cap set items, sum of %u members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), cap_set_count,
+			    member_count);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+		cap_set_count = rsbac_list_lol_count(device_p->group_eff_handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->group_eff_handle);
+		seq_printf(m,
+			    "device %02u:%02u has %u file group eff cap set items, sum of %u members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), cap_set_count,
+			    member_count);
+		cap_set_count = rsbac_list_lol_count(device_p->group_fs_handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->group_fs_handle);
+		seq_printf(m,
+			    "device %02u:%02u has %u file group fs cap set items, sum of %u members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), cap_set_count,
+			    member_count);
+#endif
+#endif				/* AUTH_GROUP */
+
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int stats_auth_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_auth_proc_show, NULL);
+}
+
+static const struct file_operations stats_auth_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = stats_auth_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *stats_auth;
+
+static int
+auth_caplist_proc_show(struct seq_file *m, void *v)
+{
+	u_int count = 0;
+	u_int member_count = 0;
+	u_long all_count;
+	u_long all_member_count;
+	int i, j;
+        struct rsbac_auth_device_list_head_t *head_p;
+	struct rsbac_auth_device_list_item_t *device_p;
+	rsbac_pid_t *p_list;
+	rsbac_old_inode_nr_t *f_list;
+	struct rsbac_auth_cap_range_t *cap_list;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "auth_caplist_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_auth, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "AUTH Cap Lists\n--------------\n");
+
+	seq_printf(m,
+		    "Process capabilities:\nset-id  count   cap-members");
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc(process_handle,
+							   &p_list[i],
+							   (void **)
+							   &cap_list);
+			seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						   seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+				}
+				rsbac_kfree(cap_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n%u process cap set items, sum of %lu members\n",
+		    count, all_member_count);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	seq_printf(m,
+		    "\nProcess eff capabilities:\nset-id  count   cap-members");
+
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_eff_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (process_eff_handle, &p_list[i],
+			     (void **) &cap_list);
+			seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+				}
+				rsbac_kfree(cap_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n%u process eff cap set items, sum of %lu members\n",
+		    count, all_member_count);
+	seq_printf(m,
+		    "\nProcess fs capabilities:\nset-id  count   cap-members");
+
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_fs_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (process_fs_handle, &p_list[i],
+			     (void **) &cap_list);
+			seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						   seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+				}
+				rsbac_kfree(cap_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n\n%u process fs cap set items, sum of %lu members\n",
+		    count, all_member_count);
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	seq_printf(m,
+		    "\nProcess group capabilities:\nset-id  count   cap-members");
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_group_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (process_group_handle, &p_list[i],
+			     (void **) &cap_list);
+			    seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+				}
+				rsbac_kfree(cap_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n%u process group cap set items, sum of %lu members\n",
+		    count, all_member_count);
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	seq_printf(m,
+		    "\nProcess group eff capabilities:\nset-id  count   cap-members");
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_group_eff_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (process_group_eff_handle, &p_list[i],
+			     (void **) &cap_list);
+			seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+				}
+				rsbac_kfree(cap_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n%u process group eff cap set items, sum of %lu members\n",
+		    count, all_member_count);
+	seq_printf(m,
+		    "\nProcess group fs capabilities:\nset-id  count   cap-members");
+
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_group_fs_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc
+			    (process_group_fs_handle, &p_list[i],
+			     (void **) &cap_list);
+			    seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+				}
+				rsbac_kfree(cap_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n\n%u process group fs cap set items, sum of %lu members\n",
+		    count, all_member_count);
+#endif
+#endif				/* AUTH_GROUP */
+
+	seq_printf(m,
+		    "\nFile capabilities:\nset-id  count   cap-members");
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+        head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		/* reset counters */
+		all_member_count = 0;
+		all_count = 0;
+		count = rsbac_list_lol_get_all_desc(device_p->handle,
+							(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+					    (device_p->handle,
+					     &f_list[i],
+					     (void **) &cap_list);
+				seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+						if (cap_list[j].
+						    first !=
+						    cap_list[j].
+						    last) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						    if (RSBAC_UID_SET(cap_list[j].first)
+						        || RSBAC_UID_SET(cap_list[j].last)
+						       )
+						          seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						    else
+#endif
+							  seq_printf
+							    (m,
+							     "%u:%u ",
+							     RSBAC_UID_NUM(cap_list[j].first),
+							     RSBAC_UID_NUM(cap_list[j].last));
+						} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+							if (RSBAC_UID_SET(cap_list[j].first))
+							    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+							else
+#endif
+							  seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+						}
+					}
+					rsbac_kfree(cap_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+			all_count += count;
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %lu file cap set items, sum of %lu members, list is clean\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), all_count,
+			    all_member_count);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+		all_member_count = 0;
+		all_count = 0;
+		count =
+		    rsbac_list_lol_get_all_desc(device_p->eff_handle,
+						(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->eff_handle,
+				     &f_list[i],
+				     (void **) &cap_list);
+				    seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+					}
+					rsbac_kfree(cap_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+			all_count += count;
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %lu file eff cap set items, sum of %lu members, list is clean\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), all_count,
+			    all_member_count);
+		all_member_count = 0;
+		all_count = 0;
+		count =
+		    rsbac_list_lol_get_all_desc(device_p->
+						fs_handle,
+						(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->fs_handle,
+				     &f_list[i],
+				     (void **) &cap_list);
+				    seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+					}
+					rsbac_kfree(cap_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+			all_count += count;
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %lu file fs cap set items, sum of %lu members, list is clean\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), all_count,
+			    all_member_count);
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+		all_member_count = 0;
+		all_count = 0;
+		count =
+		    rsbac_list_lol_get_all_desc(device_p->
+						group_handle,
+						(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->group_handle,
+				     &f_list[i],
+				     (void **) &cap_list);
+				seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+					}
+					rsbac_kfree(cap_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+			all_count += count;
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %lu file group cap set items, sum of %lu members, list is clean\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), all_count,
+			    all_member_count);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+		all_member_count = 0;
+		all_count = 0;
+		count = rsbac_list_lol_get_all_desc(device_p->
+						group_eff_handle,
+						(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->group_eff_handle,
+				     &f_list[i],
+				     (void **) &cap_list);
+				seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+					}
+					rsbac_kfree(cap_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+			all_count += count;
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %lu file group eff cap set items, sum of %lu members, list is clean\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), all_count,
+			    all_member_count);
+		all_member_count = 0;
+		all_count = 0;
+		count = rsbac_list_lol_get_all_desc(device_p->
+						group_fs_handle,
+						(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->group_fs_handle,
+				     &f_list[i],
+				     (void **) &cap_list);
+				seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+					if (cap_list[j].first !=
+					    cap_list[j].last) {
+					    
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first)
+						    || RSBAC_UID_SET(cap_list[j].last)
+						   )
+						    seq_printf(m,
+							    "%u/%u:%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_SET(cap_list[j].last),
+							    RSBAC_UID_NUM(cap_list[j].last));
+						else
+#endif
+						    seq_printf(m,
+							    "%u:%u ",
+							    RSBAC_UID_NUM(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].last));
+					} else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+						if (RSBAC_UID_SET(cap_list[j].first))
+						    seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(cap_list[j].first),
+							    RSBAC_UID_NUM(cap_list[j].first));
+						else
+#endif
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(cap_list[j].first));
+					}
+					}
+					rsbac_kfree(cap_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+			all_count += count;
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %lu file group fs cap set items, sum of %lu members, list is clean\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), all_count,
+			    all_member_count);
+#endif
+#endif				/* AUTH_GROUP */
+
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int auth_caplist_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, auth_caplist_proc_show, NULL);
+}
+
+static const struct file_operations auth_caplist_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = auth_caplist_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *auth_caplist;
+#endif				/* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */
+
+/************************************************* */
+/*               Init functions                    */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac/error.h.                 */
+
+/************************************************************************** */
+/* Initialization of all AUTH data structures. After this call, all AUTH    */
+/* data is kept in memory for performance reasons, but is written to disk   */
+/* on every change. */
+
+/* Because there can be no access to aci data structures before init,       */
+/* rsbac_init_auth() will initialize all rw-spinlocks to unlocked.          */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_auth(void)
+#else
+int __init rsbac_init_auth(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_auth_device_list_item_t *device_p = NULL;
+	struct rsbac_list_lol_info_t lol_info;
+
+	if (rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_init_auth(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+
+	rsbac_printk(KERN_INFO "rsbac_init_auth(): Initializing RSBAC: AUTH subsystem\n");
+
+	lol_info.version = RSBAC_AUTH_P_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &process_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      cap_compare,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_AUTH_P_LIST_NAME,
+				      RSBAC_AUTO_DEV,
+				      RSBAC_LIST_MIN_MAX_HASH_BITS,
+				      rsbac_list_hash_pid,
+				      NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_auth(): Registering AUTH process cap list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	lol_info.version = RSBAC_AUTH_P_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &process_eff_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      cap_compare,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_AUTH_P_EFF_LIST_NAME,
+				      RSBAC_AUTO_DEV,
+				      RSBAC_LIST_MIN_MAX_HASH_BITS,
+				      rsbac_list_hash_pid,
+				      NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_auth(): Registering AUTH process eff cap list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+	lol_info.version = RSBAC_AUTH_P_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &process_fs_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      cap_compare,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_AUTH_P_FS_LIST_NAME,
+				      RSBAC_AUTO_DEV,
+				      RSBAC_LIST_MIN_MAX_HASH_BITS,
+				      rsbac_list_hash_pid,
+				      NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_auth(): Registering AUTH process fs cap list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	lol_info.version = RSBAC_AUTH_P_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &process_group_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      cap_compare,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_AUTH_P_GROUP_LIST_NAME,
+				      RSBAC_AUTO_DEV,
+				      RSBAC_LIST_MIN_MAX_HASH_BITS,
+				      rsbac_list_hash_pid,
+				      NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_auth(): Registering AUTH process group cap list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	lol_info.version = RSBAC_AUTH_P_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &process_group_eff_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      cap_compare,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_AUTH_P_GROUP_EFF_LIST_NAME,
+				      RSBAC_AUTO_DEV,
+				      RSBAC_LIST_MIN_MAX_HASH_BITS,
+				      rsbac_list_hash_pid,
+				      NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_auth(): Registering AUTH process group eff cap list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+	lol_info.version = RSBAC_AUTH_P_LIST_VERSION;
+	lol_info.key = RSBAC_AUTH_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(struct rsbac_auth_cap_range_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &process_group_fs_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA | RSBAC_LIST_AUTO_HASH_RESIZE | RSBAC_LIST_OWN_SLAB,
+				      NULL,
+				      cap_compare,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_AUTH_P_GROUP_FS_LIST_NAME,
+				      RSBAC_AUTO_DEV,
+				      RSBAC_LIST_MIN_MAX_HASH_BITS,
+				      rsbac_list_hash_pid,
+				      NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_auth(): Registering AUTH process group fs cap list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+#endif
+#endif				/* AUTH_GROUP */
+
+	auth_device_item_slab = rsbac_slab_create_rcu("rsbac_auth_device_item",
+					sizeof(struct rsbac_auth_device_list_item_t));
+
+	/* Init FD lists */
+	device_list_head_p = kmalloc(sizeof(*device_list_head_p), GFP_KERNEL);
+	if (!device_list_head_p) {
+		rsbac_printk(KERN_WARNING
+			"rsbac_init_auth(): Failed to allocate device_list_head\n");
+		return -ENOMEM;
+	}
+	spin_lock_init(&device_list_lock);
+	init_srcu_struct(&device_list_srcu);
+	lockdep_set_class(&device_list_lock, &device_list_lock_class);
+	device_list_head_p->head = NULL;
+	device_list_head_p->tail = NULL;
+	device_list_head_p->curr = NULL;
+	device_list_head_p->count = 0;
+
+	/* read all data */
+	rsbac_pr_debug(ds_auth, "rsbac_init_auth(): Registering FD lists\n");
+	device_p = create_device_item(rsbac_root_dev);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_init_auth(): Could not add device!\n");
+		return -RSBAC_ECOULDNOTADDDEVICE;
+	}
+	if ((err = auth_register_fd_lists(device_p, rsbac_root_dev))) {
+		char tmp[RSBAC_MAXNAMELEN];
+
+		rsbac_printk(KERN_WARNING "rsbac_init_auth(): File/Dir cap set registration failed for dev %02u:%02u, err %s!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev),
+			     get_error_name(tmp, err));
+	}
+	device_p = add_device_item(device_p);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_init_auth(): Could not add device!\n");
+		return -RSBAC_ECOULDNOTADDDEVICE;
+	}
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+	auth_devices = proc_create("auth_devices",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p,
+					&auth_devices_proc_fops);
+	stats_auth = proc_create("stats_auth",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p,
+					&stats_auth_proc_fops);
+	auth_caplist = proc_create("auth_caplist",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p,
+					&auth_caplist_proc_fops);
+#endif
+
+	rsbac_pr_debug(ds_auth, "Ready.\n");
+	return err;
+}
+
+int rsbac_mount_auth(kdev_t kdev)
+{
+	int err = 0;
+	struct rsbac_auth_device_list_item_t *device_p;
+	struct rsbac_auth_device_list_item_t *new_device_p;
+	int srcu_idx;
+
+	rsbac_pr_debug(ds_auth, "mounting device %02u:%02u\n",
+		       RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(kdev);
+	/* repeated mount? */
+	if (device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mount_auth: repeated mount %u of device %02u:%02u\n",
+			     device_p->mount_count, RSBAC_MAJOR(kdev),
+			     RSBAC_MINOR(kdev));
+		device_p->mount_count++;
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return 0;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	new_device_p = create_device_item(kdev);
+	if (!new_device_p)
+		return -RSBAC_ECOULDNOTADDDEVICE;
+
+	/* register lists */
+	if ((err = auth_register_fd_lists(new_device_p, kdev))) {
+		char tmp[RSBAC_MAXNAMELEN];
+
+		rsbac_printk(KERN_WARNING "rsbac_mount_auth(): File/Dir ACL registration failed for dev %02u:%02u, err %s!\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev),
+			     get_error_name(tmp, err));
+	}
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	/* make sure to only add, if this device item has not been added in the meantime */
+	device_p = lookup_device(kdev);
+	if (device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mount_auth(): mount race for device %02u:%02u detected!\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+		device_p->mount_count++;
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		clear_device_item(new_device_p);
+	} else {
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		device_p = add_device_item(new_device_p);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_mount_auth: adding device %02u:%02u failed!\n",
+				     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+			clear_device_item(new_device_p);
+			err = -RSBAC_ECOULDNOTADDDEVICE;
+		}
+	}
+	return err;
+}
+
+/* When umounting a device, its file cap set list must be removed. */
+
+int rsbac_umount_auth(kdev_t kdev)
+{
+	struct rsbac_auth_device_list_item_t *device_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_umount(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(ds_auth, "umounting device %02u:%02u\n",
+		       RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+	/* sync of attribute lists was done in rsbac_umount */
+	spin_lock(&device_list_lock);
+	device_p = lookup_device_locked(kdev);
+	if (device_p) {
+		if (device_p->mount_count == 1)
+			remove_device_item(kdev);
+		else {
+			if (device_p->mount_count > 1) {
+				device_p->mount_count--;
+				spin_unlock(&device_list_lock);
+			} else {
+				spin_unlock(&device_list_lock);
+				rsbac_printk(KERN_WARNING "rsbac_mount_auth: device %02u:%02u has mount_count < 1!\n",
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev));
+			}
+		}
+	}
+	else
+		spin_unlock(&device_list_lock);
+	return 0;
+}
+
+/***************************************************/
+/* We also need some status information...         */
+
+int rsbac_stats_auth(void)
+{
+	u_int cap_set_count = 0;
+	u_int member_count = 0;
+        struct rsbac_auth_device_list_head_t *head_p;
+	struct rsbac_auth_device_list_item_t *device_p;
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_stats_auth(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_auth, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	rsbac_printk(KERN_INFO "AUTH Status\n-----------\n");
+
+	rsbac_printk(KERN_INFO "%lu process cap set items, sum of %lu members\n",
+		     rsbac_list_lol_count(process_handle),
+		     rsbac_list_lol_all_subcount(process_handle));
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+        head_p = srcu_dereference(device_list_head_p, &device_list_srcu);
+	device_p = srcu_dereference(head_p->head, &device_list_srcu);
+	while (device_p) {
+		/* reset counters */
+		cap_set_count = rsbac_list_lol_count(device_p->handle);
+		member_count = rsbac_list_lol_all_subcount(device_p->handle);
+		rsbac_printk(KERN_INFO "device %02u:%02u has %u file cap set items, sum of %u members\n",
+			     RSBAC_MAJOR(device_p->id),
+			     RSBAC_MINOR(device_p->id), cap_set_count,
+			     member_count);
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return 0;
+}
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the rw-spinlocks to protect the targets during */
+/* access.                                                                  */
+/* Trying to access a never created or removed set returns an error! */
+
+/* rsbac_auth_add_to_capset */
+/* Add a set member to a set sublist. Set behaviour: also returns success, */
+/* if member was already in set! */
+
+int rsbac_auth_add_to_p_capset(rsbac_list_ta_number_t ta_number,
+			       rsbac_pid_t pid,
+			       enum rsbac_auth_cap_type_t cap_type,
+			       struct rsbac_auth_cap_range_t cap_range,
+			       rsbac_time_t ttl)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_add_to_p_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_add_to_p_capset(): called from interrupt!\n");
+	}
+	if (cap_range.first > cap_range.last)
+		return -RSBAC_EINVALIDVALUE;
+	switch (cap_type) {
+	case ACT_real:
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    process_handle, ttl,
+						    &pid, &cap_range,
+						    NULL);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    process_eff_handle,
+						    ttl, &pid, &cap_range,
+						    NULL);
+	case ACT_fs:
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    process_fs_handle, ttl,
+						    &pid, &cap_range,
+						    NULL);
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    process_group_handle,
+						    ttl, &pid, &cap_range,
+						    NULL);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    process_group_eff_handle,
+						    ttl, &pid, &cap_range,
+						    NULL);
+	case ACT_group_fs:
+		return rsbac_ta_list_lol_subadd_ttl(ta_number,
+						    process_group_fs_handle,
+						    ttl, &pid, &cap_range,
+						    NULL);
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		return -RSBAC_EINVALIDATTR;
+	}
+}
+
+int rsbac_auth_add_to_f_capset(rsbac_list_ta_number_t ta_number,
+			       rsbac_auth_file_t file,
+			       enum rsbac_auth_cap_type_t cap_type,
+			       struct rsbac_auth_cap_range_t cap_range,
+			       rsbac_time_t ttl)
+{
+	int err = 0;
+	struct rsbac_auth_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_add_to_f_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_add_to_f_capset(): called from interrupt!\n");
+	}
+	if (cap_range.first > cap_range.last)
+		return -RSBAC_EINVALIDVALUE;
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_add_to_f_capset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+
+	switch (cap_type) {
+	case ACT_real:
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->handle,
+						 ttl, &inode_nr,
+						 &cap_range, NULL);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->eff_handle,
+						 ttl, &inode_nr,
+						 &cap_range, NULL);
+		break;
+	case ACT_fs:
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->fs_handle,
+						 ttl, &inode_nr,
+						 &cap_range, NULL);
+		break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->group_handle,
+						 ttl,
+						 &inode_nr, &cap_range,
+						 NULL);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->group_eff_handle,
+						 ttl,
+						 &inode_nr, &cap_range,
+						 NULL);
+		break;
+	case ACT_group_fs:
+		err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+						 device_p->group_fs_handle,
+						 ttl,
+						 &inode_nr, &cap_range,
+						 NULL);
+		break;
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		err = -RSBAC_EINVALIDATTR;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+/* rsbac_auth_remove_from_capset */
+/* Remove a set member from a sublist. Set behaviour: Returns no error, if */
+/* member is not in list.                                                  */
+
+int rsbac_auth_remove_from_p_capset(rsbac_list_ta_number_t ta_number,
+				    rsbac_pid_t pid,
+				    enum rsbac_auth_cap_type_t cap_type,
+				    struct rsbac_auth_cap_range_t
+				    cap_range)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_remove_from_p_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_remove_from_p_capset(): called from interrupt!\n");
+	}
+	if (cap_range.first > cap_range.last)
+		return -RSBAC_EINVALIDVALUE;
+	switch (cap_type) {
+	case ACT_real:
+		return rsbac_ta_list_lol_subremove(ta_number,
+						   process_handle, &pid,
+						   &cap_range);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		return rsbac_ta_list_lol_subremove(ta_number,
+						   process_eff_handle,
+						   &pid, &cap_range);
+	case ACT_fs:
+		return rsbac_ta_list_lol_subremove(ta_number,
+						   process_fs_handle, &pid,
+						   &cap_range);
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		return rsbac_ta_list_lol_subremove(ta_number,
+						   process_group_handle,
+						   &pid, &cap_range);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		return rsbac_ta_list_lol_subremove(ta_number,
+						   process_group_eff_handle,
+						   &pid, &cap_range);
+	case ACT_group_fs:
+		return rsbac_ta_list_lol_subremove(ta_number,
+						   process_group_fs_handle,
+						   &pid, &cap_range);
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		return -RSBAC_EINVALIDATTR;
+	}
+}
+
+int rsbac_auth_remove_from_f_capset(rsbac_list_ta_number_t ta_number,
+				    rsbac_auth_file_t file,
+				    enum rsbac_auth_cap_type_t cap_type,
+				    struct rsbac_auth_cap_range_t
+				    cap_range)
+{
+	int err = 0;
+	struct rsbac_auth_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_remove_from_f_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_remove_from_f_capset(): called from interrupt!\n");
+	}
+	if (cap_range.first > cap_range.last)
+		return -RSBAC_EINVALIDVALUE;
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_remove_from_f_capset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	switch (cap_type) {
+	case ACT_real:
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->handle,
+						&inode_nr, &cap_range);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->eff_handle,
+						&inode_nr, &cap_range);
+		break;
+	case ACT_fs:
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->fs_handle,
+						&inode_nr, &cap_range);
+		break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->group_handle,
+						&inode_nr, &cap_range);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->group_eff_handle,
+						&inode_nr, &cap_range);
+		break;
+	case ACT_group_fs:
+		err = rsbac_ta_list_lol_subremove(ta_number,
+						device_p->group_fs_handle,
+						&inode_nr, &cap_range);
+		break;
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		err = -RSBAC_EINVALIDATTR;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+/* rsbac_auth_clear_capset */
+/* Remove all set members from a sublist. Set behaviour: Returns no error, */
+/* if list is empty.                                                       */
+
+int rsbac_auth_clear_p_capset(rsbac_list_ta_number_t ta_number,
+			      rsbac_pid_t pid,
+			      enum rsbac_auth_cap_type_t cap_type)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_clear_p_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_clear_p_capset(): called from interrupt!\n");
+	}
+	switch (cap_type) {
+	case ACT_real:
+		return rsbac_ta_list_lol_remove(ta_number, process_handle,
+						&pid);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		return rsbac_ta_list_lol_remove(ta_number,
+						process_eff_handle, &pid);
+	case ACT_fs:
+		return rsbac_ta_list_lol_remove(ta_number,
+						process_fs_handle, &pid);
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		return rsbac_ta_list_lol_remove(ta_number,
+						process_group_handle,
+						&pid);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		return rsbac_ta_list_lol_remove(ta_number,
+						process_group_eff_handle,
+						&pid);
+	case ACT_group_fs:
+		return rsbac_ta_list_lol_remove(ta_number,
+						process_group_fs_handle,
+						&pid);
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
+
+int rsbac_auth_clear_f_capset(rsbac_list_ta_number_t ta_number,
+			      rsbac_auth_file_t file,
+			      enum rsbac_auth_cap_type_t cap_type)
+{
+	int err = 0;
+	struct rsbac_auth_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_clear_f_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_clear_f_capset(): called from interrupt!\n");
+	}
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_clear_f_capset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	switch (cap_type) {
+	case ACT_real:
+		err = rsbac_ta_list_lol_remove(ta_number,
+					device_p->handle,
+					&inode_nr);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		err = rsbac_ta_list_lol_remove(ta_number,
+					device_p->eff_handle,
+					&inode_nr);
+		break;
+	case ACT_fs:
+		err = rsbac_ta_list_lol_remove(ta_number,
+					device_p->fs_handle,
+					&inode_nr);
+		break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		err = rsbac_ta_list_lol_remove(ta_number,
+					device_p->group_handle,
+					&inode_nr);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		err = rsbac_ta_list_lol_remove(ta_number,
+					device_p->group_eff_handle,
+					&inode_nr);
+		break;
+	case ACT_group_fs:
+		err = rsbac_ta_list_lol_remove(ta_number,
+					device_p-> group_fs_handle,
+					&inode_nr);
+		break;
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		err = -RSBAC_EINVALIDTARGET;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+/* rsbac_auth_capset_member */
+/* Return truth value, whether member is in set */
+
+rsbac_boolean_t rsbac_auth_p_capset_member(rsbac_pid_t pid,
+					   enum rsbac_auth_cap_type_t
+					   cap_type, rsbac_uid_t member)
+{
+	rsbac_boolean_t result;
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+	int srcu_idx;
+#endif
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_p_capset_member(): RSBAC not initialized\n");
+		return FALSE;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_p_capset_member(): called from interrupt!\n");
+	}
+	switch (cap_type) {
+	case ACT_real:
+		result = rsbac_list_lol_subexist_compare(process_handle, &pid,
+						    &member,
+						    single_cap_compare);
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+		/* check for pseudo set "all" */
+		if (!result) {
+			rsbac_uid_t amember;
+
+			amember = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_ALL, member);
+			result = rsbac_list_lol_subexist_compare(process_handle,
+								&pid,
+								&amember,
+								single_cap_compare);
+		}
+#endif
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+		if (!result && (RSBAC_UID_NUM(member) <= RSBAC_AUTH_MAX_RANGE_UID)
+		    ) {
+			union rsbac_target_id_t tid;
+			union rsbac_attribute_value_t attr_val;
+			rsbac_boolean_t learn;
+
+			learn = rsbac_auth_learn;
+			if (!learn) {
+				tid.process = pid;
+				/* check learn on process */
+				if (!rsbac_get_attr
+				    (SW_AUTH, T_PROCESS, tid, A_auth_learn,
+				     &attr_val, FALSE))
+					learn = attr_val.auth_learn;
+			}
+			if (learn) {
+				struct rsbac_auth_cap_range_t range;
+				int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_UID_SET(member))
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH capability for uid %u/%u to pid %u(%s) to transaction %u!\n",
+						RSBAC_UID_SET(member),
+						RSBAC_UID_NUM(member),
+						pid_nr(pid),
+						current->comm,
+						auth_learn_ta);
+				else
+#endif
+				rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH capability for uid %u to pid %u(%s) to transaction %u!\n",
+					     RSBAC_UID_NUM(member), pid_nr(pid), current->comm, auth_learn_ta);
+				range.first = member;
+				range.last = member;
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+				if (!rsbac_list_ta_exist(auth_learn_ta))
+					rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+							&auth_learn_ta,
+							RSBAC_ALL_USERS,
+							RSBAC_AUTH_LEARN_TA_NAME,
+							NULL);
+#endif
+				rsbac_ta_list_lol_subadd_ttl(auth_learn_ta,
+							process_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&pid,
+							&range,
+							NULL);
+
+				tid.process = pid;
+				if (!(err = rsbac_get_attr
+				    (SW_GEN, T_PROCESS, tid,
+				     A_program_file, &attr_val,
+				     FALSE))) {
+					struct
+					    rsbac_auth_device_list_item_t
+					    *device_p;
+					union rsbac_attribute_value_t
+					    attr_val2;
+					char * target_id_name;
+					rsbac_old_inode_nr_t inode_nr = attr_val.program_file.inode;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				        target_id_name
+				         = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+				           /* max. path name len + some extra */
+#else
+				        target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+				           /* max. file name len + some extra */
+#endif
+					if (!rsbac_get_attr
+					    (SW_AUTH, T_PROCESS, tid,
+					     A_auth_start_uid, &attr_val2,
+					     FALSE)
+					    && (range.first ==
+						attr_val2.auth_start_uid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_OWNER_F_CAP;
+						range.last = range.first;
+					}
+					tid.file = attr_val.program_file;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+					if(RSBAC_UID_SET(range.first))
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH capability for uid %u/%u to FILE %s to transaction %u!\n",
+							     RSBAC_UID_SET(range.first),
+							     RSBAC_UID_NUM(range.first),
+							     get_target_name(NULL, T_FILE, target_id_name, tid),
+							     auth_learn_ta);
+					else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH capability for uid %u to FILE %s to transaction %u!\n",
+						     RSBAC_UID_NUM(range.first),
+						     get_target_name(NULL, T_FILE, target_id_name, tid),
+						     auth_learn_ta);
+					rsbac_kfree(target_id_name);
+					srcu_idx = srcu_read_lock(&device_list_srcu);
+					device_p =
+					    lookup_device(attr_val.
+							  program_file.
+							  device);
+					if (device_p) {
+						rsbac_ta_list_lol_subadd_ttl(
+							auth_learn_ta,
+							device_p->handle,
+							RSBAC_LIST_TTL_KEEP,
+							&inode_nr,
+							&range,
+							NULL);
+					} else {
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): unknown device %02u:%02u!\n",
+							     MAJOR
+							     (attr_val.
+							      program_file.
+							      device),
+							     MINOR
+							     (attr_val.
+							      program_file.
+							      device));
+					}
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+				} else
+					rsbac_pr_get_error_num(A_program_file, err);
+				result = TRUE;
+			}
+		}
+#endif
+		break;
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		result =
+		    rsbac_list_lol_subexist_compare(process_eff_handle,
+						    &pid, &member,
+						    single_cap_compare);
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+		/* check for pseudo set "all" */
+		if (!result) {
+			rsbac_uid_t amember;
+
+			amember = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_ALL, member);
+			result = rsbac_list_lol_subexist_compare(process_eff_handle,
+								&pid,
+								&amember,
+								single_cap_compare);
+		}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+		if (!result && (RSBAC_UID_NUM(member) <= RSBAC_AUTH_MAX_RANGE_UID)
+		    ) {
+			union rsbac_target_id_t tid;
+			union rsbac_attribute_value_t attr_val;
+			rsbac_boolean_t learn;
+
+			learn = rsbac_auth_learn;
+			if (!learn) {
+				tid.process = pid;
+				/* check learn on process */
+				if (!rsbac_get_attr
+				    (SW_AUTH, T_PROCESS, tid, A_auth_learn,
+				     &attr_val, FALSE))
+					learn = attr_val.auth_learn;
+			}
+			if (learn) {
+				struct rsbac_auth_cap_range_t range;
+				int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_UID_SET(member))
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH eff capability for uid %u/%u to pid %u(%s) to transaction %u!\n",
+						RSBAC_UID_SET(member),
+						RSBAC_UID_NUM(member),
+						pid_nr(pid),
+						current->comm,
+						auth_learn_ta);
+				else
+#endif
+				rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH eff capability for uid %u to pid %u(%s) to transaction %u!\n",
+					     RSBAC_UID_NUM(member), pid_nr(pid), current->comm, auth_learn_ta);
+				range.first = member;
+				range.last = member;
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+				if (!rsbac_list_ta_exist(auth_learn_ta))
+					rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+							&auth_learn_ta,
+							RSBAC_ALL_USERS,
+							RSBAC_AUTH_LEARN_TA_NAME,
+							NULL);
+#endif
+				rsbac_ta_list_lol_subadd_ttl(auth_learn_ta,
+							process_eff_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&pid,
+							&range,
+							NULL);
+
+				tid.process = pid;
+				if (!(err = rsbac_get_attr
+				    (SW_GEN, T_PROCESS, tid,
+				     A_program_file, &attr_val,
+				     FALSE))) {
+					struct
+					    rsbac_auth_device_list_item_t
+					    *device_p;
+					union rsbac_attribute_value_t
+					    attr_val2;
+					char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				        target_id_name
+				         = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+				           /* max. path name len + some extra */
+#else
+				        target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+				           /* max. file name len + some extra */
+#endif
+					if (!rsbac_get_attr
+					    (SW_AUTH, T_PROCESS, tid,
+					     A_auth_start_uid, &attr_val2,
+					     FALSE)
+					    && (range.first ==
+						attr_val2.auth_start_uid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_OWNER_F_CAP;
+						range.last = range.first;
+					} else
+					    if (!rsbac_get_attr
+						(SW_AUTH, T_PROCESS, tid,
+						 A_auth_start_euid,
+						 &attr_val2, FALSE)
+						&& (range.first ==
+						    attr_val2.
+						    auth_start_euid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_DAC_OWNER_F_CAP;
+						range.last = range.first;
+					}
+					tid.file = attr_val.program_file;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+					if(RSBAC_UID_SET(range.first))
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH eff capability for uid %u/%u to FILE %s to transaction %u!\n",
+							     RSBAC_UID_SET(range.first),
+							     RSBAC_UID_NUM(range.first),
+							     get_target_name(NULL, T_FILE, target_id_name, tid),
+							     auth_learn_ta);
+					else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH eff capability for uid %u to FILE %s to transaction %u!\n",
+						     RSBAC_UID_NUM(range.first),
+						     get_target_name(NULL, T_FILE, target_id_name, tid),
+						     auth_learn_ta);
+					rsbac_kfree(target_id_name);
+					srcu_idx = srcu_read_lock(&device_list_srcu);
+					device_p =
+					    lookup_device(attr_val.
+							  program_file.
+							  device);
+					if (device_p) {
+						rsbac_ta_list_lol_subadd_ttl(
+							auth_learn_ta,
+							device_p->eff_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&attr_val.program_file.inode,
+							&range,
+							NULL);
+					} else {
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): unknown device %02u:%02u!\n",
+							     MAJOR
+							     (attr_val.
+							      program_file.
+							      device),
+							     MINOR
+							     (attr_val.
+							      program_file.
+							      device));
+					}
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+				} else
+					rsbac_pr_get_error_num(A_program_file, err);
+				result = TRUE;
+			}
+		}
+#endif
+		break;
+
+	case ACT_fs:
+		result =
+		    rsbac_list_lol_subexist_compare(process_fs_handle,
+						    &pid, &member,
+						    single_cap_compare);
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+		/* check for pseudo set "all" */
+		if (!result) {
+			rsbac_uid_t amember;
+
+			amember = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_ALL, member);
+			result = rsbac_list_lol_subexist_compare(process_fs_handle,
+								&pid,
+								&amember,
+								single_cap_compare);
+		}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+		if (!result && (RSBAC_UID_NUM(member) <= RSBAC_AUTH_MAX_RANGE_UID)
+		    ) {
+			union rsbac_target_id_t tid;
+			union rsbac_attribute_value_t attr_val;
+			rsbac_boolean_t learn;
+
+			learn = rsbac_auth_learn;
+			if (!learn) {
+				tid.process = pid;
+				/* check learn on process */
+				if (!rsbac_get_attr
+				    (SW_AUTH, T_PROCESS, tid, A_auth_learn,
+				     &attr_val, FALSE))
+					learn = attr_val.auth_learn;
+			}
+			if (learn) {
+				struct rsbac_auth_cap_range_t range;
+				int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_UID_SET(member))
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH fs capability for uid %u/%u to pid %u(%s) to transaction %u!\n",
+						RSBAC_UID_SET(member),
+						RSBAC_UID_NUM(member),
+						pid_nr(pid),
+						current->comm,
+						auth_learn_ta);
+				else
+#endif
+				rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH fs capability for uid %u to pid %u(%s) to transaction %u!\n",
+					     RSBAC_UID_NUM(member), pid_nr(pid), current->comm, auth_learn_ta);
+				range.first = member;
+				range.last = member;
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+				if (!rsbac_list_ta_exist(auth_learn_ta))
+					rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+							&auth_learn_ta,
+							RSBAC_ALL_USERS,
+							RSBAC_AUTH_LEARN_TA_NAME,
+							NULL);
+#endif
+				rsbac_ta_list_lol_subadd_ttl(auth_learn_ta,
+							process_fs_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&pid,
+							&range,
+							NULL);
+
+				tid.process = pid;
+				if (!(err = rsbac_get_attr
+				    (SW_GEN, T_PROCESS, tid,
+				     A_program_file, &attr_val,
+				     FALSE))) {
+					struct
+					    rsbac_auth_device_list_item_t
+					    *device_p;
+					union rsbac_attribute_value_t
+					    attr_val2;
+					char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				        target_id_name
+				         = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+				           /* max. path name len + some extra */
+#else
+				        target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+				           /* max. file name len + some extra */
+#endif
+					if (!rsbac_get_attr
+					    (SW_AUTH, T_PROCESS, tid,
+					     A_auth_start_uid, &attr_val2,
+					     FALSE)
+					    && (range.first ==
+						attr_val2.auth_start_uid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_OWNER_F_CAP;
+						range.last = range.first;
+					} else
+					    if (!rsbac_get_attr
+						(SW_AUTH, T_PROCESS, tid,
+						 A_auth_start_euid,
+						 &attr_val2, FALSE)
+						&& (range.first ==
+						    attr_val2.
+						    auth_start_euid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_DAC_OWNER_F_CAP;
+						range.last = range.first;
+					}
+					tid.file = attr_val.program_file;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+					if(RSBAC_UID_SET(range.first))
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH fs capability for uid %u/%u to FILE %s to transaction %u!\n",
+							     RSBAC_UID_SET(range.first),
+							     RSBAC_UID_NUM(range.first),
+							     get_target_name(NULL, T_FILE, target_id_name, tid),
+							     auth_learn_ta);
+					else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH fs capability for uid %u to FILE %s to transaction %u!\n",
+						     RSBAC_UID_NUM(range.first),
+						     get_target_name(NULL, T_FILE, target_id_name, tid),
+						     auth_learn_ta);
+					rsbac_kfree(target_id_name);
+					srcu_idx = srcu_read_lock(&device_list_srcu);
+					device_p =
+					    lookup_device(attr_val.
+							  program_file.
+							  device);
+					if (device_p) {
+						rsbac_ta_list_lol_subadd_ttl(
+							auth_learn_ta,
+							device_p->fs_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&attr_val.program_file.inode,
+							&range,
+							NULL);
+					} else {
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): unknown device %02u:%02u!\n",
+							     MAJOR
+							     (attr_val.
+							      program_file.
+							      device),
+							     MINOR
+							     (attr_val.
+							      program_file.
+							      device));
+					}
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+				} else
+					rsbac_pr_get_error_num(A_program_file, err);
+				result = TRUE;
+			}
+		}
+#endif
+		break;
+#endif				/* AUTH_DAC_OWNER */
+
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		result =
+		    rsbac_list_lol_subexist_compare(process_group_handle,
+						    &pid, &member,
+						    single_cap_compare);
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+		/* check for pseudo set "all" */
+		if (!result) {
+			rsbac_uid_t amember;
+
+			amember = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_ALL, member);
+			result = rsbac_list_lol_subexist_compare(process_group_handle,
+								&pid,
+								&amember,
+								single_cap_compare);
+		}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+		if (!result && (RSBAC_GID_NUM(member) <= RSBAC_AUTH_MAX_RANGE_GID)
+		    ) {
+			union rsbac_target_id_t tid;
+			union rsbac_attribute_value_t attr_val;
+			rsbac_boolean_t learn;
+
+			learn = rsbac_auth_learn;
+			if (!learn) {
+				tid.process = pid;
+				/* check learn on process */
+				if (!rsbac_get_attr
+				    (SW_AUTH, T_PROCESS, tid, A_auth_learn,
+				     &attr_val, FALSE))
+					learn = attr_val.auth_learn;
+			}
+			if (learn) {
+				struct rsbac_auth_cap_range_t range;
+				int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_GID_SET(member))
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group capability for gid %u/%u to pid %u(%s) to transaction %u!\n",
+						RSBAC_GID_SET(member),
+						RSBAC_GID_NUM(member),
+						pid_nr(pid),
+						current->comm,
+						auth_learn_ta);
+				else
+#endif
+				rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group capability for gid %u to pid %u(%s) to transaction %u!\n",
+					     RSBAC_GID_NUM(member), pid_nr(pid), current->comm, auth_learn_ta);
+				range.first = member;
+				range.last = member;
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+				if (!rsbac_list_ta_exist(auth_learn_ta))
+					rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+							&auth_learn_ta,
+							RSBAC_ALL_USERS,
+							RSBAC_AUTH_LEARN_TA_NAME,
+							NULL);
+#endif
+				rsbac_ta_list_lol_subadd_ttl(auth_learn_ta,
+							process_group_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&pid,
+							&range,
+							NULL);
+
+				tid.process = pid;
+				if (!(err = rsbac_get_attr
+				    (SW_GEN, T_PROCESS, tid,
+				     A_program_file, &attr_val,
+				     FALSE))) {
+					struct
+					    rsbac_auth_device_list_item_t
+					    *device_p;
+					union rsbac_attribute_value_t
+					    attr_val2;
+					char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				        target_id_name
+				         = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+				           /* max. path name len + some extra */
+#else
+				        target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+				           /* max. file name len + some extra */
+#endif
+					if (!rsbac_get_attr
+					    (SW_AUTH, T_PROCESS, tid,
+					     A_auth_start_gid, &attr_val2,
+					     FALSE)
+					    && (range.first ==
+						attr_val2.auth_start_gid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_GROUP_F_CAP;
+						range.last = range.first;
+					}
+					tid.file = attr_val.program_file;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+					if(RSBAC_GID_SET(range.first))
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group capability for gid %u/%u to FILE %s to transaction %u!\n",
+							     RSBAC_GID_SET(range.first),
+							     RSBAC_GID_NUM(range.first),
+							     get_target_name(NULL, T_FILE, target_id_name, tid),
+							     auth_learn_ta);
+					else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group capability for gid %u to FILE %s to transaction %u!\n",
+						     RSBAC_GID_NUM(range.first),
+						     get_target_name(NULL, T_FILE, target_id_name, tid),
+						     auth_learn_ta);
+					rsbac_kfree(target_id_name);
+					srcu_idx = srcu_read_lock(&device_list_srcu);
+					device_p =
+					    lookup_device(attr_val.
+							  program_file.
+							  device);
+					if (device_p) {
+						rsbac_ta_list_lol_subadd_ttl(
+							auth_learn_ta,
+							device_p->group_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&attr_val.program_file.inode,
+							&range,
+							NULL);
+					} else {
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): unknown device %02u:%02u!\n",
+							     MAJOR
+							     (attr_val.
+							      program_file.
+							      device),
+							     MINOR
+							     (attr_val.
+							      program_file.
+							      device));
+					}
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+				} else
+					rsbac_pr_get_error_num(A_program_file, err);
+				result = TRUE;
+			}
+		}
+#endif
+		break;
+
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		result =
+		    rsbac_list_lol_subexist_compare
+		    (process_group_eff_handle, &pid, &member,
+		     single_cap_compare);
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+		/* check for pseudo set "all" */
+		if (!result) {
+			rsbac_uid_t amember;
+
+			amember = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_ALL, member);
+			result = rsbac_list_lol_subexist_compare(process_group_eff_handle,
+								&pid,
+								&amember,
+								single_cap_compare);
+		}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+		if (!result && (RSBAC_GID_NUM(member) <= RSBAC_AUTH_MAX_RANGE_GID)
+		    ) {
+			union rsbac_target_id_t tid;
+			union rsbac_attribute_value_t attr_val;
+			rsbac_boolean_t learn;
+
+			learn = rsbac_auth_learn;
+			if (!learn) {
+				tid.process = pid;
+				/* check learn on process */
+				if (!rsbac_get_attr
+				    (SW_AUTH, T_PROCESS, tid, A_auth_learn,
+				     &attr_val, FALSE))
+					learn = attr_val.auth_learn;
+			}
+			if (learn) {
+				struct rsbac_auth_cap_range_t range;
+				int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_GID_SET(member))
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group eff capability for gid %u/%u to pid %u(%s) to transaction %u!\n",
+						RSBAC_GID_SET(member),
+						RSBAC_GID_NUM(member),
+						pid_nr(pid),
+						current->comm,
+						auth_learn_ta);
+				else
+#endif
+				rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group eff capability for gid %u to pid %u(%s) to transaction %u!\n",
+					     RSBAC_GID_NUM(member), pid_nr(pid), current->comm, auth_learn_ta);
+				range.first = member;
+				range.last = member;
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+				if (!rsbac_list_ta_exist(auth_learn_ta))
+					rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+							&auth_learn_ta,
+							RSBAC_ALL_USERS,
+							RSBAC_AUTH_LEARN_TA_NAME,
+							NULL);
+#endif
+				rsbac_ta_list_lol_subadd_ttl(auth_learn_ta,
+							process_group_eff_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&pid,
+							&range,
+							NULL);
+
+				tid.process = pid;
+				if (!(err = rsbac_get_attr
+				    (SW_GEN, T_PROCESS, tid,
+				     A_program_file, &attr_val,
+				     FALSE))) {
+					struct
+					    rsbac_auth_device_list_item_t
+					    *device_p;
+					union rsbac_attribute_value_t
+					    attr_val2;
+					char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				        target_id_name
+				         = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+				           /* max. path name len + some extra */
+#else
+				        target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+				           /* max. file name len + some extra */
+#endif
+					if (!rsbac_get_attr
+					    (SW_AUTH, T_PROCESS, tid,
+					     A_auth_start_gid, &attr_val2,
+					     FALSE)
+					    && (range.first ==
+						attr_val2.auth_start_gid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_GROUP_F_CAP;
+						range.last = range.first;
+					} else
+					    if (!rsbac_get_attr
+						(SW_AUTH, T_PROCESS, tid,
+						 A_auth_start_egid,
+						 &attr_val2, FALSE)
+						&& (range.first ==
+						    attr_val2.
+						    auth_start_egid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_DAC_GROUP_F_CAP;
+						range.last = range.first;
+					}
+					tid.file = attr_val.program_file;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+					if(RSBAC_GID_SET(range.first))
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group eff capability for gid %u/%u to FILE %s to transaction %u!\n",
+							     RSBAC_GID_SET(range.first),
+							     RSBAC_GID_NUM(range.first),
+							     get_target_name(NULL, T_FILE, target_id_name, tid),
+							     auth_learn_ta);
+					else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group eff capability for gid %u to FILE %s to transaction %u!\n",
+						     RSBAC_GID_NUM(range.first),
+						     get_target_name(NULL, T_FILE, target_id_name, tid),
+						     auth_learn_ta);
+					rsbac_kfree(target_id_name);
+					srcu_idx = srcu_read_lock(&device_list_srcu);
+					device_p =
+					    lookup_device(attr_val.
+							  program_file.
+							  device);
+					if (device_p) {
+						rsbac_ta_list_lol_subadd_ttl(
+							auth_learn_ta,
+							device_p->group_eff_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&attr_val.program_file.inode,
+							&range,
+							NULL);
+					} else {
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): unknown device %02u:%02u!\n",
+							     MAJOR
+							     (attr_val.
+							      program_file.
+							      device),
+							     MINOR
+							     (attr_val.
+							      program_file.
+							      device));
+					}
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+				} else
+					rsbac_pr_get_error_num(A_program_file, err);
+				result = TRUE;
+			}
+		}
+#endif
+		break;
+
+	case ACT_group_fs:
+		result =
+		    rsbac_list_lol_subexist_compare
+		    (process_group_fs_handle, &pid, &member,
+		     single_cap_compare);
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+		/* check for pseudo set "all" */
+		if (!result) {
+			rsbac_uid_t amember;
+
+			amember = RSBAC_GEN_GID(RSBAC_UM_VIRTUAL_ALL, member);
+			result = rsbac_list_lol_subexist_compare(process_group_fs_handle,
+								&pid,
+								&amember,
+								single_cap_compare);
+		}
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+		if (!result && (RSBAC_GID_NUM(member) <= RSBAC_AUTH_MAX_RANGE_GID)
+		    ) {
+			union rsbac_target_id_t tid;
+			union rsbac_attribute_value_t attr_val;
+			rsbac_boolean_t learn;
+
+			learn = rsbac_auth_learn;
+			if (!learn) {
+				tid.process = pid;
+				/* check learn on process */
+				if (!rsbac_get_attr
+				    (SW_AUTH, T_PROCESS, tid, A_auth_learn,
+				     &attr_val, FALSE))
+					learn = attr_val.auth_learn;
+			}
+			if (learn) {
+				struct rsbac_auth_cap_range_t range;
+				int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_GID_SET(member))
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group fs capability for gid %u/%u to pid %u(%s) to transaction %u!\n",
+						RSBAC_GID_SET(member),
+						RSBAC_GID_NUM(member),
+						pid_nr(pid),
+						current->comm,
+						auth_learn_ta);
+				else
+#endif
+				rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group fs capability for gid %u to pid %u(%s) to transaction %u!\n",
+					     RSBAC_GID_NUM(member), pid_nr(pid), current->comm, auth_learn_ta);
+				range.first = member;
+				range.last = member;
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+				if (!rsbac_list_ta_exist(auth_learn_ta))
+					rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+							&auth_learn_ta,
+							RSBAC_ALL_USERS,
+							RSBAC_AUTH_LEARN_TA_NAME,
+							NULL);
+#endif
+				rsbac_ta_list_lol_subadd_ttl(auth_learn_ta,
+							process_group_fs_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&pid,
+							&range,
+							NULL);
+
+				tid.process = pid;
+				if (!(err = rsbac_get_attr
+				    (SW_GEN, T_PROCESS, tid,
+				     A_program_file, &attr_val,
+				     FALSE))) {
+					struct
+					    rsbac_auth_device_list_item_t
+					    *device_p;
+					union rsbac_attribute_value_t
+					    attr_val2;
+					char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+				        target_id_name
+				         = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+				           /* max. path name len + some extra */
+#else
+				        target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+				           /* max. file name len + some extra */
+#endif
+					if (!rsbac_get_attr
+					    (SW_AUTH, T_PROCESS, tid,
+					     A_auth_start_gid, &attr_val2,
+					     FALSE)
+					    && (range.first ==
+						attr_val2.auth_start_gid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_GROUP_F_CAP;
+						range.last = range.first;
+					} else
+					    if (!rsbac_get_attr
+						(SW_AUTH, T_PROCESS, tid,
+						 A_auth_start_egid,
+						 &attr_val2, FALSE)
+						&& (range.first ==
+						    attr_val2.
+						    auth_start_egid)
+					    ) {
+						range.first =
+						    RSBAC_AUTH_DAC_GROUP_F_CAP;
+						range.last = range.first;
+					}
+					tid.file = attr_val.program_file;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+					if(RSBAC_GID_SET(range.first))
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group fs capability for gid %u/%u to FILE %s to transaction %u!\n",
+							     RSBAC_GID_SET(range.first),
+							     RSBAC_GID_NUM(range.first),
+							     get_target_name(NULL, T_FILE, target_id_name, tid),
+							     auth_learn_ta);
+					else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): adding AUTH group fs capability for gid %u to FILE %s to transaction %u!\n",
+						     RSBAC_GID_NUM(range.first),
+						     get_target_name(NULL, T_FILE, target_id_name, tid),
+						     auth_learn_ta);
+					rsbac_kfree(target_id_name);
+					srcu_idx = srcu_read_lock(&device_list_srcu);
+					device_p =
+					    lookup_device(attr_val.
+							  program_file.
+							  device);
+					if (device_p) {
+						rsbac_ta_list_lol_subadd_ttl(
+							auth_learn_ta,
+							device_p->group_fs_handle,
+							RSBAC_LIST_TTL_KEEP,
+							&attr_val.program_file.inode,
+							&range,
+							NULL);
+					} else {
+						rsbac_printk(KERN_INFO "rsbac_auth_p_capset_member(): unknown device %02u:%02u!\n",
+							     MAJOR
+							     (attr_val.
+							      program_file.
+							      device),
+							     MINOR
+							     (attr_val.
+							      program_file.
+							      device));
+					}
+					srcu_read_unlock(&device_list_srcu, srcu_idx);
+				} else
+					rsbac_pr_get_error_num(A_program_file, err);
+				result = TRUE;
+			}
+		}
+#endif
+		break;
+#endif				/* AUTH_DAC_GROUP */
+#endif				/* AUTH_GROUP */
+
+	default:
+		return FALSE;
+	}
+	return result;
+}
+
+/* rsbac_auth_remove_capset */
+/* Remove a full set. For cleanup, if object is deleted. */
+/* To empty an existing set use rsbac_auth_clear_capset. */
+
+int rsbac_auth_remove_p_capsets(rsbac_pid_t pid)
+{
+	int err;
+
+	err = rsbac_auth_clear_p_capset(0, pid, ACT_real);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	err = rsbac_auth_clear_p_capset(0, pid, ACT_eff);
+	err = rsbac_auth_clear_p_capset(0, pid, ACT_fs);
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	err = rsbac_auth_clear_p_capset(0, pid, ACT_group_real);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	err = rsbac_auth_clear_p_capset(0, pid, ACT_group_eff);
+	err = rsbac_auth_clear_p_capset(0, pid, ACT_group_fs);
+#endif
+#endif				/* AUTH_GROUP */
+
+	return err;
+}
+
+int rsbac_auth_remove_f_capsets(rsbac_auth_file_t file)
+{
+	int err;
+
+	err = rsbac_auth_clear_f_capset(0, file, ACT_real);
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	if (!err)
+		err = rsbac_auth_clear_f_capset(0, file, ACT_eff);
+	if (!err)
+		err = rsbac_auth_clear_f_capset(0, file, ACT_fs);
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	err = rsbac_auth_clear_f_capset(0, file, ACT_group_real);
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	if (!err)
+		err = rsbac_auth_clear_f_capset(0, file, ACT_group_eff);
+	if (!err)
+		err = rsbac_auth_clear_f_capset(0, file, ACT_group_fs);
+#endif
+#endif				/* AUTH_GROUP */
+
+	return err;
+}
+
+int rsbac_auth_copy_fp_capset(rsbac_auth_file_t file,
+			      rsbac_pid_t p_cap_set_id)
+{
+	struct rsbac_auth_device_list_item_t *device_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_copy_fp_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_copy_fp_capset(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_auth, "Copying file cap set data to process cap set\n");
+*/
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_copy_fp_capset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	/* call the copy function */
+	err = copy_fp_cap_set_item(device_p, file, p_cap_set_id);
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+int rsbac_auth_copy_pp_capset(rsbac_pid_t old_p_set_id,
+			      rsbac_pid_t new_p_set_id)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_copy_pp_capset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_copy_pp_capset(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_auth, "Copying process cap set data to process cap set\n");
+*/
+	/* call the copy function */
+	return copy_pp_cap_set_item(old_p_set_id, new_p_set_id);
+}
+
+int rsbac_auth_get_f_caplist(rsbac_list_ta_number_t ta_number,
+			     rsbac_auth_file_t file,
+			     enum rsbac_auth_cap_type_t cap_type,
+			     struct rsbac_auth_cap_range_t **caplist_p,
+			     rsbac_time_t ** ttllist_p)
+{
+	struct rsbac_auth_device_list_item_t *device_p;
+	long count;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_get_f_caplist(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_get_f_caplist(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_auth, "Getting file/dir cap set list\n");
+*/
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_get_f_caplist(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	switch (cap_type) {
+	case ACT_real:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      device_p->handle,
+							      &inode_nr,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      device_p->eff_handle,
+							      &inode_nr,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+	case ACT_fs:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      device_p->fs_handle,
+							      &inode_nr,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      device_p->group_handle,
+							      &inode_nr,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      device_p->group_eff_handle,
+							      &inode_nr,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+	case ACT_group_fs:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      device_p->group_fs_handle,
+							      &inode_nr,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		count = -RSBAC_EINVALIDTARGET;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return count;
+}
+
+int rsbac_auth_get_p_caplist(rsbac_list_ta_number_t ta_number,
+			     rsbac_pid_t pid,
+			     enum rsbac_auth_cap_type_t cap_type,
+			     struct rsbac_auth_cap_range_t **caplist_p,
+			     rsbac_time_t ** ttllist_p)
+{
+	long count;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_get_p_caplist(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_auth_get_p_caplist(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_auth, "Getting process cap set list\n");
+*/
+	switch (cap_type) {
+	case ACT_real:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      process_handle,
+							      &pid,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_OWNER
+	case ACT_eff:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      process_eff_handle,
+							      &pid,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+	case ACT_fs:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      process_fs_handle,
+							      &pid,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+	case ACT_group_real:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      process_group_handle,
+							      &pid,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+	case ACT_group_eff:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      process_group_eff_handle,
+							      &pid,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+	case ACT_group_fs:
+		count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							      process_group_fs_handle,
+							      &pid,
+							      (void **)
+							      caplist_p,
+							      ttllist_p);
+		break;
+#endif
+#endif				/* AUTH_GROUP */
+
+	default:
+		count = -RSBAC_EINVALIDTARGET;
+	}
+	return count;
+}
diff --git a/rsbac/data_structures/gen_lists.c b/rsbac/data_structures/gen_lists.c
new file mode 100644
index 0000000..a9abf4a
--- /dev/null
+++ b/rsbac/data_structures/gen_lists.c
@@ -0,0 +1,13085 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2017:           */
+/*   Amon Ott <ao@rsbac.org>           */
+/* Generic lists for all parts         */
+/* Last modified: 01/Mar/2017          */
+/************************************* */
+
+#include <linux/sched.h>
+#include <linux/module.h>
+#ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
+#include <linux/random.h>
+#endif
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+#ifndef CONFIG_RSBAC_NO_WRITE
+#include <linux/mount.h>
+#endif
+#include <linux/srcu.h>
+#include <linux/hash.h>
+
+#include <rsbac/types.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/debug.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/lists.h>
+#include <rsbac/gen_lists.h>
+
+/********************/
+/* Global Variables */
+/********************/
+
+static struct rsbac_list_reg_head_t reg_head;
+static struct rsbac_list_lol_reg_head_t lol_reg_head;
+static rsbac_boolean_t list_initialized = FALSE;
+static struct srcu_struct reg_list_srcu;
+static struct srcu_struct lol_reg_list_srcu;
+
+static struct kmem_cache * reg_item_slab = NULL;
+static struct kmem_cache * lol_reg_item_slab = NULL;
+
+static struct lock_class_key list_lock_class;
+
+static u_int rsbac_list_max_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+static struct rsbac_list_reg_item_t *ta_handle = NULL;
+static DEFINE_SPINLOCK(ta_lock);
+static rsbac_boolean_t ta_committing = FALSE;
+DECLARE_WAIT_QUEUE_HEAD(ta_wait);
+#ifndef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
+rsbac_list_ta_number_t ta_next = 1;
+#endif
+#endif
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+static int do_forget(rsbac_list_ta_number_t ta_number);
+#endif
+
+#ifdef CONFIG_RSBAC_AUTO_WRITE
+static rsbac_time_t next_rehash = 0;
+#endif
+
+static u_int rsbac_list_read_errors = 0;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+static __u64 rcu_free_calls = 0;
+static __u64 rcu_free_item_chain_calls = 0;
+static __u64 rcu_free_lol_calls = 0;
+static __u64 rcu_free_lol_sub_calls = 0;
+static __u64 rcu_free_lol_item_chain_calls = 0;
+static __u64 rcu_free_lol_subitem_chain_calls = 0;
+static __u64 rcu_free_do_cleanup_calls = 0;
+static __u64 rcu_free_do_cleanup_lol_calls = 0;
+static __u64 rcu_free_callback_calls = 0;
+static __u64 rcu_free_callback_lol_calls = 0;
+static __u32 max_rcu_callback_count = 0;
+#endif
+
+/* Limit RCU callback calls to RCURATE per second, switch to sync when exceeded */
+#if CONFIG_RSBAC_RCU_RATE < 0
+#define RCURATE 0
+#else
+#if CONFIG_RSBAC_RCU_RATE > 1000
+#define RCURATE 1000
+#else
+#define RCURATE CONFIG_RSBAC_RCU_RATE
+#endif
+#endif
+u_int rsbac_list_rcu_rate = RCURATE;
+static u_int rcu_callback_count = 0;
+static struct timer_list rcu_rate_timer;
+
+static struct kmem_cache * rcu_free_item_slab = NULL;
+static struct kmem_cache * rcu_free_head_slab = NULL;
+static struct kmem_cache * rcu_free_head_lol_slab = NULL;
+
+
+/*********************************/
+/* Data Structures               */
+/*********************************/
+
+/* RCU garbage collector */
+
+/* Call spinlocked */
+static inline struct rsbac_list_rcu_free_head_t *
+	get_rcu_free(struct rsbac_list_reg_item_t * list)
+{
+	if (list->rcu_free) {
+		struct rsbac_list_rcu_free_head_t * rcu_free;
+
+		rcu_free = list->rcu_free;
+		list->rcu_free = NULL;
+		return rcu_free;
+	} else
+		return NULL;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_rcu_free_head_lol_t *
+	get_rcu_free_lol(struct rsbac_list_lol_reg_item_t * list)
+{
+	if (list->rcu_free) {
+		struct rsbac_list_rcu_free_head_lol_t * rcu_free;
+
+		rcu_free = list->rcu_free;
+		list->rcu_free = NULL;
+		return rcu_free;
+	} else
+		return NULL;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_rcu_free_head_t *
+	create_rcu_free(struct rsbac_list_reg_item_t * list)
+{
+	/* Just to be sure */
+	if (unlikely(!list))
+		return NULL;
+	/* Exists, all fine */
+	if (list->rcu_free)
+		return list->rcu_free;
+
+	list->rcu_free = rsbac_smalloc_clear(rcu_free_head_slab);
+	if (unlikely(!list->rcu_free))
+		return NULL;
+	list->rcu_free->slab = list->slab;
+	return list->rcu_free;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_rcu_free_head_lol_t *
+	create_rcu_free_lol(struct rsbac_list_lol_reg_item_t * list)
+{
+	/* Just to be sure */
+	if (unlikely(!list))
+		return NULL;
+	/* Exists, all fine */
+	if (list->rcu_free)
+		return list->rcu_free;
+
+	list->rcu_free = rsbac_smalloc_clear(rcu_free_head_lol_slab);
+	if (unlikely(!list->rcu_free))
+		return NULL;
+	list->rcu_free->slab = list->slab;
+	list->rcu_free->subslab = list->subslab;
+	return list->rcu_free;
+}
+
+/* Call spinlocked */
+static void rcu_free(struct rsbac_list_reg_item_t * list, void * mem)
+{
+	struct rsbac_list_rcu_free_item_t * rcu_item;
+
+	if (unlikely(!create_rcu_free(list))) {
+		rsbac_printk(KERN_WARNING "rcu_free(): cannot allocate rcu_free_head for list %s, loosing item %p!\n",
+			     list->name, mem);
+		return;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_calls++;
+#endif
+#if 0
+	/* Sanity check for dupes - to be removed after test phase */
+	rcu_item = list->rcu_free->head;
+	while (rcu_item) {
+		if (unlikely(rcu_item->mem == mem)) {
+			BUG();
+			return;
+		}
+		rcu_item = rcu_item->next;
+	}
+#endif
+	rcu_item = rsbac_smalloc(rcu_free_item_slab);
+	if (likely(rcu_item)) {
+		rcu_item->mem = mem;
+		rcu_item->next = list->rcu_free->head;
+		list->rcu_free->head = rcu_item;
+	} else {
+		rsbac_printk(KERN_WARNING "rcu_free(): cannot allocate rcu_free for list %s, loosing item %p!\n",
+			     list->name, mem);
+		rcu_callback_count = rsbac_list_rcu_rate;
+	}
+}
+
+/* Call spinlocked */
+static void rcu_free_lol(struct rsbac_list_lol_reg_item_t * list, void * mem)
+{
+	struct rsbac_list_rcu_free_item_t * rcu_item;
+
+	if (unlikely(!create_rcu_free_lol(list))) {
+		rsbac_printk(KERN_WARNING "rcu_free_lol(): cannot allocate rcu_free_head for list of lists %s, loosing item %p!\n",
+			     list->name, mem);
+		return;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_lol_calls++;
+#endif
+#if 0
+	/* Sanity check for dupes - to be removed after test phase  */
+	rcu_item = list->rcu_free->head;
+	while (rcu_item) {
+		if (unlikely(rcu_item->mem == mem)) {
+			BUG();
+			return;
+		}
+		rcu_item = rcu_item->next;
+	}
+#endif
+	rcu_item = rsbac_smalloc(rcu_free_item_slab);
+	if (likely(rcu_item)) {
+		rcu_item->mem = mem;
+		rcu_item->next = list->rcu_free->head;
+		list->rcu_free->head = rcu_item;
+	} else {
+		rsbac_printk(KERN_WARNING "rcu_free_lol(): cannot allocate rcu_free for list of lists %s, loosing item %p!\n",
+			     list->name, mem);
+		rcu_callback_count = rsbac_list_rcu_rate;
+	}
+}
+
+/* Call spinlocked */
+static void rcu_free_lol_sub(struct rsbac_list_lol_reg_item_t * list, void * mem)
+{
+	struct rsbac_list_rcu_free_item_t * rcu_item;
+
+	if (unlikely(!create_rcu_free_lol(list))) {
+		rsbac_printk(KERN_WARNING "rcu_free_lol_sub(): cannot allocate rcu_free_head for list of lists %s, loosing subitem %p!\n",
+			     list->name, mem);
+		return;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_lol_calls++;
+#endif
+#if 0
+	/* Sanity check for dupes - to be removed after test phase  */
+	rcu_item = list->rcu_free->subhead;
+	while (rcu_item) {
+		if (unlikely(rcu_item->mem == mem)) {
+			BUG();
+			return;
+		}
+		rcu_item = rcu_item->next;
+	}
+#endif
+	rcu_item = rsbac_smalloc(rcu_free_item_slab);
+	if (likely(rcu_item)) {
+		rcu_item->mem = mem;
+		rcu_item->next = list->rcu_free->subhead;
+		list->rcu_free->subhead = rcu_item;
+	} else {
+		rsbac_printk(KERN_WARNING "rcu_free_lol_sub(): cannot allocate rcu_free for list of lists %s, loosing subitem %p!\n",
+			     list->name, mem);
+		rcu_callback_count = rsbac_list_rcu_rate;
+	}
+}
+
+/* Call spinlocked */
+static void rcu_free_item_chain(struct rsbac_list_reg_item_t * list,
+				struct rsbac_list_item_t * item_chain)
+{
+	if (!item_chain)
+		return;
+	if (unlikely(!create_rcu_free(list))) {
+		rsbac_printk(KERN_WARNING "rcu_free_item_chain(): cannot allocate rcu_free_head for list %s, loosing chain %p!\n",
+			     list->name, item_chain);
+		return;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_item_chain_calls++;
+#endif
+	if (!list->rcu_free->item_chain) {
+		list->rcu_free->item_chain = item_chain;
+	} else { 
+		while (item_chain) {
+			rcu_free(list, item_chain);
+			item_chain = item_chain->next;
+		}
+	}
+}
+
+/* Call spinlocked */
+static void rcu_free_lol_subitem_chain(struct rsbac_list_lol_reg_item_t * list,
+				struct rsbac_list_item_t * subitem_chain)
+{
+	if (!subitem_chain)
+		return;
+	if (unlikely(!create_rcu_free_lol(list))) {
+		rsbac_printk(KERN_WARNING "rcu_free_lol_subitem_chain(): cannot allocate rcu_free_head for list of lists %s, loosing subchain %p!\n",
+			     list->name, subitem_chain);
+		return;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_lol_subitem_chain_calls++;
+#endif
+	if (!list->rcu_free->lol_item_subchain) {
+		list->rcu_free->lol_item_subchain = subitem_chain;
+	} else { 
+		while (subitem_chain) {
+			rcu_free_lol_sub(list, subitem_chain);
+			subitem_chain = subitem_chain->next;
+		}
+	}
+}
+
+/* Call spinlocked */
+static void rcu_free_lol_item_chain(struct rsbac_list_lol_reg_item_t * list,
+				struct rsbac_list_lol_item_t * lol_item_chain)
+{
+	if (!lol_item_chain)
+		return;
+	if (unlikely(!create_rcu_free_lol(list))) {
+		rsbac_printk(KERN_WARNING "rcu_free_lol_item_chain(): cannot allocate rcu_free_head for list of lists %s, loosing chain %p!\n",
+			     list->name, lol_item_chain);
+		return;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_lol_item_chain_calls++;
+#endif
+	if (!list->rcu_free->lol_item_chain) {
+		list->rcu_free->lol_item_chain = lol_item_chain;
+	} else { 
+		struct rsbac_list_item_t * sub_item;
+
+		while (lol_item_chain) {
+			sub_item = lol_item_chain->head;
+			while (sub_item) {
+				rcu_free_lol_sub(list, sub_item);
+				sub_item = sub_item->next;
+			}
+			rcu_free_lol(list, lol_item_chain);
+			lol_item_chain = lol_item_chain->next;
+		}
+	}
+}
+
+/* Call unlocked */
+static void rcu_free_do_cleanup(struct rsbac_list_rcu_free_head_t * rcu_head)
+{
+	struct rsbac_list_rcu_free_item_t * rcu_item;
+	struct rsbac_list_rcu_free_item_t * rcu_next_item;
+	struct rsbac_list_item_t * item_chain;
+	struct rsbac_list_item_t * item_chain_next;
+
+	if (!rcu_head)
+		return;
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_do_cleanup_calls++;
+#endif
+	rcu_item = rcu_head->head;
+	if (rcu_head->slab) {
+		while (rcu_item) {
+			rsbac_sfree(rcu_head->slab, rcu_item->mem);
+			rcu_next_item = rcu_item->next;
+			rsbac_sfree(rcu_free_item_slab, rcu_item);
+			rcu_item = rcu_next_item;
+		}
+		item_chain = rcu_head->item_chain;
+		while (item_chain) {
+			item_chain_next = item_chain->next;
+			rsbac_sfree(rcu_head->slab, item_chain);
+			item_chain = item_chain_next;
+		}
+	} else {
+		while (rcu_item) {
+			rsbac_kfree(rcu_item->mem);
+			rcu_next_item = rcu_item->next;
+			rsbac_sfree(rcu_free_item_slab, rcu_item);
+			rcu_item = rcu_next_item;
+		}
+		item_chain = rcu_head->item_chain;
+		while (item_chain) {
+			item_chain_next = item_chain->next;
+			rsbac_kfree(item_chain);
+			item_chain = item_chain_next;
+		}
+	}
+	rsbac_sfree(rcu_free_head_slab, rcu_head);
+}
+
+/* Call unlocked */
+static void rcu_free_do_cleanup_lol(struct rsbac_list_rcu_free_head_lol_t * rcu_head)
+{
+	struct rsbac_list_rcu_free_item_t * rcu_item;
+	struct rsbac_list_rcu_free_item_t * rcu_next_item;
+	struct rsbac_list_lol_item_t * lol_item_chain;
+	struct rsbac_list_lol_item_t * lol_item_chain_next;
+	struct rsbac_list_item_t * lol_item_subchain;
+	struct rsbac_list_item_t * lol_item_subchain_next;
+
+	if (!rcu_head)
+		return;
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_do_cleanup_lol_calls++;
+#endif
+	rcu_item = rcu_head->head;
+	if (rcu_head->slab) {
+		while (rcu_item) {
+			rsbac_sfree(rcu_head->slab, rcu_item->mem);
+			rcu_next_item = rcu_item->next;
+			rsbac_sfree(rcu_free_item_slab, rcu_item);
+			rcu_item = rcu_next_item;
+		}
+		rcu_item = rcu_head->subhead;
+		while (rcu_item) {
+			rsbac_sfree(rcu_head->subslab, rcu_item->mem);
+			rcu_next_item = rcu_item->next;
+			rsbac_sfree(rcu_free_item_slab, rcu_item);
+			rcu_item = rcu_next_item;
+		}
+		lol_item_chain = rcu_head->lol_item_chain;
+		while (lol_item_chain) {
+			lol_item_subchain = lol_item_chain->head;
+			while (lol_item_subchain) {
+				lol_item_subchain_next = lol_item_subchain->next;
+				rsbac_sfree(rcu_head->subslab, lol_item_subchain);
+				lol_item_subchain = lol_item_subchain_next;
+			}
+			lol_item_chain_next = lol_item_chain->next;
+			rsbac_sfree(rcu_head->slab, lol_item_chain);
+			lol_item_chain = lol_item_chain_next;
+		}
+		lol_item_subchain = rcu_head->lol_item_subchain;
+		while (lol_item_subchain) {
+			lol_item_subchain_next = lol_item_subchain->next;
+			rsbac_sfree(rcu_head->subslab, lol_item_subchain);
+			lol_item_subchain = lol_item_subchain_next;
+		}
+	} else {
+		while (rcu_item) {
+			rsbac_kfree(rcu_item->mem);
+			rcu_next_item = rcu_item->next;
+			rsbac_sfree(rcu_free_item_slab, rcu_item);
+			rcu_item = rcu_next_item;
+		}
+		lol_item_chain = rcu_head->lol_item_chain;
+		while (lol_item_chain) {
+			lol_item_subchain = lol_item_chain->head;
+			while (lol_item_subchain) {
+				lol_item_subchain_next = lol_item_subchain->next;
+				rsbac_kfree(lol_item_subchain);
+				lol_item_subchain = lol_item_subchain_next;
+			}
+			lol_item_chain_next = lol_item_chain->next;
+			rsbac_kfree(lol_item_chain);
+			lol_item_chain = lol_item_chain_next;
+		}
+		lol_item_subchain = rcu_head->lol_item_subchain;
+		while (lol_item_subchain) {
+			lol_item_subchain_next = lol_item_subchain->next;
+			rsbac_kfree(lol_item_subchain);
+			lol_item_subchain = lol_item_subchain_next;
+		}
+	}
+	rsbac_sfree(rcu_free_head_lol_slab, rcu_head);
+}
+
+/* RCU callback, do not call directly. Called unlocked by RCU. */
+static void rcu_free_callback(struct rcu_head *rp)
+{
+	if (unlikely(!rp))
+		return;
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_callback_calls++;
+#endif
+	rcu_free_do_cleanup((struct rsbac_list_rcu_free_head_t *) rp);
+}
+
+/* RCU callback, do not call directly. Called unlocked by RCU. */
+static void rcu_free_callback_lol(struct rcu_head *rp)
+{
+	if (unlikely(!rp))
+		return;
+#ifdef CONFIG_RSBAC_LIST_STATS
+	rcu_free_callback_lol_calls++;
+#endif
+	rcu_free_do_cleanup_lol((struct rsbac_list_rcu_free_head_lol_t *) rp);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call unlocked */
+static void do_call_rcu(struct rsbac_list_rcu_free_head_t * rcu_head)
+{
+	if (rcu_head) {
+		rcu_callback_count++;
+		call_rcu(&rcu_head->rcu, rcu_free_callback);
+	}
+}
+/* Call unlocked */
+static void do_call_rcu_lol(struct rsbac_list_rcu_free_head_lol_t * rcu_head)
+{
+	if (rcu_head) {
+		rcu_callback_count++;
+		call_rcu(&rcu_head->rcu, rcu_free_callback_lol);
+	}
+}
+#endif
+
+/* Call unlocked */
+static void do_sync_rcu(struct rsbac_list_rcu_free_head_t * rcu_head)
+{
+	if (rcu_head) {
+		rcu_callback_count++;
+		if (rcu_callback_count < rsbac_list_rcu_rate)
+			call_rcu(&rcu_head->rcu, rcu_free_callback);
+		else {
+			synchronize_rcu();
+			rcu_free_do_cleanup(rcu_head);
+		}
+	}
+}
+
+/* Call unlocked */
+static void do_sync_rcu_lol(struct rsbac_list_rcu_free_head_lol_t * rcu_head)
+{
+	if (rcu_head) {
+		rcu_callback_count++;
+		if (rcu_callback_count < rsbac_list_rcu_rate)
+			call_rcu(&rcu_head->rcu, rcu_free_callback_lol);
+		else {
+			synchronize_rcu();
+			rcu_free_do_cleanup_lol(rcu_head);
+		}
+	}
+}
+
+/* List handling */
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_item_compare(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* NULL or not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_item_memcmp(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *lookup_item(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	if (unlikely(!list || !desc || !hashed))
+		return NULL;
+
+	if (list->compare)
+		return lookup_item_compare(list, hashed, hash, desc);
+	else
+		return lookup_item_memcmp(list, hashed, hash, desc);
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *lookup_item_compare_locked(
+	struct rsbac_list_reg_item_t *list, void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc || !list->compare))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr) {
+		curr = list->hashed[hash].head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].curr, curr);
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* NULL or not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static inline struct rsbac_list_item_t *lookup_item_memcmp_locked(struct
+						    rsbac_list_reg_item_t
+						    *list, void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr) {
+		curr = list->hashed[hash].head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].curr, curr);
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_item_t *lookup_item_locked(struct rsbac_list_reg_item_t
+					     *list, void *desc)
+{
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if (list->compare)
+		return lookup_item_compare_locked(list, desc);
+	else
+		return lookup_item_memcmp_locked(list, desc);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *ta_lookup_item_compare(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	u_int hash,
+ 	void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].ta_curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].ta_head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* NULL or not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *ta_lookup_item_memcmp(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].ta_curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].ta_head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *ta_lookup_item(
+	const rsbac_list_ta_number_t ta_number,
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if (!hashed[hash].ta_copied)
+		return lookup_item(list, hashed, hash, desc);
+	if (hashed[hash].ta_copied != ta_number)
+		return NULL;
+
+	if (list->compare)
+		return ta_lookup_item_compare(list, hashed, hash, desc);
+	else
+		return ta_lookup_item_memcmp(list, hashed, hash, desc);
+}
+
+static inline struct rsbac_list_item_t *ta_lookup_item_compare_locked(
+	struct rsbac_list_reg_item_t *list, void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc || !list->compare))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr) {
+		curr = list->hashed[hash].ta_head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].ta_curr, curr);
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* NULL or not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static inline struct rsbac_list_item_t *ta_lookup_item_memcmp_locked(struct
+						       rsbac_list_reg_item_t
+						       *list, void *desc)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr) {
+		curr = list->hashed[hash].ta_head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].ta_curr, curr);
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_item_t *ta_lookup_item_locked(const rsbac_list_ta_number_t ta_number,
+						struct
+						rsbac_list_reg_item_t
+						*list, void *desc)
+{
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (!list->hashed[hash].ta_copied)
+		return lookup_item_locked(list, desc);
+	if (list->hashed[hash].ta_copied != ta_number)
+		return NULL;
+
+	if (list->compare)
+		return ta_lookup_item_compare_locked(list, desc);
+	else
+		return ta_lookup_item_memcmp_locked(list, desc);
+}
+#endif
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_item_data_compare(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_item_data_memcmp(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *lookup_item_data(
+	struct rsbac_list_reg_item_t * list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if (compare)
+		return lookup_item_data_compare(list, hashed, hash_bits, data, compare);
+	else
+		return lookup_item_data_memcmp(list, hashed, hash_bits, data);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *ta_lookup_item_data_compare(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_reg_item_t * list,
+		struct rsbac_list_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *ta_lookup_item_data_memcmp(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_reg_item_t *list,
+		struct rsbac_list_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *ta_lookup_item_data(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_reg_item_t *list,
+		struct rsbac_list_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if(!ta_number)
+		return lookup_item_data(list, hashed, hash_bits, data, compare);
+	if (compare)
+		return ta_lookup_item_data_compare(ta_number, list, hashed, hash_bits, data, compare);
+	else
+		return ta_lookup_item_data_memcmp(ta_number, list, hashed, hash_bits, data);
+}
+#endif
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_item_data_compare_selector(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_item_data_memcmp_selector(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *lookup_item_data_selector(
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if (compare)
+		return lookup_item_data_compare_selector(list,
+						hashed, hash_bits,
+						data, compare,
+						selector,
+						param);
+	else
+		return lookup_item_data_memcmp_selector(list,
+						hashed, hash_bits,
+						data,
+						selector,
+						param);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *ta_lookup_item_data_compare_selector(
+	const rsbac_list_ta_number_t ta_number,
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *ta_lookup_item_data_memcmp_selector(
+	const rsbac_list_ta_number_t ta_number,
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *ta_lookup_item_data_selector(
+	const rsbac_list_ta_number_t ta_number,
+	struct rsbac_list_reg_item_t *list,
+	struct rsbac_list_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if(!ta_number)
+		return lookup_item_data_selector(
+			list, hashed, hash_bits,
+			data, compare,
+			selector, param);
+	if (compare)
+		return ta_lookup_item_data_compare_selector(
+			ta_number, list,
+			hashed, hash_bits,
+			data, compare,
+			selector, param);
+	else
+		return ta_lookup_item_data_memcmp_selector(
+			ta_number, list,
+			hashed, hash_bits,
+			data,
+			selector, param);
+}
+#endif
+
+/* list of lists - subitems */
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_lol_subitem_compare(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_item_t *sublist,
+	void *subdesc,
+	rsbac_list_compare_function_t compare)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	if (unlikely(!list || !sublist || !subdesc || !compare))
+		return NULL;
+
+	curr = rcu_dereference(sublist->curr);
+	if (!curr) {
+		curr = rcu_dereference(sublist->head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = compare(&curr[1], subdesc);
+	if (compres) {
+		if (compres < 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr && (compare(&curr[1], subdesc) < 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr && (compare(&curr[1], subdesc) > 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!compare(&curr[1], subdesc))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_lol_subitem_memcmp(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_item_t *sublist,
+	void *subdesc)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	if (unlikely(!list || !sublist || !subdesc))
+		return NULL;
+
+	curr = rcu_dereference(sublist->curr);
+	if (!curr) {
+		curr = rcu_dereference(sublist->head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(subdesc, &curr[1], list->info.subdesc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr
+			       && (memcmp(subdesc,
+					  &curr[1],
+					  list->info.subdesc_size) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr
+			       && (memcmp(subdesc,
+					  &curr[1],
+					  list->info.subdesc_size) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!memcmp(subdesc,
+				    &curr[1], list->info.subdesc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_item_t *lookup_lol_subitem(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_item_t *sublist,
+	void *subdesc)
+{
+	if (unlikely(!list || !sublist || !subdesc))
+		return NULL;
+
+	if (list->subcompare)
+		return lookup_lol_subitem_compare(list, sublist, subdesc,
+						  list->subcompare);
+	else
+		return lookup_lol_subitem_memcmp(list, sublist, subdesc);
+}
+
+static inline struct rsbac_list_item_t *lookup_lol_subitem_compare_locked(struct
+							    rsbac_list_lol_reg_item_t
+							    *list,
+							    struct
+							    rsbac_list_lol_item_t
+							    *sublist,
+							    void *subdesc,
+							    rsbac_list_compare_function_t
+							    compare)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	if (unlikely(!list || !sublist || !subdesc || !compare))
+		return NULL;
+
+	curr = sublist->curr;
+	if (!curr) {
+		curr = sublist->head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = compare(&curr[1], subdesc);
+	if (compres) {
+		if (compres < 0) {
+			curr = curr->next;
+			while (curr && (compare(&curr[1], subdesc) < 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr && (compare(&curr[1], subdesc) > 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(sublist->curr, curr);
+			if (!compare(&curr[1], subdesc))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static inline struct rsbac_list_item_t *lookup_lol_subitem_memcmp_locked(struct
+							   rsbac_list_lol_reg_item_t
+							   *list,
+							   struct
+							   rsbac_list_lol_item_t
+							   *sublist,
+							   void *subdesc)
+{
+	struct rsbac_list_item_t *curr;
+	int compres;
+
+	if (unlikely(!list || !sublist || !subdesc))
+		return NULL;
+
+	curr = sublist->curr;
+	if (!curr) {
+		curr = sublist->head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(subdesc, &curr[1], list->info.subdesc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr
+			       && (memcmp(subdesc,
+					  &curr[1],
+					  list->info.subdesc_size) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr
+			       && (memcmp(subdesc,
+					  &curr[1],
+					  list->info.subdesc_size) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(sublist->curr, curr);
+			if (!memcmp(subdesc,
+				    &curr[1], list->info.subdesc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_item_t *lookup_lol_subitem_locked(struct
+						    rsbac_list_lol_reg_item_t
+						    *list,
+						    struct
+						    rsbac_list_lol_item_t
+						    *sublist,
+						    void *subdesc)
+{
+	if (unlikely(!list || !sublist || !subdesc))
+		return NULL;
+
+	if (list->subcompare)
+		return lookup_lol_subitem_compare_locked(list, sublist, subdesc,
+						  list->subcompare);
+	else
+		return lookup_lol_subitem_memcmp_locked(list, sublist, subdesc);
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_item_t *lookup_lol_subitem_user_compare(struct
+								 rsbac_list_lol_reg_item_t
+								 *list,
+								 struct
+								 rsbac_list_lol_item_t
+								 *sublist,
+								 void
+								 *subdesc,
+								 rsbac_list_compare_function_t
+								 compare)
+{
+	struct rsbac_list_item_t *curr;
+
+	if (unlikely(!list || !sublist || !subdesc || !compare))
+		return NULL;
+
+	curr = rcu_dereference(sublist->head);
+	/* note: item desc is behind official struct */
+	while (curr) {
+		if (!compare(&curr[1], subdesc))
+			return curr;
+		curr = rcu_dereference(curr->next);
+	}
+	return curr;
+}
+
+/* list of lists - items */
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_compare(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_memcmp(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_lol_item_t *lookup_lol_item(
+	struct rsbac_list_lol_reg_item_t * list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	if (unlikely(!list || !desc || !hashed))
+		return NULL;
+
+	if (list->compare)
+		return lookup_lol_item_compare(list, hashed, hash, desc);
+	else
+		return lookup_lol_item_memcmp(list, hashed, hash, desc);
+}
+
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_compare_locked(struct
+							     rsbac_list_lol_reg_item_t
+							     *list,
+							     void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc || !list->compare))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr) {
+		curr = list->hashed[hash].head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].curr, curr);
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_memcmp_locked(struct
+							    rsbac_list_lol_reg_item_t
+							    *list,
+							    void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr) {
+		curr = list->hashed[hash].head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].curr, curr);
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_lol_item_t *lookup_lol_item_locked(struct
+						     rsbac_list_lol_reg_item_t
+						     *list, void *desc)
+{
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if (list->compare)
+		return lookup_lol_item_compare_locked(list, desc);
+	else
+		return lookup_lol_item_memcmp_locked(list, desc);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_compare(
+	struct rsbac_list_lol_reg_item_t * list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].ta_curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].ta_head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_memcmp(
+	struct rsbac_list_lol_reg_item_t * list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int compres;
+
+	curr = rcu_dereference(hashed[hash].ta_curr);
+	if (!curr) {
+		curr = rcu_dereference(hashed[hash].ta_head);
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = rcu_dereference(curr->next);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = rcu_dereference(curr->next);
+		} else {
+			curr = rcu_dereference(curr->prev);
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = rcu_dereference(curr->prev);
+		}
+		if (curr) {
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_lol_item_t *ta_lookup_lol_item(
+	const rsbac_list_ta_number_t ta_number,
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	u_int hash,
+	void *desc)
+{
+	if (unlikely(!list || !desc || !hashed))
+		return NULL;
+
+	if (!hashed[hash].ta_copied)
+		return lookup_lol_item(list, hashed, hash, desc);
+	if (hashed[hash].ta_copied != ta_number)
+		return NULL;
+
+	if (list->compare)
+		return ta_lookup_lol_item_compare(list, hashed, hash, desc);
+	else
+		return ta_lookup_lol_item_memcmp(list, hashed, hash, desc);
+}
+
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_compare_locked(struct
+								rsbac_list_lol_reg_item_t
+								*list,
+								void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc || !list->compare))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr) {
+		curr = list->hashed[hash].ta_head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = list->compare(desc, &curr[1]);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr && (list->compare(desc, &curr[1]) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr && (list->compare(desc, &curr[1]) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].ta_curr, curr);
+			if (!list->compare(desc, &curr[1]))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_memcmp_locked(struct
+							       rsbac_list_lol_reg_item_t
+							       *list,
+							       void *desc)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+	int compres;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr) {
+		curr = list->hashed[hash].ta_head;
+		if (!curr)
+			return NULL;
+	}
+	/* if current item is not the right one, search... */
+	/* note: item desc is behind official struct */
+	compres = memcmp(desc, &curr[1], list->info.desc_size);
+	if (compres) {
+		if (compres > 0) {
+			curr = curr->next;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) > 0)
+			    )
+				curr = curr->next;
+		} else {
+			curr = curr->prev;
+			while (curr
+			       && (memcmp(desc,
+					  &curr[1],
+					  list->info.desc_size) < 0)
+			    )
+				curr = curr->prev;
+		}
+		if (curr) {
+			rcu_assign_pointer(list->hashed[hash].ta_curr, curr);
+			if (!memcmp(desc, &curr[1], list->info.desc_size))
+				return curr;
+		}
+		/* not found */
+		return NULL;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_lol_item_t
+    *ta_lookup_lol_item_locked(const rsbac_list_ta_number_t ta_number,
+			struct rsbac_list_lol_reg_item_t *list, void *desc)
+{
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (!list->hashed[hash].ta_copied)
+		return lookup_lol_item_locked(list, desc);
+	if (list->hashed[hash].ta_copied != ta_number)
+		return NULL;
+
+	if (list->compare)
+		return ta_lookup_lol_item_compare_locked(list, desc);
+	else
+		return ta_lookup_lol_item_memcmp_locked(list, desc);
+}
+#endif
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_data_compare(
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_data_memcmp(
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_lol_item_t *lookup_lol_item_data(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if (compare)
+		return lookup_lol_item_data_compare(list, hashed, hash_bits, data, compare);
+	else
+		return lookup_lol_item_data_memcmp(list, hashed, hash_bits, data);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_data_compare(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_data_memcmp(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_lol_item_t *ta_lookup_lol_item_data(
+	const rsbac_list_ta_number_t ta_number,
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t compare)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if(!ta_number)
+		return lookup_lol_item_data(list, hashed, hash_bits, data, compare);
+	if (compare)
+		return ta_lookup_lol_item_data_compare(ta_number, list,
+							hashed, hash_bits,
+							data,
+							compare);
+	else
+		return ta_lookup_lol_item_data_memcmp(ta_number, list,
+							hashed, hash_bits,
+							data);
+}
+#endif
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_data_compare_selector(
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *lookup_lol_item_data_memcmp_selector(
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	if (unlikely(!list || !data))
+		return NULL;
+
+	for(i=0; i<nr_hashes; i++) {
+		curr = rcu_dereference(hashed[i].head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_lol_item_t *lookup_lol_item_data_selector(
+	struct rsbac_list_lol_reg_item_t *list,
+	struct rsbac_list_lol_hashed_t * hashed,
+	const __u8 hash_bits,
+	void *data,
+	rsbac_list_data_compare_function_t
+	compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if (compare)
+		return lookup_lol_item_data_compare_selector(list, hashed, hash_bits, data, compare, selector, param);
+	else
+		return lookup_lol_item_data_memcmp_selector(list, hashed, hash_bits, data, selector, param);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_data_compare_selector(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || compare((char *) curr + sizeof(*curr) +
+				      list->info.desc_size, data)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_data_memcmp_selector(
+		const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	struct rsbac_list_lol_item_t *curr;
+	int i;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	for(i=0; i<nr_hashes; i++) {
+		if (!hashed[i].ta_copied || hashed[i].ta_copied != ta_number)
+			curr = rcu_dereference(hashed[i].head);
+		else
+			curr = rcu_dereference(hashed[i].ta_head);
+
+		/* note: item desc is behind official struct */
+		while (curr
+		       && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
+			   || memcmp(data,
+				     &curr[1] + list->info.desc_size,
+				     list->info.data_size)
+			   || !selector((char *) curr + sizeof(*curr), param)
+		       )
+		    )
+			curr = rcu_dereference(curr->next);
+		if(curr)
+			return curr;
+	}
+	return NULL;
+}
+
+/* Call RCU locked */
+static struct rsbac_list_lol_item_t
+    *ta_lookup_lol_item_data_selector(const rsbac_list_ta_number_t ta_number,
+		struct rsbac_list_lol_reg_item_t *list,
+		struct rsbac_list_lol_hashed_t * hashed,
+		const __u8 hash_bits,
+		void *data,
+		rsbac_list_data_compare_function_t compare,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	if (unlikely(!list || !data || !hashed))
+		return NULL;
+
+	if(likely(!ta_number))
+		return lookup_lol_item_data_selector(list, hashed, hash_bits, data, compare,
+				selector, param);
+	if (compare)
+		return ta_lookup_lol_item_data_compare_selector(ta_number, list,
+				hashed, hash_bits, data,
+				compare, selector, param);
+	else
+		return ta_lookup_lol_item_data_memcmp_selector(ta_number,
+				list, hashed, hash_bits,
+				data, selector, param);
+}
+#endif
+
+/* Registration lookup */
+
+static struct rsbac_list_reg_item_t *lookup_reg(struct rsbac_list_reg_item_t *handle)
+{
+	struct rsbac_list_reg_item_t *curr = srcu_dereference(reg_head.curr, &reg_list_srcu);
+
+	if (unlikely(!handle))
+		return NULL;
+	/* if there is no current item or it is not the right one, search... */
+	if (curr != handle) {
+		curr = srcu_dereference(reg_head.head, &reg_list_srcu);
+		while (curr && curr != handle)
+			curr = srcu_dereference(curr->next, &reg_list_srcu);
+		if (!curr)
+			rsbac_pr_debug(lists,
+				       "Lookup of unknown list handle %p\n",
+				       handle);
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_reg_item_t *lookup_reg_name(char *name,
+						     kdev_t device)
+{
+	struct rsbac_list_reg_item_t *curr = srcu_dereference(reg_head.curr, &reg_list_srcu);
+
+	if (unlikely(!name))
+		return NULL;
+	/* if there is no current item or it is not the right one, search... */
+	if (!curr || (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
+		      || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
+		      || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
+	    )
+	    ) {
+		curr = srcu_dereference(reg_head.head, &reg_list_srcu);
+		while (curr
+		       &&
+		       (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
+			|| (RSBAC_MAJOR(curr->device) !=
+			    RSBAC_MAJOR(device))
+			|| (RSBAC_MINOR(curr->device) !=
+			    RSBAC_MINOR(device))
+		       )
+		    )
+			curr = srcu_dereference(curr->next, &reg_list_srcu);
+		if (!curr)
+			rsbac_pr_debug(lists, "Lookup of unknown list name %s "
+				       "on device %02u:%02u\n", name,
+				       RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/* List of lists registration lookup */
+
+static struct rsbac_list_lol_reg_item_t *lookup_lol_reg(struct
+							rsbac_list_lol_reg_item_t
+							*handle)
+{
+	struct rsbac_list_lol_reg_item_t *curr = srcu_dereference(lol_reg_head.curr, &lol_reg_list_srcu);
+
+	if (unlikely(!handle))
+		return NULL;
+	/* if there is no current item or it is not the right one, search... */
+	if (curr != handle) {
+		curr = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+		while (curr && curr != handle)
+			curr = srcu_dereference(curr->next, &lol_reg_list_srcu);
+		if (!curr)
+			rsbac_pr_debug(lists, "Lookup of unknown list handle %p\n",
+				     handle);
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_list_lol_reg_item_t *lookup_lol_reg_name(char *name,
+							     kdev_t device)
+{
+	struct rsbac_list_lol_reg_item_t *curr = srcu_dereference(lol_reg_head.curr, &lol_reg_list_srcu);
+
+	if (unlikely(!name))
+		return NULL;
+	/* if there is no current item or it is not the right one, search... */
+	if (!curr || (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
+		      || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
+		      || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
+	    )
+	    ) {
+		curr = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+		while (curr
+		       &&
+		       (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
+			|| (RSBAC_MAJOR(curr->device) !=
+			    RSBAC_MAJOR(device))
+			|| (RSBAC_MINOR(curr->device) !=
+			    RSBAC_MINOR(device))
+		       )
+		    )
+			curr = srcu_dereference(curr->next, &lol_reg_list_srcu);
+		if (!curr)
+			rsbac_pr_debug(lists, "Lookup of unknown list name %s "
+				       "on device %02u:%02u\n", name,
+				       RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/*************/
+/* Add items */
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *insert_item_compare(
+	struct rsbac_list_reg_item_t * list,
+	void *desc,
+	struct rsbac_list_item_t * new_item_p)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr)
+		curr = list->hashed[hash].head;
+	if ((list->compare(desc, &curr[1]) > 0)) {
+		curr = curr->next;
+		while (curr && (list->compare(desc, &curr[1]) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr && (list->compare(desc, &curr[1]) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].head;
+			rcu_assign_pointer(list->hashed[hash].head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].head, new_item_p);
+		}
+	}
+	list->hashed[hash].count++;
+	rcu_assign_pointer(list->hashed[hash].curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *insert_item_memcmp(struct
+						    rsbac_list_reg_item_t
+						    *list, void *desc,
+						    struct
+						    rsbac_list_item_t
+						    *new_item_p)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr)
+		curr = list->hashed[hash].head;
+	if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
+		curr = curr->next;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].head;
+			rcu_assign_pointer(list->hashed[hash].head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].head, new_item_p);
+		}
+	}
+	list->hashed[hash].count++;
+	rcu_assign_pointer(list->hashed[hash].curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_item_t *add_item(struct rsbac_list_reg_item_t
+					  *list, rsbac_time_t max_age,
+					  void *desc, void *data)
+{
+	struct rsbac_list_item_t *new_item_p = NULL;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+	if (unlikely(list->info.data_size && !data))
+		return NULL;
+
+	/* item desc and data are behind official struct */
+	if (list->slab)
+		new_item_p = rsbac_smalloc(list->slab);
+	else
+		new_item_p = rsbac_kmalloc(sizeof(*new_item_p)
+						+ list->info.desc_size
+						+ list->info.data_size);
+	if (unlikely(!new_item_p))
+		return NULL;
+
+	new_item_p->max_age = max_age;
+	/* item desc is behind official struct */
+	memcpy(&new_item_p[1], desc, list->info.desc_size);
+	/* item data is behind official struct and desc */
+	/* data might be empty! */
+	if (data && list->info.data_size)
+		memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
+		       list->info.desc_size, data, list->info.data_size);
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (!list->hashed[hash].head) {
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(list->hashed[hash].head, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].tail, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].curr, new_item_p);
+		list->hashed[hash].count = 1;
+		return new_item_p;
+	}
+	if(list->hashed[hash].count >= list->max_items_per_hash) {
+		rsbac_sfree(list->slab, new_item_p);
+		if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
+			rsbac_printk(KERN_WARNING "add_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
+			     list->name,
+			     hash,
+			     RSBAC_MAJOR(list->device),
+			     RSBAC_MINOR(list->device),
+			     list->max_items_per_hash);
+	  	return NULL;
+	}
+	if (list->compare)
+		return insert_item_compare(list, desc, new_item_p);
+	else
+		return insert_item_memcmp(list, desc, new_item_p);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+static void ta_remove_all_items(struct rsbac_list_reg_item_t *list, u_int hash);
+
+/* Call spinlocked */
+static int ta_copy(const rsbac_list_ta_number_t ta_number,
+		   struct rsbac_list_reg_item_t *list,
+		   u_int hash)
+{
+	struct rsbac_list_item_t *curr;
+	struct rsbac_list_item_t *new_item_p;
+	u_int item_size = sizeof(*new_item_p)
+	    + list->info.desc_size + list->info.data_size;
+
+	/* write access to ta_* is safe for readers as long as ta_copied is not set */
+	curr = list->hashed[hash].head;
+	if (curr) {
+		if (list->slab)
+			new_item_p = rsbac_smalloc(list->slab);
+		else
+			new_item_p = rsbac_kmalloc(item_size);
+		if (!new_item_p) {
+			ta_remove_all_items(list, hash);
+			return -RSBAC_ENOMEM;
+		}
+		memcpy(new_item_p, curr, item_size);
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		list->hashed[hash].ta_head = new_item_p;
+		list->hashed[hash].ta_tail = new_item_p;
+		list->hashed[hash].ta_curr = new_item_p;
+		list->hashed[hash].ta_count = 1;
+		curr = curr->next;
+	} else {
+		list->hashed[hash].ta_head = NULL;
+		list->hashed[hash].ta_tail = NULL;
+		list->hashed[hash].ta_curr = NULL;
+		list->hashed[hash].ta_count = 0;
+		list->hashed[hash].ta_copied = ta_number;
+		return 0;
+	}
+	while (curr) {
+		if (list->slab)
+			new_item_p = rsbac_smalloc(list->slab);
+		else
+			new_item_p = rsbac_kmalloc(item_size);
+		if (!new_item_p) {
+			ta_remove_all_items(list, hash);
+			return -RSBAC_ENOMEM;
+		}
+		memcpy(new_item_p, curr, item_size);
+		new_item_p->prev = list->hashed[hash].ta_tail;
+		new_item_p->next = NULL;
+		list->hashed[hash].ta_tail->next = new_item_p;
+		list->hashed[hash].ta_tail = new_item_p;
+		list->hashed[hash].ta_count++;
+		curr = curr->next;
+	}
+	list->hashed[hash].ta_copied = ta_number;
+	return 0;
+}
+
+static void ta_remove_all_lol_items(struct rsbac_list_lol_reg_item_t *list,
+				u_int hash);
+
+/* Call spinlocked */
+static int ta_lol_copy(const rsbac_list_ta_number_t ta_number,
+		       struct rsbac_list_lol_reg_item_t *list,
+		       u_int hash)
+{
+	struct rsbac_list_lol_item_t *curr;
+	struct rsbac_list_lol_item_t *new_item_p;
+	struct rsbac_list_item_t *sub_curr;
+	struct rsbac_list_item_t *new_subitem_p;
+	u_int item_size = sizeof(*new_item_p)
+	    + list->info.desc_size + list->info.data_size;
+	u_int subitem_size = sizeof(*new_subitem_p)
+	    + list->info.subdesc_size + list->info.subdata_size;
+
+	/* write access to ta_* is safe for readers as long as ta_copied is not set */
+	list->hashed[hash].ta_head = NULL;
+	list->hashed[hash].ta_tail = NULL;
+	list->hashed[hash].ta_curr = NULL;
+	list->hashed[hash].ta_count = 0;
+
+	curr = list->hashed[hash].head;
+	while (curr) {
+		if (list->slab)
+			new_item_p = rsbac_smalloc(list->slab);
+		else
+			new_item_p = rsbac_kmalloc(item_size);
+		if (!new_item_p) {
+			ta_remove_all_lol_items(list, hash);
+			return -RSBAC_ENOMEM;
+		}
+		memcpy(new_item_p, curr, item_size);
+		new_item_p->head = NULL;
+		new_item_p->tail = NULL;
+		new_item_p->curr = NULL;
+		new_item_p->count = 0;
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		sub_curr = curr->head;
+		while (sub_curr) {
+			if (list->subslab)
+				new_subitem_p = rsbac_smalloc(list->subslab);
+			else
+				new_subitem_p = rsbac_kmalloc(subitem_size);
+			if (!new_subitem_p) {
+				ta_remove_all_lol_items(list, hash);
+				rsbac_sfree(list->slab, new_item_p);
+				return -RSBAC_ENOMEM;
+			}
+			memcpy(new_subitem_p, sub_curr, subitem_size);
+			new_subitem_p->prev = NULL;
+			new_subitem_p->next = NULL;
+			if (new_item_p->tail) {
+				new_subitem_p->prev = new_item_p->tail;
+				new_item_p->tail->next = new_subitem_p;
+				new_item_p->tail = new_subitem_p;
+				new_item_p->count++;
+			} else {
+				new_item_p->head = new_subitem_p;
+				new_item_p->tail = new_subitem_p;
+				new_item_p->count = 1;
+			}
+			sub_curr = sub_curr->next;
+		}
+		if (list->hashed[hash].ta_tail) {
+			new_item_p->prev = list->hashed[hash].ta_tail;
+			list->hashed[hash].ta_tail->next = new_item_p;
+			list->hashed[hash].ta_tail= new_item_p;
+			list->hashed[hash].ta_count++;
+		} else {
+			list->hashed[hash].ta_head = new_item_p;
+			list->hashed[hash].ta_tail = new_item_p;
+			list->hashed[hash].ta_curr = new_item_p;
+			list->hashed[hash].ta_count = 1;
+		}
+		curr = curr->next;
+	}
+	list->hashed[hash].ta_copied = ta_number;
+	return 0;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *ta_insert_item_compare(struct
+							rsbac_list_reg_item_t
+							*list, void *desc,
+							struct
+							rsbac_list_item_t
+							*new_item_p)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr)
+		curr = list->hashed[hash].ta_head;
+	if ((list->compare(desc, &curr[1]) > 0)) {
+		curr = curr->next;
+		while (curr && (list->compare(desc, &curr[1]) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].ta_tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].ta_tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr && (list->compare(desc, &curr[1]) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].ta_head;
+			rcu_assign_pointer(list->hashed[hash].ta_head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_head, new_item_p);
+		}
+	}
+	list->hashed[hash].ta_count++;
+	rcu_assign_pointer(list->hashed[hash].ta_curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *ta_insert_item_memcmp(struct
+						       rsbac_list_reg_item_t
+						       *list, void *desc,
+						       struct
+						       rsbac_list_item_t
+						       *new_item_p)
+{
+	struct rsbac_list_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr)
+		curr = list->hashed[hash].ta_head;
+	if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
+		curr = curr->next;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].ta_tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].ta_tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].ta_head;
+			rcu_assign_pointer(list->hashed[hash].ta_head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_head, new_item_p);
+		}
+	}
+	list->hashed[hash].ta_count++;
+	rcu_assign_pointer(list->hashed[hash].ta_curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_item_t *ta_add_item(const rsbac_list_ta_number_t
+					     ta_number,
+					     struct rsbac_list_reg_item_t
+					     *list, rsbac_time_t max_age,
+					     void *desc, void *data)
+{
+	struct rsbac_list_item_t *new_item_p = NULL;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+	if (unlikely(list->info.data_size && !data))
+		return NULL;
+	if (!ta_number)
+		return add_item(list, max_age, desc, data);
+	/* item desc and data are behind official struct */
+	if (list->slab)
+		new_item_p = rsbac_smalloc(list->slab);
+	else
+		new_item_p = rsbac_kmalloc(sizeof(*new_item_p)
+						+ list->info.desc_size
+						+ list->info.data_size);
+	if (unlikely(!new_item_p))
+		return NULL;
+	new_item_p->max_age = max_age;
+	/* item desc is behind official struct */
+	memcpy(&new_item_p[1], desc, list->info.desc_size);
+	/* item data is behind official struct and desc */
+	/* data might be empty! */
+	if (data && list->info.data_size)
+		memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
+		       list->info.desc_size, data, list->info.data_size);
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (!list->hashed[hash].ta_copied) {	/* copy list to ta_list */
+		if (ta_copy(ta_number, list, hash)) {
+			rsbac_sfree(list->slab, new_item_p);
+			return NULL;
+		}
+	} else {
+		if (list->hashed[hash].ta_copied != ta_number) {
+			rsbac_sfree(list->slab, new_item_p);
+			return NULL;
+		}
+	}
+
+	if (!list->hashed[hash].ta_head) {
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(list->hashed[hash].ta_head, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].ta_tail, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].ta_curr, new_item_p);
+		list->hashed[hash].ta_count = 1;
+		return new_item_p;
+	}
+	if (list->hashed[hash].ta_count >= list->max_items_per_hash) {
+		rsbac_sfree(list->slab, new_item_p);
+		if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
+			rsbac_printk(KERN_WARNING "ta_add_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
+			     list->name,
+			     hash,
+			     RSBAC_MAJOR(list->device),
+			     RSBAC_MINOR(list->device),
+			     list->max_items_per_hash);
+	  	return NULL;
+	}
+	if (list->compare)
+		return ta_insert_item_compare(list, desc, new_item_p);
+	else
+		return ta_insert_item_memcmp(list, desc, new_item_p);
+}
+#endif
+
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *insert_lol_subitem_compare(struct
+							    rsbac_list_lol_reg_item_t
+							    *list,
+							    struct
+							    rsbac_list_lol_item_t
+							    *sublist,
+							    void *subdesc,
+							    struct
+							    rsbac_list_item_t
+							    *new_item_p)
+{
+	struct rsbac_list_item_t *curr;
+
+	curr = sublist->curr;
+	if (!curr)
+		curr = sublist->head;
+	if ((list->subcompare(subdesc, &curr[1]) > 0)) {
+		curr = curr->next;
+		while (curr && (list->subcompare(subdesc, &curr[1]) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = sublist->tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(sublist->tail->next, new_item_p);
+			rcu_assign_pointer(sublist->tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr && (list->subcompare(subdesc, &curr[1]) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = sublist->head;
+			rcu_assign_pointer(sublist->head->prev, new_item_p);
+			rcu_assign_pointer(sublist->head, new_item_p);
+		}
+	}
+	sublist->count++;
+	rcu_assign_pointer(sublist->curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_item_t *insert_lol_subitem_memcmp(struct
+							   rsbac_list_lol_reg_item_t
+							   *list,
+							   struct
+							   rsbac_list_lol_item_t
+							   *sublist,
+							   void *subdesc,
+							   struct
+							   rsbac_list_item_t
+							   *new_item_p)
+{
+	struct rsbac_list_item_t *curr;
+
+	curr = sublist->curr;
+	if (!curr)
+		curr = sublist->head;
+	if (memcmp(subdesc, &curr[1], list->info.subdesc_size) > 0) {
+		curr = curr->next;
+		while (curr
+		       && (memcmp(subdesc,
+				  &curr[1], list->info.subdesc_size) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = sublist->tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(sublist->tail->next, new_item_p);
+			rcu_assign_pointer(sublist->tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr
+		       && (memcmp(subdesc,
+				  &curr[1], list->info.subdesc_size) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = sublist->head;
+			rcu_assign_pointer(sublist->head->prev, new_item_p);
+			rcu_assign_pointer(sublist->head, new_item_p);
+		}
+	}
+	sublist->count++;
+	rcu_assign_pointer(sublist->curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_item_t *add_lol_subitem(struct
+						 rsbac_list_lol_reg_item_t
+						 *list,
+						 struct
+						 rsbac_list_lol_item_t
+						 *sublist,
+						 rsbac_time_t max_age,
+						 void *subdesc,
+						 void *subdata)
+{
+	struct rsbac_list_item_t *new_item_p = NULL;
+
+	if (unlikely(!list || !sublist || !subdesc))
+		return NULL;
+	if (unlikely(list->info.subdata_size && !subdata))
+		return NULL;
+	/* item desc and data are behind official struct */
+	if (list->subslab)
+		new_item_p = rsbac_smalloc(list->subslab);
+	else
+		new_item_p = rsbac_kmalloc(sizeof(*new_item_p)
+						+ list->info.subdesc_size
+						+ list->info.subdata_size);
+	if (unlikely(!new_item_p))
+		return NULL;
+
+	new_item_p->max_age = max_age;
+	/* item desc is behind official struct */
+	memcpy(&new_item_p[1], subdesc, list->info.subdesc_size);
+	/* item data is behind official struct and desc */
+	/* subdata might be empty! */
+	if (subdata && list->info.subdata_size)
+		memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
+		       list->info.subdesc_size, subdata,
+		       list->info.subdata_size);
+
+	/* Sublist was empty */
+	if (!sublist->head) {
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(sublist->head, new_item_p);
+		rcu_assign_pointer(sublist->tail, new_item_p);
+		rcu_assign_pointer(sublist->curr, new_item_p);
+		sublist->count = 1;
+		return new_item_p;
+	}
+	if (sublist->count >= list->max_subitems) {
+		rsbac_sfree(list->slab, new_item_p);
+		if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
+			rsbac_printk(KERN_WARNING "add_lol_subitem(): cannot add subitem to sublist of %s on device %02u:%02u, would be more than %u subitems!\n",
+			     list->name,
+			     RSBAC_MAJOR(list->device),
+			     RSBAC_MINOR(list->device),
+			     list->max_subitems);
+	  	return NULL;
+	}
+	if (list->subcompare)
+		return insert_lol_subitem_compare(list, sublist, subdesc,
+						  new_item_p);
+	else
+		return insert_lol_subitem_memcmp(list, sublist, subdesc,
+						 new_item_p);
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_lol_item_t *insert_lol_item_compare(struct
+							     rsbac_list_lol_reg_item_t
+							     *list,
+							     void *desc,
+							     struct
+							     rsbac_list_lol_item_t
+							     *new_item_p)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr)
+		curr = list->hashed[hash].head;
+	if ((list->compare(desc, &curr[1]) > 0)) {
+		curr = curr->next;
+		while (curr && (list->compare(desc, &curr[1]) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr && (list->compare(desc, &curr[1]) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].head;
+			rcu_assign_pointer(list->hashed[hash].head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].head, new_item_p);
+		}
+	}
+	list->hashed[hash].count++;
+	rcu_assign_pointer(list->hashed[hash].curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_lol_item_t *insert_lol_item_memcmp(struct
+							    rsbac_list_lol_reg_item_t
+							    *list,
+							    void *desc,
+							    struct
+							    rsbac_list_lol_item_t
+							    *new_item_p)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].curr;
+	if (!curr)
+		curr = list->hashed[hash].head;
+	if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
+		curr = curr->next;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].head;
+			rcu_assign_pointer(list->hashed[hash].head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].head, new_item_p);
+		}
+	}
+	list->hashed[hash].count++;
+	rcu_assign_pointer(list->hashed[hash].curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_lol_item_t *add_lol_item(struct
+						  rsbac_list_lol_reg_item_t
+						  *list,
+						  rsbac_time_t max_age,
+						  void *desc, void *data)
+{
+	struct rsbac_list_lol_item_t *new_item_p = NULL;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+	if (unlikely(list->info.data_size && !data))
+		return NULL;
+	/* item desc and data are behind official struct */
+	if (list->slab)
+		new_item_p = rsbac_smalloc(list->slab);
+	else
+		new_item_p = rsbac_kmalloc(sizeof(*new_item_p)
+						+ list->info.desc_size
+						+ list->info.data_size);
+	if (unlikely(!new_item_p))
+		return NULL;
+
+	/* Init sublist */
+	new_item_p->head = NULL;
+	new_item_p->tail = NULL;
+	new_item_p->curr = NULL;
+	new_item_p->count = 0;
+	new_item_p->max_age = max_age;
+	/* item desc is behind official struct */
+	memcpy(&new_item_p[1], desc, list->info.desc_size);
+	/* item data is behind official struct and desc */
+	/* data might be empty! */
+	if (data && list->info.data_size)
+		memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
+		       list->info.desc_size, data, list->info.data_size);
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (!list->hashed[hash].head) {
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(list->hashed[hash].head, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].tail, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].curr, new_item_p);
+		list->hashed[hash].count = 1;
+		return new_item_p;
+	}
+	if (list->hashed[hash].count >= list->max_items_per_hash) {
+		rsbac_sfree(list->slab, new_item_p);
+		if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
+			rsbac_printk(KERN_WARNING "add_lol_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
+			     list->name,
+			     hash,
+			     RSBAC_MAJOR(list->device),
+			     RSBAC_MINOR(list->device),
+			     list->max_items_per_hash);
+	  	return NULL;
+	}
+	if (list->compare)
+		return insert_lol_item_compare(list, desc, new_item_p);
+	else
+		return insert_lol_item_memcmp(list, desc, new_item_p);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call spinlocked */
+static inline struct rsbac_list_lol_item_t *ta_insert_lol_item_compare(struct
+								rsbac_list_lol_reg_item_t
+								*list,
+								void *desc,
+								struct
+								rsbac_list_lol_item_t
+								*new_item_p)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr)
+		curr = list->hashed[hash].ta_head;
+	if ((list->compare(desc, &curr[1]) > 0)) {
+		curr = curr->next;
+		while (curr && (list->compare(desc, &curr[1]) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].ta_tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].ta_tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr && (list->compare(desc, &curr[1]) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].ta_head;
+			rcu_assign_pointer(list->hashed[hash].ta_head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_head, new_item_p);
+		}
+	}
+	list->hashed[hash].ta_count++;
+	rcu_assign_pointer(list->hashed[hash].ta_curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static inline struct rsbac_list_lol_item_t *ta_insert_lol_item_memcmp(struct
+							       rsbac_list_lol_reg_item_t
+							       *list,
+							       void *desc,
+							       struct
+							       rsbac_list_lol_item_t
+							       *new_item_p)
+{
+	struct rsbac_list_lol_item_t *curr;
+	u_int hash = 0;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	curr = list->hashed[hash].ta_curr;
+	if (!curr)
+		curr = list->hashed[hash].ta_head;
+	if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
+		curr = curr->next;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) > 0)
+		    )
+			curr = curr->next;
+		if (curr) {
+			/* insert before curr */
+			new_item_p->prev = curr->prev;
+			new_item_p->next = curr;
+			rcu_assign_pointer(curr->prev->next, new_item_p);
+			rcu_assign_pointer(curr->prev, new_item_p);
+		} else {
+			/* insert as last item */
+			new_item_p->prev = list->hashed[hash].ta_tail;
+			new_item_p->next = NULL;
+			rcu_assign_pointer(list->hashed[hash].ta_tail->next, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, new_item_p);
+		}
+	} else {
+		curr = curr->prev;
+		while (curr
+		       && (memcmp(desc,
+				  &curr[1], list->info.desc_size) < 0)
+		    )
+			curr = curr->prev;
+		if (curr) {
+			/* insert after curr */
+			new_item_p->prev = curr;
+			new_item_p->next = curr->next;
+			rcu_assign_pointer(curr->next->prev, new_item_p);
+			rcu_assign_pointer(curr->next, new_item_p);
+		} else {
+			/* insert as first item */
+			new_item_p->prev = NULL;
+			new_item_p->next = list->hashed[hash].ta_head;
+			rcu_assign_pointer(list->hashed[hash].ta_head->prev, new_item_p);
+			rcu_assign_pointer(list->hashed[hash].ta_head, new_item_p);
+		}
+	}
+	list->hashed[hash].ta_count++;
+	rcu_assign_pointer(list->hashed[hash].ta_curr, new_item_p);
+	return new_item_p;
+}
+
+/* Call spinlocked */
+static struct rsbac_list_lol_item_t *ta_add_lol_item(const rsbac_list_ta_number_t
+						     ta_number,
+						     struct
+						     rsbac_list_lol_reg_item_t
+						     *list,
+						     rsbac_time_t max_age,
+						     void *desc,
+						     void *data)
+{
+	struct rsbac_list_lol_item_t *new_item_p = NULL;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return NULL;
+	if (unlikely(list->info.data_size && !data))
+		return NULL;
+	if (!ta_number)
+		return add_lol_item(list, max_age, desc, data);
+	/* item desc and data are behind official struct */
+	if (list->slab)
+		new_item_p = rsbac_smalloc(list->slab);
+	else
+		new_item_p = rsbac_kmalloc(sizeof(*new_item_p)
+						+ list->info.desc_size
+						+ list->info.data_size);
+	if (unlikely(!new_item_p))
+		return NULL;
+
+	/* Init sublist */
+	new_item_p->head = NULL;
+	new_item_p->tail = NULL;
+	new_item_p->curr = NULL;
+	new_item_p->count = 0;
+	new_item_p->max_age = max_age;
+	new_item_p->prev = NULL;
+	new_item_p->next = NULL;
+	/* item desc is behind official struct */
+	memcpy(&new_item_p[1], desc, list->info.desc_size);
+	/* item data is behind official struct and desc */
+	/* data might be empty! */
+	if (data && list->info.data_size)
+		memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
+		       list->info.desc_size, data, list->info.data_size);
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (!list->hashed[hash].ta_copied) {	/* copy list to ta_list */
+		if (ta_lol_copy(ta_number, list, hash)) {
+			rsbac_sfree(list->slab, new_item_p);
+			return NULL;
+		}
+	} else {
+		if (list->hashed[hash].ta_copied != ta_number) {
+			rsbac_sfree(list->slab, new_item_p);
+			return NULL;
+		}
+	}
+
+	if (!list->hashed[hash].ta_head) {
+		rcu_assign_pointer(list->hashed[hash].ta_head, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].ta_tail, new_item_p);
+		rcu_assign_pointer(list->hashed[hash].ta_curr, new_item_p);
+		list->hashed[hash].ta_count = 1;
+		return (new_item_p);
+	}
+	if (list->hashed[hash].ta_count >= list->max_items_per_hash) {
+		rsbac_sfree(list->slab, new_item_p);
+		if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
+			rsbac_printk(KERN_WARNING "ta_add_lol_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
+			     list->name,
+			     hash,
+			     RSBAC_MAJOR(list->device),
+			     RSBAC_MINOR(list->device),
+			     list->max_items_per_hash);
+	  	return NULL;
+	}
+	if (list->compare)
+		return ta_insert_lol_item_compare(list, desc, new_item_p);
+	else
+		return ta_insert_lol_item_memcmp(list, desc, new_item_p);
+}
+#endif
+
+/* Add registration items */
+
+/* no locking needed */
+static inline struct rsbac_list_reg_item_t *create_reg(
+		struct rsbac_list_info_t *info_p,
+		u_int flags,
+		rsbac_list_compare_function_t * compare,
+		rsbac_list_get_conv_t * get_conv,
+		void *def_data,
+		char *name,
+		kdev_t device,
+		const __u8 hash_bits,
+		rsbac_list_hash_function_t hash_function,
+		char * old_name_base)
+{
+	struct rsbac_list_reg_item_t *new_item_p = NULL;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	if (!(new_item_p = rsbac_smalloc_clear_unlocked(reg_item_slab)))
+		return NULL;
+	if (!(new_item_p->hashed = rsbac_kmalloc_clear_unlocked(nr_hashes*sizeof(struct rsbac_list_hashed_t)))) {
+		rsbac_sfree(reg_item_slab, new_item_p);
+		return NULL;
+	}
+	new_item_p->info = *info_p;
+	if (!def_data)
+		flags &= ~RSBAC_LIST_DEF_DATA;
+	new_item_p->flags = flags;
+	new_item_p->compare = compare;
+	new_item_p->get_conv = get_conv;
+	new_item_p->rcu_free = NULL;
+	if (flags & RSBAC_LIST_DEF_DATA) {
+		new_item_p->def_data = rsbac_kmalloc_unlocked(info_p->data_size);
+		if (new_item_p->def_data)
+			memcpy(new_item_p->def_data, def_data,
+			       info_p->data_size);
+		else {
+			rsbac_kfree(new_item_p->hashed);
+			rsbac_sfree(reg_item_slab, new_item_p);
+			return NULL;
+		}
+	} else
+		new_item_p->def_data = NULL;
+	if (name) {
+		strncpy(new_item_p->name, name, RSBAC_LIST_MAX_FILENAME);
+		new_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
+	} else {
+		strcpy(new_item_p->name, RSBAC_LIST_NONAME);
+	}
+	new_item_p->hash_bits = hash_bits;
+	if (flags & RSBAC_LIST_NO_MAX)
+		new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS_LIMIT;
+	else
+		new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS;
+	new_item_p->hash_function = hash_function;
+	if (old_name_base) {
+		strncpy(new_item_p->old_name_base, old_name_base, RSBAC_LIST_MAX_FILENAME);
+		new_item_p->old_name_base[RSBAC_LIST_MAX_FILENAME] = 0;
+	} else {
+		new_item_p->old_name_base[0] = 0;
+	}
+	new_item_p->device = device;
+	spin_lock_init(&new_item_p->lock);
+	if (flags & RSBAC_LIST_OWN_SLAB) {
+		new_item_p->slabname = rsbac_kmalloc(RSBAC_MAX_SLABNAME);
+		if (!new_item_p->slabname) {
+			rsbac_kfree(new_item_p->hashed);
+			rsbac_sfree(reg_item_slab, new_item_p);
+			if (new_item_p->def_data)
+				rsbac_kfree(new_item_p->def_data);
+			return NULL;
+		}
+		if (device != RSBAC_AUTO_DEV) {
+			snprintf(new_item_p->slabname,
+				RSBAC_MAX_SLABNAME,
+				"%s-%02u:%02u",
+				name,
+				RSBAC_MAJOR(device), RSBAC_MINOR(device));
+		} else {
+			strncpy(new_item_p->slabname, name, RSBAC_MAX_SLABNAME);
+		}
+		new_item_p->slabname[RSBAC_MAX_SLABNAME - 1] = 0;
+		new_item_p->slab = rsbac_slab_create_rcu(new_item_p->slabname,
+			sizeof(struct rsbac_list_item_t) + info_p->desc_size + info_p->data_size);
+	} else {
+		new_item_p->slabname = NULL;
+		new_item_p->slab = NULL;
+	}
+	lockdep_set_class(&new_item_p->lock, &list_lock_class);
+	new_item_p->dirty = FALSE;
+	if (flags & RSBAC_LIST_NO_WRITE)
+		new_item_p->no_write = TRUE;
+	else
+		new_item_p->no_write = FALSE;
+	new_item_p->self = new_item_p;
+	return new_item_p;
+}
+
+/* locking needed */
+static struct rsbac_list_reg_item_t *add_reg(struct rsbac_list_reg_item_t
+					     *new_item_p)
+{
+	if (!reg_head.head) {
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(reg_head.head, new_item_p);
+		rcu_assign_pointer(reg_head.tail, new_item_p);
+		rcu_assign_pointer(reg_head.curr, new_item_p);
+		reg_head.count = 1;
+	} else {
+		new_item_p->prev = reg_head.tail;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(reg_head.tail->next, new_item_p);
+		rcu_assign_pointer(reg_head.tail, new_item_p);
+		rcu_assign_pointer(reg_head.curr, new_item_p);
+		reg_head.count++;
+	}
+	return new_item_p;
+}
+
+/* no locking needed */
+static inline struct rsbac_list_lol_reg_item_t *create_lol_reg(
+		struct rsbac_list_lol_info_t *info_p,
+		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,
+		void *def_data,
+		void *def_subdata,
+		char *name,
+		kdev_t device,
+		const __u8 hash_bits,
+		rsbac_list_hash_function_t hash_function,
+		char * old_name_base)
+{
+	struct rsbac_list_lol_reg_item_t *new_item_p = NULL;
+	const u_int nr_hashes = 1 << hash_bits;
+
+	if (!(new_item_p = rsbac_smalloc_clear_unlocked(lol_reg_item_slab)))
+		return NULL;
+	if (!(new_item_p->hashed = rsbac_kmalloc_clear_unlocked(nr_hashes*sizeof(struct rsbac_list_lol_hashed_t)))) {
+		rsbac_sfree(lol_reg_item_slab, new_item_p);
+		return NULL;
+	}
+	new_item_p->info = *info_p;
+	if (info_p->data_size && !def_data)
+		flags &= ~RSBAC_LIST_DEF_DATA;
+	if (!def_subdata)
+		flags &= ~RSBAC_LIST_DEF_SUBDATA;
+	new_item_p->flags = flags;
+	new_item_p->compare = compare;
+	new_item_p->subcompare = subcompare;
+	new_item_p->get_conv = get_conv;
+	new_item_p->get_subconv = get_subconv;
+	new_item_p->rcu_free = NULL;
+	if ((flags & RSBAC_LIST_DEF_DATA)
+	    && (info_p->data_size)
+	    ) {
+		new_item_p->def_data = rsbac_kmalloc_unlocked(info_p->data_size);
+		if (new_item_p->def_data)
+			memcpy(new_item_p->def_data, def_data,
+			       info_p->data_size);
+		else {
+			rsbac_kfree(new_item_p->hashed);
+			rsbac_sfree(lol_reg_item_slab, new_item_p);
+			return NULL;
+		}
+	} else
+		new_item_p->def_data = NULL;
+	if ((flags & RSBAC_LIST_DEF_SUBDATA)
+	    && (info_p->subdata_size)
+	   ) {
+		new_item_p->def_subdata =
+		    rsbac_kmalloc_unlocked(info_p->subdata_size);
+		if (new_item_p->def_subdata)
+			memcpy(new_item_p->def_subdata, def_subdata,
+			       info_p->subdata_size);
+		else {
+			if (new_item_p->def_data)
+				rsbac_kfree(new_item_p->def_data);
+			rsbac_kfree(new_item_p->hashed);
+			rsbac_sfree(lol_reg_item_slab, new_item_p);
+			return NULL;
+		}
+	} else
+		new_item_p->def_subdata = NULL;
+	if (name) {
+		strncpy(new_item_p->name, name, RSBAC_LIST_MAX_FILENAME);
+		new_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
+	} else {
+		strcpy(new_item_p->name, RSBAC_LIST_NONAME);
+	}
+	new_item_p->hash_bits = hash_bits;
+	if (flags & RSBAC_LIST_NO_MAX) {
+		new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS_LIMIT;
+		new_item_p->max_subitems = RSBAC_LIST_MAX_NR_ITEMS_LIMIT;
+	} else {
+		new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS;
+		new_item_p->max_subitems = RSBAC_LIST_MAX_NR_SUBITEMS;
+	}
+	new_item_p->hash_function = hash_function;
+	if (old_name_base) {
+		strncpy(new_item_p->old_name_base, old_name_base, RSBAC_LIST_MAX_FILENAME);
+		new_item_p->old_name_base[RSBAC_LIST_MAX_FILENAME] = 0;
+	} else
+		new_item_p->old_name_base[0] = 0;
+	new_item_p->device = device;
+	spin_lock_init(&new_item_p->lock);
+	if (flags & RSBAC_LIST_OWN_SLAB) {
+		new_item_p->slabname = rsbac_kmalloc(RSBAC_MAX_SLABNAME);
+		if (!new_item_p->slabname) {
+			rsbac_kfree(new_item_p->hashed);
+			rsbac_sfree(lol_reg_item_slab, new_item_p);
+			if (new_item_p->def_data)
+				rsbac_kfree(new_item_p->def_data);
+			if (new_item_p->def_subdata)
+				rsbac_kfree(new_item_p->def_subdata);
+			return NULL;
+		}
+		new_item_p->subslabname = rsbac_kmalloc(RSBAC_MAX_SLABNAME);
+		if (!new_item_p->subslabname) {
+			rsbac_kfree(new_item_p->hashed);
+			rsbac_sfree(lol_reg_item_slab, new_item_p);
+			if (new_item_p->def_data)
+				rsbac_kfree(new_item_p->def_data);
+			if (new_item_p->def_subdata)
+				rsbac_kfree(new_item_p->def_subdata);
+			if (new_item_p->slabname)
+				rsbac_kfree(new_item_p->slabname);
+			return NULL;
+		}
+		if (device != RSBAC_AUTO_DEV) {
+			snprintf(new_item_p->slabname,
+				RSBAC_MAX_SLABNAME,
+				"%s-%02u:%02u",
+				name,
+				RSBAC_MAJOR(device), RSBAC_MINOR(device));
+			snprintf(new_item_p->subslabname,
+				RSBAC_MAX_SLABNAME,
+				"%s-s-%02u:%02u",
+				name,
+				RSBAC_MAJOR(device), RSBAC_MINOR(device));
+		} else {
+			strncpy(new_item_p->slabname, name, RSBAC_MAX_SLABNAME);
+			snprintf(new_item_p->subslabname,
+				RSBAC_MAX_SLABNAME,
+				"%s-s",
+				name);
+		}
+		new_item_p->slabname[RSBAC_MAX_SLABNAME - 1] = 0;
+		new_item_p->subslabname[RSBAC_MAX_SLABNAME - 1] = 0;
+		new_item_p->slab = rsbac_slab_create_rcu(new_item_p->slabname,
+				sizeof(struct rsbac_list_lol_item_t) + info_p->desc_size + info_p->data_size);
+		new_item_p->subslab = rsbac_slab_create_rcu(new_item_p->subslabname,
+				sizeof(struct rsbac_list_item_t) + info_p->subdesc_size + info_p->subdata_size);
+	} else {
+		new_item_p->slabname = NULL;
+		new_item_p->subslabname = NULL;
+		new_item_p->slab = NULL;
+		new_item_p->subslab = NULL;
+	}
+	lockdep_set_class(&new_item_p->lock, &list_lock_class);
+	new_item_p->dirty = FALSE;
+	if (flags & RSBAC_LIST_NO_WRITE)
+		new_item_p->no_write = TRUE;
+	else
+		new_item_p->no_write = FALSE;
+	new_item_p->self = new_item_p;
+	return new_item_p;
+}
+
+/* locking needed */
+static struct rsbac_list_lol_reg_item_t *add_lol_reg(struct
+						     rsbac_list_lol_reg_item_t
+						     *new_item_p)
+{
+	if (!lol_reg_head.head) {
+		new_item_p->prev = NULL;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(lol_reg_head.head, new_item_p);
+		rcu_assign_pointer(lol_reg_head.tail, new_item_p);
+		rcu_assign_pointer(lol_reg_head.curr, new_item_p);
+		lol_reg_head.count = 1;
+	} else {
+		new_item_p->prev = lol_reg_head.tail;
+		new_item_p->next = NULL;
+		rcu_assign_pointer(lol_reg_head.tail->next, new_item_p);
+		rcu_assign_pointer(lol_reg_head.tail, new_item_p);
+		rcu_assign_pointer(lol_reg_head.curr, new_item_p);
+		lol_reg_head.count++;
+	}
+	return new_item_p;
+}
+
+/* Removing items */
+
+/* Call spinlocked */
+static inline void do_remove_item(struct rsbac_list_reg_item_t *list,
+			   struct rsbac_list_item_t *item_p,
+			   u_int hash)
+{
+	if (unlikely(!list || !item_p))
+		return;
+
+	/* curr is no longer valid -> reset */
+	if (list->hashed[hash].curr == item_p)
+		rcu_assign_pointer(list->hashed[hash].curr, NULL);
+	if ((list->hashed[hash].head == item_p)) {	/* item is head */
+		if ((list->hashed[hash].tail == item_p)) {	/* item is head and tail = only item -> list will be empty */
+			rcu_assign_pointer(list->hashed[hash].head, NULL);
+			rcu_assign_pointer(list->hashed[hash].tail, NULL);
+		} else {	/* item is head, but not tail -> next item becomes head */
+			rcu_assign_pointer(item_p->next->prev, NULL);
+			rcu_assign_pointer(list->hashed[hash].head, item_p->next);
+		}
+	} else {		/* item is not head */
+		if ((list->hashed[hash].tail == item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+			rcu_assign_pointer(item_p->prev->next, NULL);
+			rcu_assign_pointer(list->hashed[hash].tail, item_p->prev);
+		} else {	/* item is neither head nor tail -> item is cut out */
+			rcu_assign_pointer(item_p->prev->next, item_p->next);
+			rcu_assign_pointer(item_p->next->prev, item_p->prev);
+		}
+	}
+	/* adjust counter */
+	list->hashed[hash].count--;
+	/* now we can remove the item from memory */
+	rcu_free(list, item_p);
+}
+
+/* Call spinlocked */
+static void remove_item(struct rsbac_list_reg_item_t *list, void *desc)
+{
+	struct rsbac_list_item_t *item_p;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return;
+	/* first we must locate the item. */
+	if ((item_p = lookup_item_locked(list, desc))) {
+		if(list->hash_function)
+			hash = list->hash_function(desc, list->hash_bits);
+		do_remove_item(list, item_p, hash);
+	}
+}
+
+/* Call spinlocked */
+static void remove_all_items(struct rsbac_list_reg_item_t *list, u_int hash)
+{
+	struct rsbac_list_item_t *item_p;
+
+	if (unlikely(!list || !list->hashed))
+		return;
+	/* cleanup all items */
+	item_p = list->hashed[hash].head;
+	rcu_assign_pointer(list->hashed[hash].curr, NULL);
+	rcu_assign_pointer(list->hashed[hash].head, NULL);
+	rcu_assign_pointer(list->hashed[hash].tail, NULL);
+	list->hashed[hash].count = 0;
+	rcu_free_item_chain(list, item_p);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call spinlocked */
+static void ta_do_remove_item(struct rsbac_list_reg_item_t *list,
+			      struct rsbac_list_item_t *item_p,
+			      u_int hash)
+{
+	if (unlikely(!list || !item_p))
+		return;
+
+	/* curr is no longer valid -> reset */
+	if (list->hashed[hash].ta_curr == item_p)
+		rcu_assign_pointer(list->hashed[hash].ta_curr, NULL);
+	if ((list->hashed[hash].ta_head == item_p)) {	/* item is head */
+		if ((list->hashed[hash].ta_tail == item_p)) {	/* item is head and tail = only item -> list will be empty */
+			rcu_assign_pointer(list->hashed[hash].ta_head, NULL);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, NULL);
+		} else {	/* item is head, but not tail -> next item becomes head */
+			rcu_assign_pointer(item_p->next->prev, NULL);
+			rcu_assign_pointer(list->hashed[hash].ta_head, item_p->next);
+		}
+	} else {		/* item is not head */
+		if ((list->hashed[hash].ta_tail == item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+			rcu_assign_pointer(item_p->prev->next, NULL);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, item_p->prev);
+		} else {	/* item is neither head nor tail -> item is cut out */
+			rcu_assign_pointer(item_p->prev->next, item_p->next);
+			rcu_assign_pointer(item_p->next->prev, item_p->prev);
+		}
+	}
+	/* adjust counter */
+	list->hashed[hash].ta_count--;
+	/* now we can remove the item from memory */
+	rcu_free(list, item_p);
+}
+
+/* Call spinlocked */
+static void ta_remove_item(const rsbac_list_ta_number_t ta_number,
+			   struct rsbac_list_reg_item_t *list, void *desc)
+{
+	struct rsbac_list_item_t *item_p;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return;
+	if (!ta_number)
+		return remove_item(list, desc);
+	/* first we must locate the item. */
+	if ((item_p = ta_lookup_item_locked(ta_number, list, desc))) {
+		if(list->hash_function)
+			hash = list->hash_function(desc, list->hash_bits);
+		ta_do_remove_item(list, item_p, hash);
+	}
+}
+
+/* Call spinlocked */
+static void ta_remove_all_items(struct rsbac_list_reg_item_t *list, u_int hash)
+{
+	struct rsbac_list_item_t *item_p;
+
+	/* cleanup all items */
+	item_p = list->hashed[hash].ta_head;
+	rcu_assign_pointer(list->hashed[hash].ta_curr, NULL);
+	rcu_assign_pointer(list->hashed[hash].ta_head, NULL);
+	rcu_assign_pointer(list->hashed[hash].ta_tail, NULL);
+	list->hashed[hash].ta_count = 0;
+	rcu_free_item_chain(list, item_p);
+}
+#endif
+
+/* Call spinlocked */
+static void do_remove_lol_subitem(struct rsbac_list_lol_item_t *sublist,
+				  struct rsbac_list_item_t *item_p)
+{
+	if (unlikely(!sublist || !item_p))
+		return;
+
+	/* curr is no longer valid -> reset */
+	if (sublist->curr == item_p)
+		rcu_assign_pointer(sublist->curr, NULL);
+	if ((sublist->head == item_p)) {	/* item is head */
+		if ((sublist->tail == item_p)) {	/* item is head and tail = only item -> list will be empty */
+			rcu_assign_pointer(sublist->head, NULL);
+			rcu_assign_pointer(sublist->tail, NULL);
+		} else {	/* item is head, but not tail -> next item becomes head */
+			rcu_assign_pointer(item_p->next->prev, NULL);
+			rcu_assign_pointer(sublist->head, item_p->next);
+		}
+	} else {		/* item is not head */
+		if ((sublist->tail == item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+			rcu_assign_pointer(item_p->prev->next, NULL);
+			rcu_assign_pointer(sublist->tail, item_p->prev);
+		} else {	/* item is neither head nor tail -> item is cut out */
+			rcu_assign_pointer(item_p->prev->next, item_p->next);
+			rcu_assign_pointer(item_p->next->prev, item_p->prev);
+		}
+	}
+	/* adjust counter */
+	sublist->count--;
+	/* free call is in calling function */
+}
+
+/* Call spinlocked */
+static void remove_lol_subitem(struct rsbac_list_lol_reg_item_t *list,
+			       struct rsbac_list_lol_item_t *sublist,
+			       void *subdesc)
+{
+	struct rsbac_list_item_t *subitem_p;
+
+	if (unlikely(!list || !sublist || !subdesc))
+		return;
+
+	/* first we must locate the item. */
+	if ((subitem_p = lookup_lol_subitem_locked(list, sublist, subdesc))) {
+		do_remove_lol_subitem(sublist, subitem_p);
+		rcu_free_lol_sub(list, subitem_p);
+	}
+}
+
+
+/* Call spinlocked */
+static void do_remove_lol_item(struct rsbac_list_lol_reg_item_t *list,
+			       struct rsbac_list_lol_item_t *item_p,
+			       u_int hash)
+{
+	if (unlikely(!list || !item_p))
+		return;
+
+	/* curr is no longer valid -> reset */
+	if (list->hashed[hash].curr == item_p)
+		rcu_assign_pointer(list->hashed[hash].curr, NULL);
+	if ((list->hashed[hash].head == item_p)) {	/* item is head */
+		if ((list->hashed[hash].tail == item_p)) {	/* item is head and tail = only item -> list will be empty */
+			rcu_assign_pointer(list->hashed[hash].head, NULL);
+			rcu_assign_pointer(list->hashed[hash].tail, NULL);
+		} else {	/* item is head, but not tail -> next item becomes head */
+#ifdef CONFIG_RSBAC_DEBUG
+			if (!item_p->next) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
+					     list->name);
+			} else
+#endif
+			{
+				rcu_assign_pointer(item_p->next->prev, NULL);
+				rcu_assign_pointer(list->hashed[hash].head, item_p->next);
+			}
+		}
+	} else {		/* item is not head */
+		if ((list->hashed[hash].tail == item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+#ifdef CONFIG_RSBAC_DEBUG
+			if (!item_p->prev) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
+					     list->name);
+			} else
+#endif
+			{
+				rcu_assign_pointer(item_p->prev->next, NULL);
+				rcu_assign_pointer(list->hashed[hash].tail, item_p->prev);
+			}
+		} else {	/* item is neither head nor tail -> item is cut out */
+#ifdef CONFIG_RSBAC_DEBUG
+			if (!item_p->prev) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
+					     list->name);
+			} else if (!item_p->next) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
+					     list->name);
+			} else
+#endif
+			{
+				rcu_assign_pointer(item_p->prev->next, item_p->next);
+				rcu_assign_pointer(item_p->next->prev, item_p->prev);
+			}
+		}
+	}
+	/* adjust counter */
+	list->hashed[hash].count--;
+
+	rcu_free_lol_subitem_chain(list, item_p->head);
+	rcu_free_lol(list, item_p);
+}
+
+/* Call spinlocked */
+static void remove_lol_item(struct rsbac_list_lol_reg_item_t *list,
+			    void *desc)
+{
+	struct rsbac_list_lol_item_t *item_p;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return;
+
+	/* first we must locate the item. */
+	if ((item_p = lookup_lol_item_locked(list, desc))) {
+		if(list->hash_function)
+			hash = list->hash_function(desc, list->hash_bits);
+		do_remove_lol_item(list, item_p, hash);
+	}
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call spinlocked */
+static void ta_do_remove_lol_item(struct rsbac_list_lol_reg_item_t *list,
+				  struct rsbac_list_lol_item_t *item_p,
+				  u_int hash)
+{
+	if (unlikely(!list || !item_p))
+		return;
+
+	/* curr is no longer valid -> reset */
+	if (list->hashed[hash].ta_curr == item_p)
+		rcu_assign_pointer(list->hashed[hash].ta_curr, NULL);
+	if ((list->hashed[hash].ta_head == item_p)) {	/* item is head */
+		if ((list->hashed[hash].ta_tail == item_p)) {	/* item is head and tail = only item -> list will be empty */
+			rcu_assign_pointer(list->hashed[hash].ta_head, NULL);
+			rcu_assign_pointer(list->hashed[hash].ta_tail, NULL);
+		} else {	/* item is head, but not tail -> next item becomes head */
+#ifdef CONFIG_RSBAC_DEBUG
+			if (!item_p->next) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
+					     list->name);
+			} else
+#endif
+			{
+				rcu_assign_pointer(item_p->next->prev, NULL);
+				rcu_assign_pointer(list->hashed[hash].ta_head, item_p->next);
+			}
+		}
+	} else {		/* item is not head */
+		if ((list->hashed[hash].ta_tail == item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+#ifdef CONFIG_RSBAC_DEBUG
+			if (!item_p->prev) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
+					     list->name);
+			} else
+#endif
+			{
+				rcu_assign_pointer(item_p->prev->next, NULL);
+				rcu_assign_pointer(list->hashed[hash].ta_tail, item_p->prev);
+			}
+		} else {	/* item is neither head nor tail -> item is cut out */
+#ifdef CONFIG_RSBAC_DEBUG
+			if (!item_p->prev) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
+					     list->name);
+			} else if (!item_p->next) {	/* list corrupted! */
+				rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
+					     list->name);
+			} else
+#endif
+			{
+				rcu_assign_pointer(item_p->prev->next, item_p->next);
+				rcu_assign_pointer(item_p->next->prev, item_p->prev);
+			}
+		}
+	}
+	/* adjust counter */
+	list->hashed[hash].ta_count--;
+
+	rcu_free_lol_subitem_chain(list, item_p->head);
+	rcu_free_lol(list, item_p);
+}
+
+/* Call spinlocked */
+static void ta_remove_lol_item(const rsbac_list_ta_number_t ta_number,
+			       struct rsbac_list_lol_reg_item_t *list,
+			       void *desc)
+{
+	struct rsbac_list_lol_item_t *item_p;
+	u_int hash = 0;
+
+	if (unlikely(!list || !desc))
+		return;
+
+	/* first we must locate the item. */
+	if ((item_p = ta_lookup_lol_item_locked(ta_number, list, desc))) {
+		if(list->hash_function)
+			hash = list->hash_function(desc, list->hash_bits);
+		ta_do_remove_lol_item(list, item_p, hash);
+	}
+}
+#endif
+
+/* Call spinlocked */
+static void remove_all_lol_subitems(struct rsbac_list_lol_reg_item_t *list,
+				struct rsbac_list_lol_item_t *sublist)
+{
+	struct rsbac_list_item_t *subitem_p;
+
+	subitem_p = sublist->head;
+	rcu_assign_pointer(sublist->curr, NULL);
+	rcu_assign_pointer(sublist->head, NULL);
+	rcu_assign_pointer(sublist->tail, NULL);
+	sublist->count = 0;
+	rcu_free_lol_subitem_chain(list, subitem_p);
+}
+
+/* Call spinlocked */
+static void remove_all_lol_items(struct rsbac_list_lol_reg_item_t *list, u_int hash)
+{
+	struct rsbac_list_lol_item_t *item_p;
+
+	if (unlikely(!list || !list->hashed))
+		return;
+	item_p = list->hashed[hash].head;
+	rcu_assign_pointer(list->hashed[hash].curr, NULL);
+	rcu_assign_pointer(list->hashed[hash].head, NULL);
+	rcu_assign_pointer(list->hashed[hash].tail, NULL);
+	list->hashed[hash].count = 0;
+	rcu_free_lol_item_chain(list, item_p);
+}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+/* Call spinlocked */
+static void ta_remove_all_lol_items(struct rsbac_list_lol_reg_item_t *list,
+				u_int hash)
+{
+	struct rsbac_list_lol_item_t *item_p;
+
+	/* cleanup all items */
+	item_p = list->hashed[hash].ta_head;
+	rcu_assign_pointer(list->hashed[hash].ta_curr, NULL);
+	rcu_assign_pointer(list->hashed[hash].ta_head, NULL);
+	rcu_assign_pointer(list->hashed[hash].ta_tail, NULL);
+	list->hashed[hash].ta_count = 0;
+	rcu_free_lol_item_chain(list, item_p);
+}
+#endif
+
+/* Remove registration items */
+
+/* no locking needed */
+static void clear_reg(struct rsbac_list_reg_item_t *reg_item_p)
+{
+	if (likely(reg_item_p)) {
+		int i;
+	        struct rsbac_list_item_t *item_p;
+	        struct rsbac_list_item_t *new_item_p;
+		const u_int nr_hashes = 1 << reg_item_p->hash_bits;
+
+		/* now we can remove the item from memory */
+		synchronize_rcu();
+		for (i=0; i<nr_hashes; i++) {
+			item_p = reg_item_p->hashed[i].head;
+			while(item_p) {
+				new_item_p = item_p->next;
+				rsbac_sfree(reg_item_p->slab, item_p);
+				item_p = new_item_p;
+			}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+			if(reg_item_p->hashed[i].ta_copied) {
+				item_p = reg_item_p->hashed[i].ta_head;
+				while(item_p) {
+					new_item_p = item_p->next;
+					rsbac_sfree(reg_item_p->slab, item_p);
+					item_p = new_item_p;
+				}
+			}
+#endif
+		}
+		if (reg_item_p->def_data)
+			rsbac_kfree(reg_item_p->def_data);
+		if (reg_item_p->slab)
+			rsbac_slab_destroy(reg_item_p->slab);
+		if (reg_item_p->slabname)
+			rsbac_kfree(reg_item_p->slabname);
+		if (reg_item_p->hashed)
+			rsbac_kfree(reg_item_p->hashed);
+		rsbac_sfree(reg_item_slab, reg_item_p);
+	}
+}
+
+/* locking needed */
+static void remove_reg(struct rsbac_list_reg_item_t *reg_item_p)
+{
+	/* first we must locate the item. */
+	if (reg_item_p && (reg_item_p->self == reg_item_p)) {/* item found and valid */
+		/* protect against reuse */
+		reg_item_p->self = NULL;
+		if ((reg_head.head == reg_item_p)) {	/* item is head */
+			if ((reg_head.tail == reg_item_p)) {	/* item is head and tail = only item -> list will be empty */
+				rcu_assign_pointer(reg_head.head, NULL);
+				rcu_assign_pointer(reg_head.tail, NULL);
+			} else {	/* item is head, but not tail -> next item becomes head */
+				reg_item_p->next->prev = NULL;
+				rcu_assign_pointer(reg_head.head, reg_item_p->next);
+			}
+		} else {	/* item is not head */
+			if ((reg_head.tail == reg_item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+				reg_item_p->prev->next = NULL;
+				rcu_assign_pointer(reg_head.tail, reg_item_p->prev);
+			} else {	/* item is neither head nor tail -> item is cut out */
+				reg_item_p->prev->next = reg_item_p->next;
+				reg_item_p->next->prev = reg_item_p->prev;
+			}
+		}
+
+		/* curr is no longer valid -> reset */
+		reg_head.curr = NULL;
+		/* adjust counter */
+		reg_head.count--;
+	}	/* end of if: item was found */
+}
+
+/* no locking needed */
+static void clear_lol_reg(struct rsbac_list_lol_reg_item_t *reg_item_p)
+{
+	int i;
+
+	if (likely(reg_item_p)) {
+	        struct rsbac_list_lol_item_t *lol_item_p;
+	        struct rsbac_list_lol_item_t *new_lol_item_p;
+	        struct rsbac_list_item_t * lol_subitem_p;
+	        struct rsbac_list_item_t * new_lol_subitem_p;
+		const u_int nr_hashes = 1 << reg_item_p->hash_bits;
+
+		/* now we can remove the item from memory */
+		synchronize_rcu();
+		for (i=0; i<nr_hashes; i++) {
+			lol_item_p = reg_item_p->hashed[i].head;
+			while(lol_item_p) {
+				lol_subitem_p = lol_item_p->head;
+				while (lol_subitem_p) {
+					new_lol_subitem_p = lol_subitem_p->next;
+					rsbac_sfree(reg_item_p->subslab, lol_subitem_p);
+					lol_subitem_p = new_lol_subitem_p;
+				}
+				new_lol_item_p = lol_item_p->next;
+				rsbac_sfree(reg_item_p->slab, lol_item_p);
+				lol_item_p = new_lol_item_p;
+			}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+			if(reg_item_p->hashed[i].ta_copied) {
+				lol_item_p = reg_item_p->hashed[i].ta_head;
+				while(lol_item_p) {
+					lol_subitem_p = lol_item_p->head;
+					while (lol_subitem_p) {
+						new_lol_subitem_p = lol_subitem_p->next;
+						rsbac_sfree(reg_item_p->subslab, lol_subitem_p);
+						lol_subitem_p = new_lol_subitem_p;
+					}
+					new_lol_item_p = lol_item_p->next;
+					rsbac_sfree(reg_item_p->slab, lol_item_p);
+					lol_item_p = new_lol_item_p;
+				}
+			}
+#endif
+		}
+		if (reg_item_p->def_data)
+			rsbac_kfree(reg_item_p->def_data);
+		if (reg_item_p->def_subdata)
+			rsbac_kfree(reg_item_p->def_subdata);
+		if (reg_item_p->slab)
+			rsbac_slab_destroy(reg_item_p->slab);
+		if (reg_item_p->subslab)
+			rsbac_slab_destroy(reg_item_p->subslab);
+		if (reg_item_p->slabname)
+			rsbac_kfree(reg_item_p->slabname);
+		if (reg_item_p->subslabname)
+			rsbac_kfree(reg_item_p->subslabname);
+		if (reg_item_p->hashed)
+			rsbac_kfree(reg_item_p->hashed);
+		rsbac_sfree(lol_reg_item_slab, reg_item_p);
+	}
+}
+
+/* locking needed */
+static void remove_lol_reg(struct rsbac_list_lol_reg_item_t *reg_item_p)
+{
+	/* first we must locate the item. */
+	if (reg_item_p && (reg_item_p->self == reg_item_p)) {/* found */
+		/* protect against reuse */
+		reg_item_p->self = NULL;
+		if ((lol_reg_head.head == reg_item_p)) {	/* item is head */
+			if ((lol_reg_head.tail == reg_item_p)) {	/* item is head and tail = only item -> list will be empty */
+				rcu_assign_pointer(lol_reg_head.head, NULL);
+				rcu_assign_pointer(lol_reg_head.tail, NULL);
+			} else {	/* item is head, but not tail -> next item becomes head */
+				reg_item_p->next->prev = NULL;
+				rcu_assign_pointer(lol_reg_head.head, reg_item_p->next);
+			}
+		} else {	/* item is not head */
+			if ((lol_reg_head.tail == reg_item_p)) {	/*item is not head, but tail -> previous item becomes tail */
+				reg_item_p->prev->next = NULL;
+				rcu_assign_pointer(lol_reg_head.tail, reg_item_p->prev);
+			} else {	/* item is neither head nor tail -> item is cut out */
+				reg_item_p->prev->next = reg_item_p->next;
+				reg_item_p->next->prev = reg_item_p->prev;
+			}
+		}
+
+		/* curr is no longer valid -> reset */
+		rcu_assign_pointer(lol_reg_head.curr, NULL);
+		/* adjust counter */
+		lol_reg_head.count--;
+	}	/* end of if: item was found */
+}
+
+#define touch(x)
+
+#define lol_touch(x)
+
+/********************/
+/* Read/Write       */
+/********************/
+
+/* call unlocked */
+static int do_read_list(struct rsbac_list_reg_item_t *list,
+	char * name,
+	rsbac_boolean_t backup)
+{
+	struct file *file_p;
+	int err = 0;
+	int tmperr;
+	int converr;
+	rsbac_version_t list_version;
+	u_long read_count = 0;
+	char *old_buf = NULL;
+	char *new_buf = NULL;
+	char *old_data;
+	char *new_data;
+	struct rsbac_list_info_t *list_info_p;
+	rsbac_list_count_t list_count;
+	rsbac_time_t timestamp;
+	struct rsbac_nanotime_t lastchange;
+	rsbac_time_t max_age = 0;
+	rsbac_list_conv_function_t *conv = NULL;
+	rsbac_boolean_t timeout = FALSE;
+	mm_segment_t oldfs;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (unlikely(!list_info_p))
+		return -RSBAC_ENOMEM;
+	/* open file */
+	if ((err = rsbac_read_open(name, &file_p, list->device))) {
+		goto double_free;
+	}
+
+	/* OK, now we can start reading */
+	/* There is a read function for this file, so check info and read as
+	 * many items as possible. A positive return value means a read success,
+	 * 0 end of file and a negative value an error. */
+
+	/* Set current user space to kernel space, because read() writes */
+	/* to user space */
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	/* check gen-list on-disk version */
+	tmperr = __vfs_read(file_p,
+				(__u8 *) & list_version,
+				sizeof(list_version), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(list_version)) {
+		rsbac_printk(KERN_WARNING "do_read_list(): read error %i from file when reading list version!\n", tmperr);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+	/* if wrong list on-disk version, fail */
+	switch (list_version) {
+	case RSBAC_LIST_DISK_VERSION:
+	case RSBAC_LIST_DISK_OLD_VERSION:
+		break;
+	default:
+		rsbac_printk(KERN_WARNING "do_read_list(): wrong on-disk list version %u in file %s, expected %u - error!\n",
+			     list_version,
+			     name, RSBAC_LIST_DISK_VERSION);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* get timestamp */
+	set_fs(KERNEL_DS);
+	tmperr = __vfs_read(file_p,
+				(__u8 *) & timestamp,
+				sizeof(timestamp), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(timestamp)) {
+		rsbac_printk(KERN_WARNING "do_read_list(): timestamp read error %i from file %s!\n",
+			     tmperr,
+			     name);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* get list info */
+	set_fs(KERNEL_DS);
+	tmperr = __vfs_read(file_p,
+				(__u8 *) list_info_p,
+				sizeof(*list_info_p), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(*list_info_p)) {
+		rsbac_printk(KERN_WARNING "do_read_list(): list info read error %i from file %s!\n",
+			     tmperr,
+			     name);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* list timed out? System time is measured in seconds. */
+	if (list_info_p->max_age
+	    && (timestamp + list_info_p->max_age) <= RSBAC_CURRENT_TIME)
+		timeout = TRUE;
+
+	/* Valid key? */
+	if (list_info_p->key != list->info.key) {
+		if (timeout) {
+			rsbac_printk(KERN_WARNING "do_read_list(): accessing timed out list %s with wrong key, ignoring old contents!\n",
+				     name);
+			goto end_read;
+		} else {
+			rsbac_printk(KERN_WARNING "do_read_list(): try to access list %s with wrong key!\n",
+				     name);
+			err = -EPERM;
+			goto end_read;
+		}
+	}
+
+	/* skip the rest, if ignore is requested */
+	if (list->flags & RSBAC_LIST_IGNORE_OLD)
+		goto end_read;
+
+	switch (list_version) {
+	case RSBAC_LIST_DISK_VERSION:
+		set_fs(KERNEL_DS);
+		tmperr = __vfs_read(file_p,
+					(char *) &lastchange,
+					sizeof(lastchange),
+					&file_p->f_pos);
+		set_fs(oldfs);
+		/* error? */
+		if (tmperr < sizeof(lastchange)) {
+			rsbac_printk(KERN_WARNING "do_read_list(): lastchange read error %i from file %s!\n",
+				     tmperr,
+				     name);
+			err = -RSBAC_EREADFAILED;
+			goto end_read;
+		}
+		break;
+	case RSBAC_LIST_DISK_OLD_VERSION:
+		break;
+	default:
+		break;
+	}
+	/* if wrong list version, try to get_conv */
+	if (list_info_p->version != list->info.version) {
+		if (list->get_conv)
+			conv = list->get_conv(list_info_p->version);
+		if (!conv) {
+			if (timeout) {
+				rsbac_printk(KERN_WARNING "do_read_list(): accessing timed out list %s without conversion function, ignoring old contents!\n",
+					     name);
+				goto end_read;
+			} else {
+				/* complain and set error, if ignore is not requested */
+				if (!
+				    (list->
+				     flags &
+				     RSBAC_LIST_IGNORE_UNSUPP_VERSION)) {
+					rsbac_printk(KERN_WARNING "do_read_list(): cannot convert list version %u of file %s to version %u!\n",
+						     list_info_p->version,
+						     name,
+						     list->info.version);
+					err = -RSBAC_EINVALIDVERSION;
+				}
+				goto end_read;
+			}
+		} else {
+			rsbac_printk(KERN_WARNING "do_read_list(): converting list version %u of file %s on device %02u:%02u to version %u!\n",
+				     list_info_p->version,
+				     name,
+				     RSBAC_MAJOR(list->device),
+				     RSBAC_MINOR(list->device),
+				     list->info.version);
+		}
+	} else {		/* same version needs same sizes */
+
+		if ((list_info_p->desc_size != list->info.desc_size)
+		    || (list_info_p->data_size != list->info.data_size)
+		    ) {
+			if (timeout) {
+				rsbac_printk(KERN_WARNING "do_read_list(): accessing timed out list %s with wrong desc or data size, ignoring old contents!\n",
+					     name);
+				goto end_read;
+			} else {
+				rsbac_printk(KERN_WARNING "do_read_list(): desc or data size mismatch on list %s!\n",
+					     name);
+				err = -RSBAC_EINVALIDLIST;
+				goto end_read;
+			}
+		}
+	}
+
+	/* get list count */
+	set_fs(KERNEL_DS);
+	tmperr = __vfs_read(file_p,
+				(__u8 *) & list_count,
+				sizeof(list_count), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(list_count)) {
+		rsbac_printk(KERN_WARNING "do_read_list(): list count read error %i from file %s!\n",
+			     tmperr,
+			     name);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* alloc mem for old and converted item */
+	old_buf =
+	    rsbac_kmalloc_unlocked(list_info_p->desc_size + list_info_p->data_size);
+	if (!old_buf) {
+		rsbac_printk(KERN_WARNING "do_read_list(): cannot allocate memory!\n");
+		err = -RSBAC_ENOMEM;
+		goto end_read;
+	}
+	new_buf =
+	    rsbac_kmalloc_unlocked(list->info.desc_size + list->info.data_size);
+	if (unlikely(!new_buf)) {
+		rsbac_printk(KERN_WARNING "do_read_list(): cannot allocate memory!\n");
+		err = -RSBAC_ENOMEM;
+		goto end_read;
+	}
+	/* calculate data pointers */
+	if (list_info_p->data_size)
+		old_data = old_buf + list_info_p->desc_size;
+	else
+		old_data = NULL;
+	if (list->info.data_size)
+		new_data = new_buf + list->info.desc_size;
+	else
+		new_data = NULL;
+
+	/* actual reading */
+	do {
+		set_fs(KERNEL_DS);
+		tmperr = __vfs_read(file_p,
+					(char *) &max_age,
+					sizeof(max_age),
+					&file_p->f_pos);
+		set_fs(oldfs);
+		if (conv) {
+			set_fs(KERNEL_DS);
+			tmperr = __vfs_read(file_p,
+						old_buf,
+						list_info_p->
+						desc_size +
+						list_info_p->data_size,
+						&file_p->f_pos);
+			set_fs(oldfs);
+			if (tmperr > 0) {	/* convert */
+				converr = conv(old_buf, old_data,
+					       new_buf, new_data);
+				if (converr)
+					tmperr = converr;
+			}
+		} else {
+			set_fs(KERNEL_DS);
+			tmperr = __vfs_read(file_p,
+						    new_buf,
+						    list->info.desc_size +
+						    list->info.data_size,
+						    &file_p->f_pos);
+			set_fs(oldfs);
+		}
+		/* if successful, add item */
+		if (tmperr > 0) {
+			/* no need to lock, list is not yet published */
+			if (!backup || !lookup_item_locked(list, new_buf))
+				add_item(list, max_age, new_buf, new_data);
+			/* allow access */
+			read_count++;
+/*
+			rsbac_pr_debug(lists, "read item %i\n", user_aci.id);
+*/
+		}
+	}
+	while (tmperr > 0);	/* end of do */
+
+	if (tmperr < 0) {
+		rsbac_printk(KERN_WARNING "do_read_list(): read error %i from file %s!\n",
+			     tmperr,
+			     name);
+		err = -RSBAC_EREADFAILED;
+	}
+
+	if (read_count != list_count) {
+		rsbac_printk(KERN_WARNING "do_read_list(): read %lu, expected %u items from file %s!\n",
+			     read_count, list_count, name);
+		err = -RSBAC_EREADFAILED;
+	}
+
+end_read:
+	if (old_buf)
+		rsbac_kfree(old_buf);
+	if (new_buf)
+		rsbac_kfree(new_buf);
+
+	rsbac_pr_debug(lists, "%lu entries read.\n", read_count);
+	/* We do not need this file any more */
+	rsbac_read_close(file_p);
+
+double_free:
+	rsbac_kfree(list_info_p);
+
+	if (   err
+	    && (err != -RSBAC_ENOTFOUND)
+	    && !backup
+	    && rsbac_list_recover
+	   ) {
+	   	char * bname;
+
+		rsbac_list_read_errors++;
+		bname = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+		if (!bname)
+			return -RSBAC_ENOMEM;
+		rsbac_printk(KERN_WARNING "restoring list %s from device %02u:%02u failed with error %s, rsbac_list_recover is set, so retrying with backup list.\n",
+			name,
+			RSBAC_MAJOR(list->device),
+			RSBAC_MINOR(list->device),
+			get_error_name(bname, err));
+		sprintf(bname, "%sb", name);
+		err = do_read_list(list, bname, TRUE);
+		if (   err
+		    && (err != -RSBAC_ENOTFOUND)
+		    && rsbac_list_recover
+		   ) {
+			rsbac_printk(KERN_WARNING "restoring list %s backup from device %02u:%02u failed with error %s, rsbac_list_recover is set, so returning that list is fine.\n",
+				name,
+				RSBAC_MAJOR(list->device),
+				RSBAC_MINOR(list->device),
+				get_error_name(bname, err));
+			err = 0;
+		}
+		list->dirty = TRUE;
+		rsbac_kfree(bname);
+	}
+
+	return err;
+}
+
+/* call unlocked */
+static int read_list(struct rsbac_list_reg_item_t *list)
+{
+  int res;
+  u_int flags;
+
+  flags = list->flags;
+  list->flags |= RSBAC_LIST_NO_MAX;
+  res = do_read_list(list, list->name, FALSE);
+  if((res == -RSBAC_ENOTFOUND) && list->old_name_base[0]) {
+	char name[RSBAC_MAXNAMELEN];
+	int i;
+
+	rsbac_printk(KERN_INFO "read_list(): list %s on device %02u:%02u not found, trying numbered lists 0 to %u with old name base '%s'\n",
+			list->name, MAJOR(list->device), MINOR(list->device), RSBAC_LIST_MAX_OLD_HASH-1, list->old_name_base);
+	for (i=0; i<RSBAC_LIST_MAX_OLD_HASH; i++) {
+		sprintf(name, "%s%u", list->old_name_base, i);
+		res = do_read_list(list, name, FALSE);
+		if(res && (res != -RSBAC_ENOTFOUND))
+			return res;
+	}
+	list->dirty = TRUE;
+  }
+  list->flags = flags;
+  return res;
+}
+
+/* call unlocked */
+static int do_read_lol_list(struct rsbac_list_lol_reg_item_t *list,
+	char * name,
+	rsbac_boolean_t backup)
+{
+	struct file *file_p;
+	int err = 0;
+	int tmperr;
+	int converr;
+	rsbac_version_t list_version;
+	u_long read_count = 0;
+	u_long sublen;
+	u_long i;
+	char *old_buf = NULL;
+	char *new_buf = NULL;
+	char *old_data;
+	char *new_data;
+	char *old_subbuf = NULL;
+	char *new_subbuf = NULL;
+	char *old_subdata;
+	char *new_subdata;
+	struct rsbac_list_lol_info_t *list_info_p;
+	rsbac_list_count_t list_count;
+	rsbac_time_t timestamp;
+	struct rsbac_nanotime_t lastchange;
+	rsbac_time_t max_age = 0;
+	rsbac_list_conv_function_t *conv = NULL;
+	rsbac_list_conv_function_t *subconv = NULL;
+	rsbac_boolean_t timeout = FALSE;
+	struct rsbac_list_lol_item_t *item_p;
+	mm_segment_t oldfs;
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (unlikely(!list_info_p))
+		return -RSBAC_ENOMEM;
+	/* open file */
+	if ((err = rsbac_read_open(name, &file_p, list->device))) {
+		goto double_free;
+	}
+
+	/* OK, now we can start reading */
+	/* There is a read function for this file, so check info and read as
+	 * many items as possible. A positive return value means a read success,
+	 * 0 end of file and a negative value an error. */
+
+	/* Set current user space to kernel space, because read() writes */
+	/* to user space */
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+
+	/* check gen-list on-disk version */
+	tmperr = __vfs_read(file_p,
+				    (__u8 *) & list_version,
+				    sizeof(list_version), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(list_version)) {
+		printk(KERN_WARNING
+			"do_read_lol_list(): read error %i from file!\n",
+			tmperr);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+	/* if wrong list on-disk version, fail */
+	switch (list_version) {
+	case RSBAC_LIST_DISK_VERSION:
+	case RSBAC_LIST_DISK_OLD_VERSION:
+		break;
+	default:
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): wrong on-disk list version %u in file %s, expected %u - error!\n",
+			     list_version,
+			     name, RSBAC_LIST_DISK_VERSION);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* get timestamp */
+	set_fs(KERNEL_DS);
+	tmperr = __vfs_read(file_p,
+				    (__u8 *) & timestamp,
+				    sizeof(timestamp), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(timestamp)) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): timestamp read error %i from file %s!\n",
+				tmperr,
+				name);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* get list info */
+	set_fs(KERNEL_DS);
+	tmperr = __vfs_read(file_p,
+				    (__u8 *) list_info_p,
+				    sizeof(*list_info_p), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(*list_info_p)) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): list info read error %i from file %s!\n",
+				tmperr,
+				name);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* list timed out? System time is measured in seconds. */
+	if (list_info_p->max_age
+	    && (timestamp + list_info_p->max_age) <= RSBAC_CURRENT_TIME)
+		timeout = TRUE;
+
+	/* Valid key? */
+	if (list_info_p->key != list->info.key) {
+		if (timeout) {
+			rsbac_printk(KERN_WARNING "do_read_lol_list(): accessing timed out list %s with wrong key, ignoring old contents!\n",
+				     name);
+			goto end_read;
+		} else {
+			rsbac_printk(KERN_WARNING "do_read_lol_list(): try to access list %s with wrong key!\n",
+				     name);
+			err = -EPERM;
+			goto end_read;
+		}
+	}
+
+	/* skip the rest, if ignore is requested */
+	if (list->flags & RSBAC_LIST_IGNORE_OLD)
+		goto end_read;
+
+	switch (list_version) {
+	case RSBAC_LIST_DISK_VERSION:
+		set_fs(KERNEL_DS);
+		tmperr = __vfs_read(file_p,
+					    (char *) &lastchange,
+					    sizeof(lastchange),
+					    &file_p->f_pos);
+		set_fs(oldfs);
+		/* error? */
+		if (tmperr < sizeof(lastchange)) {
+			rsbac_printk(KERN_WARNING "do_read_lol_list(): lastchange read error %i from file %s!\n",
+					tmperr,
+					name);
+			err = -RSBAC_EREADFAILED;
+			goto end_read;
+		}
+		break;
+	case RSBAC_LIST_DISK_OLD_VERSION:
+		break;
+	default:
+		break;
+	}
+	/* if wrong list version, try to get_conv */
+	if (list_info_p->version != list->info.version) {
+		if (list->get_conv)
+			conv = list->get_conv(list_info_p->version);
+		if (list->get_subconv)
+			subconv = list->get_subconv(list_info_p->version);
+		if (!conv || !subconv) {
+			if (timeout) {
+				rsbac_printk(KERN_WARNING "do_read_lol_list(): accessing timed out list %s without both conversion functions, ignoring old contents!\n",
+					     name);
+				goto end_read;
+			} else {
+				/* complain and set error, if ignore is not requested */
+				if (!
+				    (list->
+				     flags &
+				     RSBAC_LIST_IGNORE_UNSUPP_VERSION)) {
+					rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot convert list version %u of file %s to version %u!\n",
+						     list_info_p->version,
+						     name,
+						     list->info.version);
+					err = -RSBAC_EINVALIDVERSION;
+				}
+				goto end_read;
+			}
+		} else {
+			rsbac_printk(KERN_WARNING "do_read_lol_list(): converting list version %u of file %s on device %02u:%02u to version %u!\n",
+				     list_info_p->version,
+				     name,
+				     RSBAC_MAJOR(list->device),
+				     RSBAC_MINOR(list->device),
+				     list->info.version);
+		}
+	} else {		/* same version needs same sizes */
+
+		if ((list_info_p->desc_size != list->info.desc_size)
+		    || (list_info_p->data_size != list->info.data_size)
+		    || (list_info_p->subdesc_size !=
+			list->info.subdesc_size)
+		    || (list_info_p->subdata_size !=
+			list->info.subdata_size)
+		    ) {
+			if (timeout) {
+				rsbac_printk(KERN_WARNING "do_read_lol_list(): accessing timed out list %s with wrong desc or data size(s), ignoring old contents!\n",
+					     name);
+				goto end_read;
+			} else {
+				rsbac_printk(KERN_WARNING "do_read_lol_list(): desc or data size mismatch on list %s!\n",
+					     name);
+				err = -RSBAC_EINVALIDLIST;
+				goto end_read;
+			}
+		}
+	}
+
+	/* get list count */
+	set_fs(KERNEL_DS);
+	tmperr = __vfs_read(file_p,
+				    (__u8 *) & list_count,
+				    sizeof(list_count), &file_p->f_pos);
+	set_fs(oldfs);
+	/* error? */
+	if (tmperr < sizeof(list_count)) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): list count read error %i from file %s!\n",
+				tmperr,
+				name);
+		err = -RSBAC_EREADFAILED;
+		goto end_read;
+	}
+
+	/* alloc mem for old and converted items */
+	old_buf =
+	    rsbac_kmalloc_unlocked(list_info_p->desc_size + list_info_p->data_size);
+	if (!old_buf) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
+		err = -RSBAC_ENOMEM;
+		goto end_read;
+	}
+	new_buf =
+	    rsbac_kmalloc_unlocked(list->info.desc_size + list->info.data_size);
+	if (!new_buf) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
+		err = -RSBAC_ENOMEM;
+		goto end_read;
+	}
+	old_subbuf =
+	    rsbac_kmalloc_unlocked(list_info_p->subdesc_size +
+			  list_info_p->subdata_size);
+	if (!old_subbuf) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
+		err = -RSBAC_ENOMEM;
+		goto end_read;
+	}
+	new_subbuf =
+	    rsbac_kmalloc_unlocked(list->info.subdesc_size +
+			  list->info.subdata_size);
+	if (!new_subbuf) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
+		err = -RSBAC_ENOMEM;
+		goto end_read;
+	}
+	/* calculate data pointers */
+	if (list_info_p->data_size)
+		old_data = old_buf + list_info_p->desc_size;
+	else
+		old_data = NULL;
+	if (list->info.data_size)
+		new_data = new_buf + list->info.desc_size;
+	else
+		new_data = NULL;
+	if (list_info_p->subdata_size)
+		old_subdata = old_subbuf + list_info_p->subdesc_size;
+	else
+		old_subdata = NULL;
+	if (list->info.subdata_size)
+		new_subdata = new_subbuf + list->info.subdesc_size;
+	else
+		new_subdata = NULL;
+
+	/* actual reading */
+	do {
+		set_fs(KERNEL_DS);
+		tmperr = __vfs_read(file_p,
+					    (char *) &max_age,
+					    sizeof(max_age),
+					    &file_p->f_pos);
+		set_fs(oldfs);
+		if (conv) {
+			set_fs(KERNEL_DS);
+			tmperr = __vfs_read(file_p,
+						    old_buf,
+						    list_info_p->
+						    desc_size +
+						    list_info_p->data_size,
+						    &file_p->f_pos);
+			set_fs(oldfs);
+			if (tmperr > 0) {	/* convert */
+				converr = conv(old_buf, old_data,
+					       new_buf, new_data);
+				if (converr)
+					tmperr = converr;
+			}
+		} else {
+			set_fs(KERNEL_DS);
+			tmperr = __vfs_read(file_p,
+						    new_buf,
+						    list->info.desc_size +
+						    list->info.data_size,
+						    &file_p->f_pos);
+			set_fs(oldfs);
+		}
+		/* if successful, add item */
+		if (tmperr > 0) {
+			/* no need to lock, list is not yet published */
+			if (!backup || !(item_p = lookup_lol_item_locked(list, new_buf)))
+				item_p = add_lol_item(list, max_age, new_buf, new_data);
+			/* allow access */
+			if (!item_p) {
+				err = -RSBAC_ENOMEM;
+				goto end_read;
+			}
+			read_count++;
+/*
+			rsbac_pr_debug(lists, "read item %i\n", user_aci.id);
+*/
+			set_fs(KERNEL_DS);
+			tmperr = __vfs_read(file_p,
+						    (__u8 *) & sublen,
+						    sizeof(sublen),
+						    &file_p->f_pos);
+			set_fs(oldfs);
+			/* if successful, read and add sublen subitems */
+			if (tmperr > 0) {
+				for (i = 0; i < sublen; i++) {
+					set_fs(KERNEL_DS);
+					tmperr = __vfs_read(file_p,
+								    (char
+								     *)
+								    &max_age,
+								    sizeof
+								    (max_age),
+								    &file_p->
+								    f_pos);
+					set_fs(oldfs);
+					if (subconv) {
+						set_fs(KERNEL_DS);
+						tmperr = __vfs_read(file_p,
+							 old_subbuf,
+							 list_info_p->
+							 subdesc_size +
+							 list_info_p->
+							 subdata_size,
+							 &file_p->f_pos);
+						set_fs(oldfs);
+						if (tmperr > 0) {	/* convert */
+							converr =
+							    subconv
+							    (old_subbuf,
+							     old_subdata,
+							     new_subbuf,
+							     new_subdata);
+							if (converr)
+								tmperr =
+								    converr;
+						}
+					} else {
+						set_fs(KERNEL_DS);
+						tmperr = __vfs_read(file_p,
+							 new_subbuf,
+							 list->info.
+							 subdesc_size +
+							 list->info.
+							 subdata_size,
+							 &file_p->f_pos);
+						set_fs(oldfs);
+					}
+					if (tmperr > 0) {
+						/* no need to lock, list is not yet published */
+						if (!backup || !lookup_lol_subitem_locked(list, item_p, new_subbuf))
+							if (!add_lol_subitem
+							    (list, item_p, max_age,
+							     new_subbuf,
+							     new_subdata)) {
+								rsbac_printk
+								    (KERN_WARNING
+								     "do_read_lol_list(): could not add subitem!\n");
+								i = sublen;
+								tmperr = -1;
+							}
+					} else {
+						i = sublen;
+						tmperr = -1;
+					}
+				}
+			}
+		}
+	}
+	while (tmperr > 0);	/* end of do */
+
+	if (tmperr < 0) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): read error %i from file %s!\n",
+				tmperr,
+				name);
+		err = -RSBAC_EREADFAILED;
+	}
+
+	if (read_count != list_count) {
+		rsbac_printk(KERN_WARNING "do_read_lol_list(): read %lu, expected %u items from file %s!\n",
+			     read_count, list_count, name);
+		err = -RSBAC_EREADFAILED;
+	}
+
+end_read:
+	if (old_buf)
+		rsbac_kfree(old_buf);
+	if (new_buf)
+		rsbac_kfree(new_buf);
+	if (old_subbuf)
+		rsbac_kfree(old_subbuf);
+	if (new_subbuf)
+		rsbac_kfree(new_subbuf);
+
+	rsbac_pr_debug(lists, "%lu entries read.\n", read_count);
+	/* We do not need this file any more */
+	rsbac_read_close(file_p);
+
+double_free:
+	rsbac_kfree(list_info_p);
+
+	if (   err
+	    && (err != -RSBAC_ENOTFOUND)
+	    && !backup
+	    && rsbac_list_recover
+	   ) {
+	   	char * bname;
+
+		rsbac_list_read_errors++;
+		bname = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+		if (!bname)
+			return -RSBAC_ENOMEM;
+		rsbac_printk(KERN_WARNING "restoring list of lists %s from device %02u:%02u failed with error %s, rsbac_list_recover is set, so retrying with backup list.\n",
+			name,
+			RSBAC_MAJOR(list->device),
+			RSBAC_MINOR(list->device),
+			get_error_name(bname, err));
+		sprintf(bname, "%sb", name);
+		err = do_read_lol_list(list, bname, TRUE);
+		if (   err
+		    && (err != -RSBAC_ENOTFOUND)
+		    && rsbac_list_recover
+		   ) {
+			rsbac_printk(KERN_WARNING "restoring list of lists %s backup from device %02u:%02u failed with error %s, rsbac_list_recover is set, so returning that list is fine.\n",
+				name,
+				RSBAC_MAJOR(list->device),
+				RSBAC_MINOR(list->device),
+				get_error_name(bname, err));
+			err = 0;
+		}
+		list->dirty = TRUE;
+		rsbac_kfree(bname);
+	}
+
+	return err;
+}				/* end of do_read_lol_list() */
+
+/* call unlocked */
+static int read_lol_list(struct rsbac_list_lol_reg_item_t *list)
+{
+  int res;
+  u_int flags;
+
+  flags = list->flags;
+  list->flags |= RSBAC_LIST_NO_MAX;
+  res = do_read_lol_list(list, list->name, FALSE);
+  if((res == -RSBAC_ENOTFOUND) && list->old_name_base[0]) {
+	char name[RSBAC_MAXNAMELEN];
+	int i;
+
+	rsbac_printk(KERN_INFO "read_lol_list(): list %s on device %02u:%02u not found, trying numbered lists 0 to %u with old name base '%s'\n",
+			list->name, MAJOR(list->device), MINOR(list->device), RSBAC_LIST_LOL_MAX_OLD_HASH-1, list->old_name_base);
+	for (i=0; i<RSBAC_LIST_LOL_MAX_OLD_HASH; i++) {
+		sprintf(name, "%s%u", list->old_name_base, i);
+		res = do_read_lol_list(list, name, FALSE);
+		if(res && (res != -RSBAC_ENOTFOUND))
+			return res;
+	}
+	list->dirty = TRUE;
+  }
+  list->flags = flags;
+  return res;
+}
+
+
+#ifndef CONFIG_RSBAC_NO_WRITE
+int check_buffer(struct rsbac_list_buffer_t ** buffer_pp, u_int size)
+{
+	if((*buffer_pp)->len + size <= RSBAC_LIST_BUFFER_DATA_SIZE)
+		return 0;
+	else {
+		struct rsbac_list_buffer_t * new_buffer;
+
+		new_buffer = rsbac_kmalloc(RSBAC_LIST_BUFFER_SIZE);
+		if(!new_buffer)
+			return -RSBAC_ENOMEM;
+		rsbac_pr_debug(write, "Added a buffer\n");
+		new_buffer->next = NULL;
+		new_buffer->len = 0;
+		(*buffer_pp)->next = new_buffer;
+		*buffer_pp = new_buffer;
+		return 0;
+	}
+}
+
+void free_buffers(struct rsbac_list_buffer_t * buffer)
+{
+	struct rsbac_list_buffer_t * next;
+
+	while(buffer) {
+		rsbac_pr_debug(write, "Freeing buffer of size %u\n",
+				buffer->len);
+		next = buffer->next;
+		rsbac_kfree(buffer);
+		buffer = next;
+	}
+}
+
+/* call unlocked */
+static int fill_buffer(struct rsbac_list_reg_item_t *list,
+		       struct rsbac_list_write_item_t **write_item_pp)
+{
+	struct rsbac_list_write_item_t *write_item_p;
+	struct rsbac_list_item_t *current_p;
+	struct rsbac_list_buffer_t *buffer = NULL;
+	rsbac_list_count_t allcount = 0;
+	rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
+	rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
+	int i;
+	const u_int nr_hashes = 1 << list->hash_bits;
+
+	write_item_p = rsbac_kmalloc(sizeof(*write_item_p));
+	if (unlikely(!write_item_p)) {
+		*write_item_pp = NULL;
+		return -RSBAC_ENOMEM;
+	}
+
+	/* fill write_item */
+	write_item_p->prev = NULL;
+	write_item_p->next = NULL;
+	write_item_p->list = list;
+	write_item_p->buffer = NULL;
+	strncpy(write_item_p->name, list->name, RSBAC_LIST_MAX_FILENAME);
+	write_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
+	write_item_p->device = list->device;
+
+	buffer = rsbac_kmalloc(RSBAC_LIST_BUFFER_SIZE);
+	if (unlikely(!buffer)) {
+		rsbac_kfree(write_item_p);
+		*write_item_pp = NULL;
+		return -RSBAC_ENOMEM;
+	}
+	write_item_p->buffer = buffer;
+	buffer->len = 0;
+	buffer->next = NULL;
+	/* copy version */
+	memcpy(buffer->data, &list_version, sizeof(list_version));
+	buffer->len = sizeof(list_version);
+	/* copy timestamp */
+	memcpy(buffer->data + buffer->len,
+	       &timestamp, sizeof(timestamp));
+	buffer->len += sizeof(timestamp);
+	/* copy info */
+	memcpy(buffer->data + buffer->len,
+	       &list->info, sizeof(list->info));
+	buffer->len += sizeof(list->info);
+
+	/* Protect list */
+	spin_lock(&list->lock);
+	for (i=0; i<nr_hashes; i++)
+		allcount += list->hashed[i].count;
+	/* copy lastchange */
+	memcpy(buffer->data + buffer->len,
+	       &list->lastchange, sizeof(list->lastchange));
+	buffer->len += sizeof(list->lastchange);
+	/* copy count */
+	memcpy(buffer->data + buffer->len,
+	       &allcount, sizeof(allcount));
+	buffer->len += sizeof(allcount);
+	/* copy list */
+	for (i=0; i<nr_hashes; i++) {
+		current_p = list->hashed[i].head;
+		while (current_p) {
+			if (unlikely(check_buffer(&buffer, sizeof(current_p->max_age) + list->info.desc_size + list->info.data_size))) {
+				/* unprotect this list */
+				spin_unlock(&list->lock);
+				free_buffers(write_item_p->buffer);
+				rsbac_kfree(write_item_p);
+				*write_item_pp = NULL;
+				return -RSBAC_ENOMEM;
+			}
+			memcpy(buffer->data + buffer->len,
+			       &current_p->max_age, sizeof(current_p->max_age));
+			buffer->len += sizeof(current_p->max_age);
+			memcpy(buffer->data + buffer->len,
+			       ((char *) current_p) + sizeof(*current_p),
+			       list->info.desc_size + list->info.data_size);
+			buffer->len += list->info.desc_size + list->info.data_size;
+			current_p = current_p->next;
+		}
+	}
+	spin_unlock(&list->lock);
+
+	*write_item_pp = write_item_p;
+
+	return 0;
+}
+
+/* call unlocked */
+static int rsbac_list_write_buffers(struct rsbac_list_write_head_t write_head)
+{
+	struct file *file_p;
+	int count = 0;
+	mm_segment_t oldfs;
+	u_int written;
+	u_long all_written;
+	u_long bytes;
+	u_int bufcount;
+	int tmperr = 0;
+	struct rsbac_list_buffer_t * buffer;
+	struct rsbac_list_write_item_t *write_item_p;
+	struct rsbac_list_write_item_t *next_item_p;
+
+	write_item_p = write_head.head;
+	while (write_item_p) {
+		rsbac_pr_debug(write, "write list %s on device %02u:%02u.\n",
+			       write_item_p->name,
+			       RSBAC_MAJOR(write_item_p->device),
+			       RSBAC_MINOR(write_item_p->device));
+		/* open file */
+		if ((tmperr = rsbac_write_open(write_item_p->name,
+					       &file_p,
+					       write_item_p->device))) {
+			if (tmperr != -RSBAC_ENOTWRITABLE) {
+				rsbac_printk(KERN_WARNING "rsbac_list_write_buffers(): opening file %s on device %02u:%02u failed with error %i!\n",
+					     write_item_p->name,
+					     RSBAC_MAJOR(write_item_p->
+							 device),
+					     RSBAC_MINOR(write_item_p->
+							 device), tmperr);
+			}
+			count = tmperr;
+			goto out_free_all;
+		}
+
+		/* OK, now we can start writing the buffer. */
+		/* Set current user space to kernel space, because write() reads    */
+		/* from user space */
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+
+		buffer = write_item_p->buffer;
+		all_written = 0;
+		bufcount = 0;
+		while (buffer && (tmperr >= 0)) {
+			rsbac_pr_debug(write, "Writing list %s, buffer %u with size %u\n",
+					write_item_p->name, bufcount, buffer->len);
+			bufcount++;
+			written = 0;
+			while ((written < buffer->len) && (tmperr >= 0)) {
+				bytes = buffer->len - written;
+				tmperr = __vfs_write(file_p,
+							buffer->data + written,
+							bytes,
+							&file_p->f_pos);
+				if (tmperr > 0) {
+					written += tmperr;
+				}
+			}
+			all_written += written;
+			buffer = buffer->next;
+		}
+		/* Set current user space back to user space, because write() reads */
+		/* from user space */
+		set_fs(oldfs);
+		/* End of write access */
+		rsbac_write_close(file_p);
+		if (tmperr < 0) {
+			rsbac_printk(KERN_WARNING "rsbac_list_write_buffers(): write error %i on device %02u:%02u file %s!\n",
+				     tmperr,
+				     RSBAC_MAJOR(write_item_p->device),
+				     RSBAC_MINOR(write_item_p->device),
+				     write_item_p->name);
+			count = tmperr;
+			goto out_free_all;
+		} else
+			count++;
+
+		rsbac_pr_debug(write, "%lu bytes from %u buffers written.\n",
+			       all_written, bufcount);
+
+		free_buffers(write_item_p->buffer);
+		next_item_p = write_item_p->next;
+		rsbac_kfree(write_item_p);
+		write_item_p = next_item_p;
+	}
+	return count;
+
+out_free_all:
+    /* Mark unwritten lists dirty and free everything */
+    while(write_item_p)
+      {
+        if(write_item_p->list->self == write_item_p->list)
+          write_item_p->list->dirty = TRUE;
+	free_buffers(write_item_p->buffer);
+        next_item_p = write_item_p->next;
+        rsbac_kfree(write_item_p);
+        write_item_p = next_item_p;
+      }
+    return count;
+}
+
+/* call unlocked */
+static int fill_lol_buffer(struct rsbac_list_lol_reg_item_t *list,
+			   struct rsbac_list_lol_write_item_t
+			   **write_item_pp)
+{
+	struct rsbac_list_lol_write_item_t *write_item_p;
+	struct rsbac_list_lol_item_t *current_p;
+	struct rsbac_list_item_t *sub_p;
+        struct rsbac_list_buffer_t *buffer = NULL;
+        rsbac_list_count_t allcount = 0;
+	rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
+	rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
+	int i;
+	const u_int nr_hashes = 1 << list->hash_bits;
+
+	write_item_p = rsbac_kmalloc_unlocked(sizeof(*write_item_p));
+	if (unlikely(!write_item_p)) {
+		*write_item_pp = NULL;
+		return (-RSBAC_ENOMEM);
+	}
+
+	rsbac_pr_debug(write, "Filling buffers for list of lists %s\n",
+		       list->name);
+	/* fill write_item */
+	write_item_p->prev = NULL;
+	write_item_p->next = NULL;
+	write_item_p->list = list;
+	write_item_p->buffer = NULL;
+	strncpy(write_item_p->name, list->name, RSBAC_LIST_MAX_FILENAME);
+	write_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
+	write_item_p->device = list->device;
+
+	buffer = rsbac_kmalloc(RSBAC_LIST_BUFFER_SIZE);
+	if (unlikely(!buffer)) {
+		rsbac_kfree(write_item_p);
+		*write_item_pp = NULL;
+		return -RSBAC_ENOMEM;
+	}
+	write_item_p->buffer = buffer;
+	buffer->len = 0;
+	buffer->next = NULL;
+	/* copy version */
+	memcpy(buffer->data, (char *) &list_version, sizeof(list_version));
+	buffer->len = sizeof(list_version);
+	/* copy timestamp */
+	memcpy(buffer->data + buffer->len,
+	       (char *) &timestamp, sizeof(timestamp));
+	buffer->len += sizeof(timestamp);
+	/* copy info */
+	memcpy(buffer->data + buffer->len,
+	       (char *) &list->info, sizeof(list->info));
+	buffer->len += sizeof(list->info);
+	/* protect list */
+	spin_lock(&list->lock);
+	for (i=0; i<nr_hashes; i++)
+		allcount += list->hashed[i].count;
+	/* copy lastchange */
+	memcpy(buffer->data + buffer->len,
+	       (char *) &list->lastchange, sizeof(list->lastchange));
+	buffer->len += sizeof(list->lastchange);
+	/* copy count */
+	memcpy(buffer->data + buffer->len,
+	       (char *) &allcount, sizeof(allcount));
+	buffer->len += sizeof(allcount);
+	/* copy list */
+	for (i=0; i<nr_hashes; i++) {
+		current_p = list->hashed[i].head;
+		while (current_p) {
+			if (unlikely(check_buffer(&buffer, sizeof(current_p->max_age)
+				 + list->info.desc_size
+				 + list->info.data_size
+				 + sizeof(current_p->count)))) {
+				/* unprotect this list */
+				spin_unlock(&list->lock);
+				free_buffers(write_item_p->buffer);
+				rsbac_kfree(write_item_p);
+				*write_item_pp = NULL;
+				return -RSBAC_ENOMEM;
+			}
+			memcpy(buffer->data + buffer->len,
+			       &current_p->max_age, sizeof(current_p->max_age));
+			buffer->len += sizeof(current_p->max_age);
+			memcpy(buffer->data + buffer->len,
+			       ((char *) current_p) + sizeof(*current_p),
+			       list->info.desc_size + list->info.data_size);
+			buffer->len += list->info.desc_size + list->info.data_size;
+			memcpy(buffer->data + buffer->len,
+			       &current_p->count, sizeof(current_p->count));
+			buffer->len += sizeof(current_p->count);
+			/* copy subitems */
+			sub_p = current_p->head;
+			while (sub_p) {
+				if (unlikely(check_buffer(&buffer, sizeof(sub_p->max_age)
+					 + list->info.subdesc_size
+					 + list->info.subdata_size))) {
+					/* unprotect this list */
+					spin_unlock(&list->lock);
+					free_buffers(write_item_p->buffer);
+					rsbac_kfree(write_item_p);
+					*write_item_pp = NULL;
+					return -RSBAC_ENOMEM;
+				}
+				memcpy(buffer->data + buffer->len,
+				       &sub_p->max_age, sizeof(sub_p->max_age));
+				buffer->len += sizeof(sub_p->max_age);
+				memcpy(buffer->data + buffer->len,
+				       ((char *) sub_p) + sizeof(*sub_p),
+				       list->info.subdesc_size +
+				       list->info.subdata_size);
+				buffer->len +=
+				    list->info.subdesc_size +
+				    list->info.subdata_size;
+				sub_p = sub_p->next;
+			}
+			current_p = current_p->next;
+		}
+	}
+	/* unprotect this list */
+	spin_unlock(&list->lock);
+	*write_item_pp = write_item_p;
+
+	return 0;
+}
+
+/* call unlocked */
+static int rsbac_list_write_lol_buffers(struct rsbac_list_lol_write_head_t
+					write_head)
+{
+	struct file *file_p;
+	int count = 0;
+	mm_segment_t oldfs;
+	u_long written;
+        u_long all_written;
+	u_long bytes;
+        u_int bufcount;
+	int tmperr = 0;
+        struct rsbac_list_buffer_t * buffer;
+	struct rsbac_list_lol_write_item_t *write_item_p;
+	struct rsbac_list_lol_write_item_t *next_item_p;
+
+	write_item_p = write_head.head;
+	while (write_item_p) {
+		rsbac_pr_debug(write, "write list of lists %s on device %02u:%02u.\n",
+			       write_item_p->name,
+			       RSBAC_MAJOR(write_item_p->device),
+			       RSBAC_MINOR(write_item_p->device));
+		/* open file */
+		if ((tmperr = rsbac_write_open(write_item_p->name,
+					       &file_p,
+					       write_item_p->device))) {
+			if (tmperr != -RSBAC_ENOTWRITABLE) {
+				rsbac_printk(KERN_WARNING "rsbac_list_write_lol_buffers(): opening file %s on device %02u:%02u failed with error %i!\n",
+					     write_item_p->name,
+					     RSBAC_MAJOR(write_item_p->
+							 device),
+					     RSBAC_MINOR(write_item_p->
+							 device), tmperr);
+			}
+			goto out_free_all;
+		}
+
+		/* OK, now we can start writing the buffer. */
+		/* Set current user space to kernel space, because write() reads    */
+		/* from user space */
+		oldfs = get_fs();
+		set_fs(KERNEL_DS);
+
+		buffer = write_item_p->buffer;
+		all_written = 0;
+		bufcount = 0;
+		while (buffer && (tmperr >= 0)) {
+			rsbac_pr_debug(write, "Writing list of lists %s, buffer %u with size %u\n",
+					write_item_p->name, bufcount, buffer->len);
+			bufcount++;
+			written = 0;
+			while ((written < buffer->len) && (tmperr >= 0)) {
+				bytes = buffer->len - written;
+				tmperr = __vfs_write(file_p,
+							buffer->data + written,
+							bytes,
+							&file_p->f_pos);
+				if (tmperr > 0) {
+					written += tmperr;
+				}
+			}
+			all_written += written;
+			buffer = buffer->next;
+		}
+		/* Set current user space back to user space, because write() reads */
+		/* from user space */
+		set_fs(oldfs);
+		/* End of write access */
+		rsbac_write_close(file_p);
+
+		if (tmperr < 0) {
+			rsbac_printk(KERN_WARNING "rsbac_list_write_lol_buffers(): write error %i on device %02u:%02u file %s!\n",
+				     tmperr,
+				     RSBAC_MAJOR(write_item_p->device),
+				     RSBAC_MINOR(write_item_p->device),
+				     write_item_p->name);
+			count = tmperr;
+			goto out_free_all;
+		} else
+			count++;
+
+		rsbac_pr_debug(write, "%lu bytes from %u buffers written.\n",
+			       all_written, bufcount);
+                free_buffers(write_item_p->buffer);
+		next_item_p = write_item_p->next;
+		rsbac_kfree(write_item_p);
+		write_item_p = next_item_p;
+	}
+	return count;
+
+out_free_all:
+    /* Mark unwritten lists dirty and free everything */
+    while(write_item_p)
+      {
+        if(write_item_p->list->self == write_item_p->list)
+          write_item_p->list->dirty = TRUE;
+	free_buffers(write_item_p->buffer);
+        next_item_p = write_item_p->next;
+        rsbac_kfree(write_item_p);
+        write_item_p = next_item_p;
+      }
+    return count;
+}
+#endif				/* ifndef CONFIG_RSBAC_NO_WRITE */
+
+/************************************************* */
+/*           PROC support                          */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC)
+static int
+lists_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	struct rsbac_list_reg_item_t *item_p;
+	struct rsbac_list_lol_reg_item_t *lol_item_p;
+	int i;
+	u_long tmp_count;
+	int srcu_idx;
+	struct rsbac_list_hashed_t * hashed;
+	struct rsbac_list_lol_hashed_t * lol_hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!rsbac_is_initialized()))
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		    "Generic Lists Status\n--------------------\nMaximum number of hash bits per list/list of lists is %u\nrsbac_list_auto_rehash_trigger is %u\n%u list read failures\n",
+		    rsbac_list_max_hash_bits, rsbac_list_auto_rehash_trigger, rsbac_list_read_errors);
+#ifdef CONFIG_RSBAC_RC_LEARN_TA
+	seq_printf(m, "RC   Learning Mode transaction Number: %u\n",
+		CONFIG_RSBAC_RC_LEARN_TA);
+#endif
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+	seq_printf(m, "AUTH Learning Mode transaction Number: %u\n",
+		CONFIG_RSBAC_AUTH_LEARN_TA);
+#endif
+#ifdef CONFIG_RSBAC_ACL_LEARN_TA
+	seq_printf(m, "ACL  Learning Mode transaction Number: %u\n",
+		CONFIG_RSBAC_ACL_LEARN_TA);
+#endif
+#ifdef CONFIG_RSBAC_CAP_LEARN_TA
+	seq_printf(m, "CAP  Learning Mode transaction Number: %u\n",
+		CONFIG_RSBAC_CAP_LEARN_TA);
+#endif
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (rsbac_list_count(ta_handle) > 0) {
+		int list_count;
+		rsbac_list_ta_number_t *desc_array;
+		struct rsbac_list_ta_data_t data;
+
+		seq_printf(m, "\nTransactions active:\n\n");
+		list_count =
+		    rsbac_list_get_all_desc(ta_handle,
+					    (void **) &desc_array);
+		if (list_count > 0) {
+			int i;
+			rsbac_time_t now = RSBAC_CURRENT_TIME;
+
+			for (i = 0; i < list_count; i++) {
+				if (!rsbac_list_get_data
+				    (ta_handle, &desc_array[i], &data)) {
+					seq_printf(m,
+						    "%u %s (ttl %is)\n",
+						    desc_array[i],
+						    data.name,
+						    data.timeout - now);
+				}
+			}
+			rsbac_kfree(desc_array);
+		}
+
+		seq_printf(m,
+			    "\nLists in Transaction\n--------------------\nName\t\tdevice\thash\tta\t     count\n");
+
+		list_count = 0;
+		srcu_idx = srcu_read_lock(&reg_list_srcu);
+		item_p = srcu_dereference(reg_head.head, &reg_list_srcu);
+		while (item_p) {
+			rcu_read_lock();
+			nr_hashes = 1 << item_p->hash_bits;
+			hashed = rcu_dereference(item_p->hashed);
+			for (i=0; i<nr_hashes; i++) {
+				if (hashed[i].ta_copied) {
+					seq_printf(m,
+						    "%-16s%02u:%02u\t%u\t%10u\t%u\n",
+						    item_p->name,
+						    RSBAC_MAJOR(item_p->device),
+						    RSBAC_MINOR(item_p->device),
+						    i,
+						    hashed[i].ta_copied,
+						    hashed[i].ta_count);
+					list_count++;
+				}
+			}
+			rcu_read_unlock();
+			item_p = srcu_dereference(item_p->next, &reg_list_srcu);
+		}
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+
+		seq_printf(m,
+			    "\n %u lists in transaction.\n\n", list_count);
+		seq_printf(m,
+			    "Lists of Lists in Transaction\n-----------------------------\nName\t\tdevice\thash\tta\t     count\n");
+		list_count = 0;
+		srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+		lol_item_p = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+		while (lol_item_p) {
+			rcu_read_lock();
+			nr_hashes = 1 << lol_item_p->hash_bits;
+			lol_hashed = rcu_dereference(lol_item_p->hashed);
+			for (i=0; i<nr_hashes; i++) {
+				if (lol_hashed[i].ta_copied) {
+					seq_printf(m,
+						    "%-16s%02u:%02u\t%u\t%10u\t%u\n",
+						    lol_item_p->name,
+						    RSBAC_MAJOR(lol_item_p->
+								device),
+						    RSBAC_MINOR(lol_item_p->
+								device),
+						    i,
+						    lol_hashed[i].ta_copied,
+						    lol_hashed[i].ta_count);
+					list_count++;
+				}
+			}
+			rcu_read_unlock();
+			lol_item_p = srcu_dereference(lol_item_p->next, &lol_reg_list_srcu);
+		}
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+
+		seq_printf(m,
+			    "\n %u lists of lists in transaction.\n\n",
+			    list_count);
+	} else
+		seq_printf(m, "No active transaction\n");
+#endif
+	seq_printf(m,
+		    "\nRegistered Generic Lists (item size %u + per hash %u)\n------------------------\n",
+		    (int) sizeof(struct rsbac_list_reg_item_t), (int) sizeof(struct rsbac_list_hashed_t));
+	seq_printf(m,
+		    "Name\t\tdevice\tcount\tdesc\tdata\tpersist\tnow/dir\tflags\thashbits\n");
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	item_p = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while (item_p) {
+		rcu_read_lock();
+		nr_hashes = 1 << item_p->hash_bits;
+		hashed = rcu_dereference(item_p->hashed);
+		tmp_count = 0;
+		for (i=0; i<nr_hashes; i++)
+			tmp_count += hashed[i].count;
+		rcu_read_unlock();
+		seq_printf(m,
+			    "%-16s%02u:%02u\t%lu\t%u\t%u\t%u\t%u/%u\t%u\t%u\n",
+			    item_p->name, RSBAC_MAJOR(item_p->device),
+			    RSBAC_MINOR(item_p->device), tmp_count,
+			    item_p->info.desc_size, item_p->info.data_size,
+			    item_p->flags & RSBAC_LIST_PERSIST,
+			    item_p->no_write,
+			    item_p->dirty & (item_p->
+					     flags & RSBAC_LIST_PERSIST),
+			    item_p->flags,
+			    item_p->hash_bits);
+		item_p = srcu_dereference(item_p->next, &reg_list_srcu);
+	}
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+
+	seq_printf(m, "\n %u lists registered.\n\n",
+		       reg_head.count);
+	seq_printf(m,
+		    "Registered Generic Lists of Lists (item size %u + per hash %u)\n---------------------------------\n",
+		    (int) sizeof(struct rsbac_list_lol_reg_item_t), (int) sizeof(struct rsbac_list_lol_hashed_t));
+	seq_printf(m,
+		    "Name\t\tdevice\tcount\tdesc\tdata\tpersist\tnow/dir\tflags\thashbits\n");
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	lol_item_p = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while (lol_item_p) {
+		rcu_read_lock();
+		nr_hashes = 1 << lol_item_p->hash_bits;
+		lol_hashed = rcu_dereference(lol_item_p->hashed);
+		tmp_count = 0;
+		for (i=0; i<nr_hashes; i++)
+			tmp_count += lol_hashed[i].count;
+		rcu_read_unlock();
+		seq_printf(m,
+			    "%-16s%02u:%02u\t%lu\t%u+%u\t%u+%u\t%u\t%u/%u\t%u\t%u\n",
+			    lol_item_p->name,
+			    RSBAC_MAJOR(lol_item_p->device),
+			    RSBAC_MINOR(lol_item_p->device),
+			    tmp_count, lol_item_p->info.desc_size,
+			    lol_item_p->info.subdesc_size,
+			    lol_item_p->info.data_size,
+			    lol_item_p->info.subdata_size,
+			    lol_item_p->flags & RSBAC_LIST_PERSIST,
+			    lol_item_p->no_write,
+			    lol_item_p->dirty & (lol_item_p->
+						 flags &
+						 RSBAC_LIST_PERSIST),
+			    lol_item_p->flags,
+			    lol_item_p->hash_bits);
+		lol_item_p = srcu_dereference(lol_item_p->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+
+	seq_printf(m, "\n %u lists of lists registered.\n",
+		       lol_reg_head.count);
+	return 0;
+}
+
+static int lists_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, lists_proc_show, NULL);
+}
+
+static const struct file_operations lists_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = lists_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *lists_proc;
+
+static int
+lists_counts_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	struct rsbac_list_reg_item_t *item_p;
+	struct rsbac_list_lol_reg_item_t *lol_item_p;
+	int i;
+#ifdef CONFIG_RSBAC_LIST_STATS
+	__u64 all_read = 0;
+	__u64 all_write = 0;
+#endif
+	int srcu_idx;
+	struct rsbac_list_hashed_t * hashed;
+	struct rsbac_list_lol_hashed_t * lol_hashed;
+	u_int nr_hashes;
+	u_long subcount;
+	struct rsbac_list_lol_item_t *sublist;
+
+	if (unlikely(!rsbac_is_initialized()))
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		    "Generic Lists Status\n--------------------\nMaximum number of hash bits per list/list of lists is %u\n\n",
+		    rsbac_list_max_hash_bits);
+	seq_printf(m,
+		    "Registered Generic Lists (item size %u + per hash %u)\n------------------------\n",
+		    (int) sizeof(struct rsbac_list_reg_item_t), (int) sizeof(struct rsbac_list_hashed_t));
+#ifdef CONFIG_RSBAC_LIST_STATS
+	seq_printf(m,
+		    "Name\t\tdevice\tmaxitem\treads\twrites\thashbit\tcounts\n");
+#else
+	seq_printf(m,
+		    "Name\t\tdevice\tmaxitem\thashbit\tcounts\n");
+#endif
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	item_p = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while (item_p) {
+#ifdef CONFIG_RSBAC_LIST_STATS
+		seq_printf(m,
+			    "%-16s%02u:%02u\t%u\t%llu\t%llu\t%u\t",
+			    item_p->name, RSBAC_MAJOR(item_p->device),
+			    RSBAC_MINOR(item_p->device),
+			    item_p->max_items_per_hash,
+			    item_p->read_count,
+			    item_p->write_count,
+			    item_p->hash_bits);
+		all_read += item_p->read_count;
+		all_write += item_p->write_count;
+#else
+		seq_printf(m,
+			    "%-16s%02u:%02u\t%u\t%u\t",
+			    item_p->name, RSBAC_MAJOR(item_p->device),
+			    RSBAC_MINOR(item_p->device),
+			    item_p->max_items_per_hash,
+			    item_p->hash_bits);
+#endif
+		rcu_read_lock();
+		nr_hashes = 1 << item_p->hash_bits;
+		hashed = rcu_dereference(item_p->hashed);
+		for (i=0; i<nr_hashes; i++) {
+			seq_printf(m,
+				    "%u ",
+				    hashed[i].count);
+		}
+		rcu_read_unlock();
+		seq_printf(m,
+			    "\n");
+		item_p = srcu_dereference(item_p->next, &reg_list_srcu);
+	}
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	seq_printf(m, "\n %u lists registered, %llu reads, %llu writes\n\n",
+		       reg_head.count, all_read, all_write);
+	all_read = 0;
+	all_write = 0;
+#else
+	seq_printf(m, "\n %u lists registered.\n\n",
+		       reg_head.count);
+#endif
+	seq_printf(m,
+		    "Registered Generic Lists of Lists (item size %u + per hash %u)\n---------------------------------\n",
+		    (int) sizeof(struct rsbac_list_lol_reg_item_t), (int) sizeof(struct rsbac_list_lol_hashed_t));
+#ifdef CONFIG_RSBAC_LIST_STATS
+	seq_printf(m,
+		    "Name\t\tdevice\tmaxitem\tmaxsubi\treads\twrites\thashbit\tcounts(sub)\n");
+#else
+	seq_printf(m,
+		    "Name\t\tdevice\tmaxitem\tmaxsubi\thashbit\tcounts(sub)\n");
+#endif
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	lol_item_p = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while (lol_item_p) {
+#ifdef CONFIG_RSBAC_LIST_STATS
+		seq_printf(m,
+			    "%-16s%02u:%02u\t%u\t%u\t%llu\t%llu\t%u\t",
+			    lol_item_p->name, RSBAC_MAJOR(lol_item_p->device),
+			    RSBAC_MINOR(lol_item_p->device),
+			    lol_item_p->max_items_per_hash,
+			    lol_item_p->max_subitems,
+			    lol_item_p->read_count,
+			    lol_item_p->write_count,
+			    lol_item_p->hash_bits);
+		all_read += lol_item_p->read_count;
+		all_write += lol_item_p->write_count;
+#else
+		seq_printf(m,
+			    "%-16s%02u:%02u\t%u\t%u\t%u\t",
+			    lol_item_p->name, RSBAC_MAJOR(lol_item_p->device),
+			    RSBAC_MINOR(lol_item_p->device),
+			    lol_item_p->max_items_per_hash,
+			    lol_item_p->max_subitems,
+			    lol_item_p->hash_bits);
+#endif
+		rcu_read_lock();
+		nr_hashes = 1 << lol_item_p->hash_bits;
+		lol_hashed = rcu_dereference(lol_item_p->hashed);
+		for (i=0; i<nr_hashes; i++) {
+			subcount = 0;
+
+			sublist = rcu_dereference(lol_hashed[i].head);
+			while (sublist) {
+				subcount += sublist->count;
+				sublist = rcu_dereference(sublist->next);
+			}
+			seq_printf(m,
+				    "%u(%lu) ",
+				    lol_hashed[i].count,
+				    subcount);
+		}
+		rcu_read_unlock();
+		seq_printf(m,
+			    "\n");
+		lol_item_p = srcu_dereference(lol_item_p->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	seq_printf(m, "\n %u lists of lists registered, %llu reads, %llu writes\n\nRCU Garbage Collector call statistics\n-------------------------------------\n",
+		       lol_reg_head.count, all_read, all_write);
+	seq_printf(m, "rcu_free:                   %llu\n", rcu_free_calls);
+	seq_printf(m, "rcu_free_item_chain:        %llu\n", rcu_free_item_chain_calls);
+	seq_printf(m, "rcu_free_lol:               %llu\n", rcu_free_lol_calls);
+	seq_printf(m, "rcu_free_lol_sub:           %llu\n", rcu_free_lol_sub_calls);
+	seq_printf(m, "rcu_free_lol_item_chain:    %llu\n", rcu_free_lol_item_chain_calls);
+	seq_printf(m, "rcu_free_lol_subitem_chain: %llu\n", rcu_free_lol_subitem_chain_calls);
+	seq_printf(m, "rcu_free_do_cleanup:        %llu\n", rcu_free_do_cleanup_calls);
+	seq_printf(m, "rcu_free_do_cleanup_lol:    %llu\n", rcu_free_do_cleanup_lol_calls);
+	seq_printf(m, "rcu_free_callback:          %llu\n", rcu_free_callback_calls);
+	seq_printf(m, "rcu_free_callback_lol:      %llu\n", rcu_free_callback_lol_calls);
+	seq_printf(m, "rcu_callback_count:         %u\n", rcu_callback_count);
+	seq_printf(m, "max_rcu_callback_count:     %u\n", max_rcu_callback_count);
+	seq_printf(m, "rcu_rate:                   %u/s\n", rsbac_list_rcu_rate);
+	seq_printf(m, "system RCU total completed: %lu\n", rcu_batches_completed());
+#else
+	seq_printf(m, "\n %u lists of lists registered.\n",
+		       lol_reg_head.count);
+#endif
+	return 0;
+}
+
+static int lists_counts_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, lists_counts_proc_show, NULL);
+}
+
+static const struct file_operations lists_counts_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = lists_counts_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *lists_counts_proc;
+
+/* Generic backup generation function */
+static int backup_proc_show(struct seq_file *m, void *data)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *current_p;
+	rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
+	rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
+	int srcu_idx;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+	int i;
+
+	if (unlikely(!rsbac_is_initialized()))
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	list = lookup_reg(data);
+	if (unlikely(!list)) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		return -ENOSYS;
+	}
+	/* copy version */
+	seq_write(m, &list_version, sizeof(list_version));
+	/* copy version */
+	seq_write(m, &timestamp, sizeof(timestamp));
+	/* copy info */
+	seq_write(m, &list->info, sizeof(list->info));
+
+	rcu_read_lock();
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	/* copy list */
+	for (i=0; i<nr_hashes; i++) {
+		current_p = rcu_dereference(hashed[i].head);
+		while (current_p) {
+			seq_write(m,
+			       ((char *) current_p) + sizeof(*current_p),
+			       list->info.desc_size + list->info.data_size);
+			current_p = rcu_dereference(current_p->next);
+		}
+	}
+
+	rcu_read_unlock();
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+/* Generic lists of lists backup generation function */
+static int lol_backup_proc_show(struct seq_file *m, void *data)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *current_p;
+	struct rsbac_list_item_t *sub_p;
+	rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
+	rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
+	int srcu_idx;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+	int i;
+
+	if (unlikely(!rsbac_is_initialized()))
+		return -ENOSYS;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	list = lookup_lol_reg(data);
+	if (unlikely(!list)) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		return -ENOSYS;
+	}
+	/* copy version */
+	seq_write(m, &list_version, sizeof(list_version));
+	/* copy version */
+	seq_write(m, &timestamp, sizeof(timestamp));
+	/* copy info */
+	seq_write(m, &list->info, sizeof(list->info));
+
+	rcu_read_lock();
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	/* copy list */
+	for (i=0; i<nr_hashes; i++) {
+		current_p = rcu_dereference(hashed[i].head);
+		while (current_p) {
+			seq_write(m,
+			       ((char *) current_p) + sizeof(*current_p),
+			       list->info.desc_size + list->info.data_size);
+			seq_write(m,
+			       &current_p->count, sizeof(current_p->count));
+			/* copy sublist */
+			sub_p = rcu_dereference(current_p->head);
+	 		while (sub_p) {
+				seq_write(m,
+				       ((char *) sub_p) + sizeof(*sub_p),
+				       list->info.subdesc_size +
+				       list->info.subdata_size);
+				sub_p = rcu_dereference(sub_p->next);
+			}
+			current_p = rcu_dereference(current_p->next);
+		}
+	}
+	rcu_read_unlock();
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+	return 0;
+}
+#endif				/* PROC */
+
+
+/********************/
+/* Init and general */
+/********************/
+int rsbac_list_compare_u32(void * desc1, void * desc2)
+  {
+    if( *((__u32*) desc1) < *((__u32*) desc2))
+      return -1;
+    return( *((__u32*) desc1) != *((__u32*) desc2));
+  }
+
+static void rcu_rate_reset(u_long dummy)
+{
+#ifdef CONFIG_RSBAC_DEBUG
+	if (rcu_callback_count > rsbac_list_rcu_rate) {
+		rsbac_pr_debug(lists,
+				"rcu_callback_count %u over rcu_rate %u, list write accesses have been throttled\n",
+				rcu_callback_count, rsbac_list_rcu_rate);
+	}
+#endif
+#ifdef CONFIG_RSBAC_LIST_STATS
+	if (rcu_callback_count > max_rcu_callback_count)
+		max_rcu_callback_count = rcu_callback_count;
+#endif
+	rcu_callback_count = 0;
+
+	mod_timer(&rcu_rate_timer, jiffies + HZ);
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_list_init(void)
+#else
+int __init rsbac_list_init(void)
+#endif
+{
+#if defined(CONFIG_RSBAC_LIST_TRANS) || defined(CONFIG_RSBAC_LIST_REPL)
+	int err;
+	struct rsbac_list_info_t *list_info_p;
+#endif
+	reg_item_slab = rsbac_slab_create_rcu("rsbac_reg_item",
+					sizeof(struct rsbac_list_reg_item_t));
+	lol_reg_item_slab = rsbac_slab_create_rcu("rsbac_lol_reg_item",
+					sizeof(struct rsbac_list_lol_reg_item_t));
+	rcu_free_item_slab = rsbac_slab_create("rsbac_rcu_free_item",
+					sizeof(struct rsbac_list_rcu_free_item_t));
+	rcu_free_head_slab = rsbac_slab_create("rsbac_rcu_free_head",
+					sizeof(struct rsbac_list_rcu_free_head_t));
+	rcu_free_head_lol_slab = rsbac_slab_create("rsbac_rcu_free_head_lol",
+					sizeof(struct rsbac_list_rcu_free_head_lol_t));
+
+	reg_head.head = NULL;
+	reg_head.tail = NULL;
+	reg_head.curr = NULL;
+	spin_lock_init(&reg_head.lock);
+	init_srcu_struct(&reg_list_srcu);
+	init_srcu_struct(&lol_reg_list_srcu);
+	reg_head.count = 0;
+
+	lol_reg_head.head = NULL;
+	lol_reg_head.tail = NULL;
+	lol_reg_head.curr = NULL;
+	spin_lock_init(&lol_reg_head.lock);
+	lol_reg_head.count = 0;
+
+	if(CONFIG_RSBAC_LIST_MAX_HASH_BITS < RSBAC_LIST_MIN_MAX_HASH_BITS)
+		rsbac_list_max_hash_bits = RSBAC_LIST_MIN_MAX_HASH_BITS;
+	else if (CONFIG_RSBAC_LIST_MAX_HASH_BITS > RSBAC_LIST_MAX_MAX_HASH_BITS)
+		rsbac_list_max_hash_bits = RSBAC_LIST_MAX_MAX_HASH_BITS;
+	else
+		rsbac_list_max_hash_bits = CONFIG_RSBAC_LIST_MAX_HASH_BITS;
+
+	list_initialized = TRUE;
+
+#if defined(CONFIG_RSBAC_LIST_TRANS) || defined(CONFIG_RSBAC_LIST_REPL)
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (unlikely(!list_info_p)) {
+		return -ENOMEM;
+	}
+#endif
+
+	/* init proc entry */
+#if defined(CONFIG_RSBAC_PROC)
+	{
+		lists_proc = proc_create(RSBAC_LIST_PROC_NAME, S_IFREG | S_IRUGO,
+				proc_rsbac_root_p, &lists_proc_fops);
+		lists_counts_proc = proc_create(RSBAC_LIST_COUNTS_PROC_NAME,
+						S_IFREG | S_IRUGO,
+						proc_rsbac_root_p,
+						&lists_counts_proc_fops);
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	rsbac_printk(KERN_INFO "rsbac_list_init(): Registering transaction list.\n");
+	list_info_p->version = 1;
+	list_info_p->key = RSBAC_LIST_TA_KEY;
+	list_info_p->desc_size = sizeof(rsbac_list_ta_number_t);
+	list_info_p->data_size = sizeof(struct rsbac_list_ta_data_t);
+	list_info_p->max_age = 0;
+	err = rsbac_list_register(RSBAC_LIST_VERSION,
+				  (void **) &ta_handle,
+				  list_info_p,
+				  0,
+				  NULL,
+				  NULL,
+				  NULL, "transactions", RSBAC_AUTO_DEV);
+	if (err) {
+		char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_list_init(): Registering transaction list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_LIST_TRANS) || defined(CONFIG_RSBAC_LIST_REPL)
+	rsbac_kfree(list_info_p);
+#endif
+
+        init_timer(&rcu_rate_timer);
+        rcu_rate_timer.function = rcu_rate_reset;
+        rcu_rate_timer.data = 0;
+        rcu_rate_timer.expires = jiffies + HZ;
+        add_timer(&rcu_rate_timer);
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_AUTO_WRITE
+int rsbac_list_auto_rehash(void);
+
+int rsbac_write_lists(void)
+{
+	int count = 0;
+	int subcount = 0;
+	int error = 0;
+	struct rsbac_list_reg_item_t *item_p;
+	struct rsbac_list_lol_reg_item_t *lol_item_p;
+	struct rsbac_list_write_head_t write_head;
+	struct rsbac_list_write_item_t *write_item_p;
+	struct rsbac_list_lol_write_head_t write_lol_head;
+	struct rsbac_list_lol_write_item_t *write_lol_item_p;
+	int srcu_idx;
+
+/*
+	rsbac_pr_debug(lists, "called.\n");
+*/
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (rsbac_list_count(ta_handle) > 0) {
+		int list_count;
+		rsbac_list_ta_number_t *desc_array;
+		struct rsbac_list_ta_data_t data;
+
+		list_count =
+		    rsbac_list_get_all_desc(ta_handle,
+					    (void **) &desc_array);
+		if (list_count > 0) {
+			int i;
+			rsbac_time_t now = RSBAC_CURRENT_TIME;
+
+			for (i = 0; i < list_count; i++) {
+				if (!rsbac_list_get_data
+				    (ta_handle, &desc_array[i], &data)) {
+					if (data.timeout < now) {
+						rsbac_printk(KERN_WARNING "rsbac_write_lists(): transaction %u timed out, forcing forget\n",
+							     desc_array
+							     [i]);
+						do_forget(desc_array[i]);
+					}
+				}
+			}
+			rsbac_kfree(desc_array);
+		}
+	}
+#endif
+
+	/* Init buffer list */
+	write_head.head = NULL;
+	write_head.tail = NULL;
+	write_head.count = 0;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	item_p = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while (item_p) {
+		if ((item_p->flags & RSBAC_LIST_PERSIST)
+		    && item_p->dirty && !item_p->no_write
+		    && !rsbac_debug_no_write) {
+		    	struct vfsmount *mnt_p;
+
+			mnt_p = rsbac_get_vfsmount(item_p->device);
+			if (mnt_p && rsbac_writable(mnt_p->mnt_sb)) {
+				item_p->dirty = FALSE;
+				error = fill_buffer(item_p, &write_item_p);
+				if (!error) {
+					if (!write_head.head) {
+						write_head.head = write_item_p;
+						write_head.tail = write_item_p;
+						write_head.count = 1;
+					} else {
+						write_head.tail->next =
+						    write_item_p;
+						write_item_p->prev =
+						    write_head.tail;
+						write_head.tail = write_item_p;
+						write_head.count++;
+					}
+				} else {
+					if ((error != -RSBAC_ENOTWRITABLE)
+					    && (error != -RSBAC_ENOMEM)
+					    ) {
+						rsbac_printk(KERN_WARNING "rsbac_write_lists(): fill_buffer() for list %s returned error %i\n",
+							     item_p->name, error);
+					item_p->dirty = TRUE;
+					}
+				}
+			}
+		}
+		item_p = srcu_dereference(item_p->next, &reg_list_srcu);
+	}
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+
+	if (write_head.count > 0)
+		rsbac_pr_debug(write, "%u lists copied to buffers\n",
+			       write_head.count);
+
+	/* write all buffers */
+	if (write_head.count) {
+		count = rsbac_list_write_buffers(write_head);
+		rsbac_pr_debug(write, "%u lists written to disk\n", count);
+	}
+
+	/* LOL */
+	/* Init buffer list */
+	write_lol_head.head = NULL;
+	write_lol_head.tail = NULL;
+	write_lol_head.count = 0;
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	lol_item_p = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while (lol_item_p) {
+		if ((lol_item_p->flags & RSBAC_LIST_PERSIST)
+		    && lol_item_p->dirty && !lol_item_p->no_write
+		    && !rsbac_debug_no_write) {
+		    	struct vfsmount *mnt_p;
+
+			mnt_p = rsbac_get_vfsmount(lol_item_p->device);
+			if (mnt_p && rsbac_writable(mnt_p->mnt_sb)) {
+				lol_item_p->dirty = FALSE;
+				error = fill_lol_buffer(lol_item_p, &write_lol_item_p);
+				if (!error) {
+					if (!write_lol_head.head) {
+						write_lol_head.head =
+							    write_lol_item_p;
+						write_lol_head.tail =
+						    write_lol_item_p;
+						write_lol_head.count = 1;
+					} else {
+						write_lol_head.tail->next =
+						    write_lol_item_p;
+						write_lol_item_p->prev =
+						    write_lol_head.tail;
+						write_lol_head.tail =
+						    write_lol_item_p;
+						write_lol_head.count++;
+					}
+				} else {
+					if ((error != -RSBAC_ENOTWRITABLE)
+					    && (error != -RSBAC_ENOMEM))
+					    {
+						rsbac_printk(KERN_WARNING "rsbac_write_lists(): fill_lol_buffer() for list %s returned error %i\n",
+							     lol_item_p->name,
+							     error);
+					}
+					lol_item_p->dirty = TRUE;
+				}
+			}
+		}
+		lol_item_p = srcu_dereference(lol_item_p->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+
+	if (write_lol_head.count > 0)
+		rsbac_pr_debug(write, "%u lists of lists copied to buffers\n",
+			       write_lol_head.count);
+	/* write all buffers */
+	if (write_lol_head.count) {
+		subcount =
+		    rsbac_list_write_lol_buffers(write_lol_head);
+		count += subcount;
+		rsbac_pr_debug(write, "%u lists of lists written to disk\n",
+			       subcount);
+	}
+	rsbac_pr_debug(write, "%u lists written.\n",
+		       count);
+
+	if(jiffies > next_rehash) {
+		rsbac_list_auto_rehash();
+		next_rehash = jiffies + (RSBAC_LIST_REHASH_INTERVAL * HZ);
+	}
+	return count;
+}
+#endif				/* CONFIG_RSBAC_AUTO_WRITE */
+
+/* Status checking */
+int rsbac_check_lists(const int correct)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_lol_reg_item_t *lol_list;
+	struct rsbac_list_item_t *item_p;
+	struct rsbac_list_item_t *next_item_p;
+	struct rsbac_list_lol_item_t *lol_item_p;
+	struct rsbac_list_lol_item_t *next_lol_item_p;
+	struct rsbac_list_item_t *lol_subitem_p;
+	struct rsbac_list_item_t *next_lol_subitem_p;
+	u_long tmp_count;
+	u_long tmp_subcount;
+	u_long subitem_count;
+	u_long dirty = 0;
+	u_int remove_count;
+	int i;
+	u_long all_count;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+	int srcu_idx;
+	u_int nr_hashes;
+
+	rsbac_pr_debug(lists, "called.\n");
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	list = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while (list) {
+restart:
+		nr_hashes = 1 << list->hash_bits;
+		remove_count = 0;
+		/* check list */
+		spin_lock(&list->lock);
+		all_count = 0;
+		for (i=0; i<nr_hashes; i++) {
+			tmp_count = 0;
+			item_p = list->hashed[i].head;
+			while (item_p) {
+				if ((item_p->max_age
+				     && (item_p->max_age <= RSBAC_CURRENT_TIME)
+				    )
+				    || (list->def_data
+					&& !memcmp(((char *) item_p) +
+						   sizeof(*item_p) +
+						   list->info.desc_size,
+						   list->def_data,
+						   list->info.data_size)
+				    )
+				    ) {
+					next_item_p = item_p->next;
+					do_remove_item(list, item_p, i);
+					remove_count++;
+					if (remove_count > rsbac_list_rcu_rate) {
+						rcu_head_p = get_rcu_free(list);
+						spin_unlock(&list->lock);
+						synchronize_rcu();
+						rcu_free_do_cleanup(rcu_head_p);
+						goto restart;
+					}
+					item_p = next_item_p;
+				} else {
+					tmp_count++;
+					if (tmp_count > (2 * list->max_items_per_hash)) {
+						tmp_count = 0;
+						rsbac_printk(KERN_WARNING "rsbac_check_lists(): list %s hash %u on device %02u:%02u counts an invalid number %lu of items, should be %u, skipping further checks!\n",
+							     list->name, i,
+							     RSBAC_MAJOR(list->device),
+							     RSBAC_MINOR(list->device),
+							     tmp_count, list->hashed[i].count);
+					}
+					item_p = item_p->next;
+				}
+			}
+			if ((tmp_count > 0) && (tmp_count != list->hashed[i].count)) {
+				if (correct) {
+					rsbac_printk(KERN_WARNING "rsbac_check_lists(): correcting count mismatch for list %s hash %u on device %02u:%02u - was %u, counted %lu!\n",
+						     list->name, i,
+						     RSBAC_MAJOR(list->device),
+						     RSBAC_MINOR(list->device),
+						     list->hashed[i].count, tmp_count);
+					list->hashed[i].count = tmp_count;
+				} else {
+					rsbac_printk(KERN_WARNING "rsbac_check_lists(): count mismatch for list %s hash %u on device %02u:%02u - is %u, counted %lu!\n",
+						     list->name, i,
+						     RSBAC_MAJOR(list->device),
+						     RSBAC_MINOR(list->device),
+						     list->hashed[i].count, tmp_count);
+				}
+			}
+			all_count += list->hashed[i].count;
+		}
+		rcu_head_p = get_rcu_free(list);
+		spin_unlock(&list->lock);
+		do_sync_rcu(rcu_head_p);
+		if (list->dirty && (list->flags & RSBAC_LIST_PERSIST)) {
+			dirty++;
+			rsbac_pr_debug(lists, "%s on %02u:%02u has %u items (list is dirty)\n",
+				       list->name, RSBAC_MAJOR(list->device),
+				       RSBAC_MINOR(list->device), all_count);
+		} else 
+			rsbac_pr_debug(lists, "%s on %02u:%02u has %u items\n",
+				       list->name, RSBAC_MAJOR(list->device),
+				       RSBAC_MINOR(list->device), all_count);
+		list = srcu_dereference(list->next, &reg_list_srcu);
+	}
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	lol_list = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while (lol_list) {
+lol_restart:
+		nr_hashes = 1 << lol_list->hash_bits;
+		remove_count = 0;
+		/* check list */
+		spin_lock(&lol_list->lock);
+		all_count = 0;
+		subitem_count = 0;
+		for (i=0; i<nr_hashes; i++) {
+			tmp_count = 0;
+			lol_item_p = lol_list->hashed[i].head;
+			while (lol_item_p) {
+				tmp_subcount = 0;
+				lol_subitem_p = lol_item_p->head;
+				while (lol_subitem_p) {
+					if ((lol_subitem_p->max_age
+					     && (lol_subitem_p->max_age <=
+						 RSBAC_CURRENT_TIME)
+					    )
+					    || (lol_list->def_subdata
+						&&
+						!memcmp(((char *)
+							 lol_subitem_p) +
+							sizeof
+							(*lol_subitem_p) +
+							lol_list->info.
+							subdesc_size,
+							lol_list->
+							def_subdata,
+							lol_list->info.
+							subdata_size)
+					    )
+					    ) {
+						next_lol_subitem_p =
+						    lol_subitem_p->next;
+						do_remove_lol_subitem
+						    (lol_item_p,
+						     lol_subitem_p);
+						rcu_free_lol_sub(lol_list, lol_subitem_p);
+						lol_subitem_p =
+						    next_lol_subitem_p;
+					} else {
+						tmp_subcount++;
+						lol_subitem_p =
+						    lol_subitem_p->next;
+					}
+				}
+				if (tmp_subcount != lol_item_p->count) {
+					if (correct) {
+						rsbac_printk(KERN_WARNING "rsbac_check_lists(): correcting count mismatch for list of lists %s hash %u sublist on %02u:%02u - was %lu, counted %lu!\n",
+							     lol_list->name, i,
+							     RSBAC_MAJOR
+							     (lol_list->
+							      device),
+							     RSBAC_MINOR
+							     (lol_list->
+							      device),
+							     lol_item_p->
+							     count,
+							     tmp_subcount);
+						lol_item_p->count =
+						    tmp_subcount;
+					} else {
+						rsbac_printk(KERN_WARNING "rsbac_check_lists(): count mismatch for list of lists %s hash %u sublist on %02u:%02u - is %lu, counted %lu!\n",
+							     lol_list->name, i,
+							     RSBAC_MAJOR
+							     (lol_list->
+							      device),
+							     RSBAC_MINOR
+							     (lol_list->
+							      device),
+							     lol_item_p->
+							     count,
+							     tmp_subcount);
+					}
+				}
+				if ((lol_item_p->max_age
+				     && (lol_item_p->max_age <= RSBAC_CURRENT_TIME)
+				    )
+				    || (lol_list->def_data
+					&& !lol_item_p->count
+					&& !memcmp(((char *) lol_item_p) +
+						   sizeof(*lol_item_p) +
+						   lol_list->info.desc_size,
+						   lol_list->def_data,
+						   lol_list->info.data_size)
+				    )
+				    || (!lol_list->info.data_size
+					&& (lol_list->flags & RSBAC_LIST_DEF_DATA)
+					&& !lol_item_p->count)
+				    ) {
+					next_lol_item_p = lol_item_p->next;
+					do_remove_lol_item(lol_list, lol_item_p, i);
+					remove_count++;
+					if (remove_count > rsbac_list_rcu_rate) {
+						rcu_head_lol_p = get_rcu_free_lol(lol_list);
+						spin_unlock(&lol_list->lock);
+						synchronize_rcu();
+						rcu_free_do_cleanup_lol(rcu_head_lol_p);
+						goto lol_restart;
+					}
+					lol_item_p = next_lol_item_p;
+				} else {
+					tmp_count++;
+					subitem_count += lol_item_p->count;
+					lol_item_p = lol_item_p->next;
+					if (tmp_count > (2 * lol_list->max_items_per_hash)) {
+						tmp_count = 0;
+						rsbac_printk(KERN_WARNING "rsbac_check_lists(): list of lists %s hash %u on device %02u:%02u counts an invalid number %lu of items, should be %u, skipping further checks!\n",
+							     lol_list->name, i,
+							     RSBAC_MAJOR(lol_list->device),
+							     RSBAC_MINOR(lol_list->device),
+							     tmp_count, lol_list->hashed[i].count);
+					}
+				}
+			}
+			if ((tmp_count > 0) && (tmp_count != lol_list->hashed[i].count)) {
+				if (correct) {
+					rsbac_printk(KERN_WARNING "rsbac_check_lists(): correcting count mismatch for list of lists %s hash %u on %02u:%02u - was %u, counted %lu!\n",
+						     lol_list->name, i,
+						     RSBAC_MAJOR(lol_list->device),
+						     RSBAC_MINOR(lol_list->device),
+						     lol_list->hashed[i].count, tmp_count);
+				lol_list->hashed[i].count = tmp_count;
+				} else {
+					rsbac_printk(KERN_WARNING "rsbac_check_lists(): count mismatch for list of lists %s hash %u on %02u:%02u - is %u, counted %lu!\n",
+						     lol_list->name, i,
+						     RSBAC_MAJOR(lol_list->device),
+						     RSBAC_MINOR(lol_list->device),
+						     lol_list->hashed[i].count, tmp_count);
+				}
+			}
+			all_count += lol_list->hashed[i].count;
+		}
+		rcu_head_lol_p = get_rcu_free_lol(lol_list);
+		spin_unlock(&lol_list->lock);
+		do_sync_rcu_lol(rcu_head_lol_p);
+		if (lol_list->dirty
+		    && (lol_list->flags & RSBAC_LIST_PERSIST)) {
+			dirty++;
+			rsbac_pr_debug(lists, "%s on %02u:%02u has %u items and %lu subitems (list is dirty)\n",
+				       lol_list->name,
+				       RSBAC_MAJOR(lol_list->device),
+				       RSBAC_MINOR(lol_list->device),
+				       all_count, subitem_count);
+		} else
+			rsbac_pr_debug(lists, "%s on %02u:%02u has %u items and %lu subitems\n",
+				       lol_list->name,
+				       RSBAC_MAJOR(lol_list->device),
+				       RSBAC_MINOR(lol_list->device),
+				       all_count, subitem_count);
+		lol_list = srcu_dereference(lol_list->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_check);
+#endif
+int rsbac_list_check(rsbac_list_handle_t handle, const int correct)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	struct rsbac_list_item_t *next_item_p;
+	u_long tmp_count;
+	int i;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+	u_int remove_count;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(!list || (list->self != list)))
+		return -RSBAC_EINVALIDLIST;
+
+	rsbac_pr_debug(lists, "checking list %s.\n", list->name);
+
+restart:
+	remove_count = 0;
+                
+	spin_lock(&list->lock);
+	nr_hashes = 1 << list->hash_bits;
+	for (i=0; i<nr_hashes; i++) {
+		tmp_count = 0;
+		item_p = list->hashed[i].head;
+		while (item_p) {
+			if ((item_p->max_age
+			     && (item_p->max_age <= RSBAC_CURRENT_TIME)
+			    )
+			    || (list->def_data
+				&& !memcmp(((char *) item_p) + sizeof(*item_p) +
+					   list->info.desc_size, list->def_data,
+					   list->info.data_size)
+			    )
+			    ) {
+				next_item_p = item_p->next;
+				do_remove_item(list, item_p, i);
+				remove_count++;
+				if (remove_count > rsbac_list_rcu_rate) {
+					rcu_head_p = get_rcu_free(list);
+					spin_unlock(&list->lock);
+					synchronize_rcu();
+					rcu_free_do_cleanup(rcu_head_p);
+					goto restart;
+				}
+				item_p = next_item_p;
+				list->dirty = TRUE;
+			} else {
+				tmp_count++;
+				item_p = item_p->next;
+			}
+		}
+		if (tmp_count != list->hashed[i].count) {
+			if (correct) {
+				rsbac_printk(KERN_WARNING "rsbac_list_check(): correcting count mismatch for list %s hash %u on device %02u:%02u - was %u, counted %lu!\n",
+					     list->name, i, RSBAC_MAJOR(list->device),
+		 			     RSBAC_MINOR(list->device),
+					     list->hashed[i].count, tmp_count);
+				list->hashed[i].count = tmp_count;
+				list->dirty = TRUE;
+			} else {
+				rsbac_printk(KERN_WARNING "rsbac_list_check(): count mismatch for list %s hash %u on device %02u:%02u - is %u, counted %lu!\n",
+					     list->name, i, RSBAC_MAJOR(list->device),
+					     RSBAC_MINOR(list->device),
+					     list->hashed[i].count, tmp_count);
+			}
+		}
+	}
+	rcu_head_p = get_rcu_free(list);
+	spin_unlock(&list->lock);
+	synchronize_rcu();
+	rcu_free_do_cleanup(rcu_head_p);
+	return 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_check);
+#endif
+int rsbac_list_lol_check(rsbac_list_handle_t handle, const int correct)
+{
+	struct rsbac_list_lol_reg_item_t *lol_list;
+	struct rsbac_list_lol_item_t *lol_item_p;
+	struct rsbac_list_lol_item_t *next_lol_item_p;
+	struct rsbac_list_item_t *lol_subitem_p;
+	struct rsbac_list_item_t *next_lol_subitem_p;
+	u_long tmp_count;
+	u_long tmp_subcount;
+	int i;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+	u_int remove_count;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	lol_list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(!lol_list || (lol_list->self != lol_list)))
+		return -RSBAC_EINVALIDLIST;
+
+	rsbac_pr_debug(lists, "checking list %s.\n", lol_list->name);
+
+restart:
+	remove_count = 0;
+	spin_lock(&lol_list->lock);
+	nr_hashes = 1 << lol_list->hash_bits;
+	for (i=0; i<nr_hashes; i++) {
+		tmp_count = 0;
+		lol_item_p = lol_list->hashed[i].head;
+		while (lol_item_p) {
+			if ((lol_item_p->max_age
+			     && (lol_item_p->max_age <= RSBAC_CURRENT_TIME)
+			    )
+			    || (lol_list->def_data
+				&& !lol_item_p->count
+				&& !memcmp(((char *) lol_item_p) +
+					   sizeof(*lol_item_p) +
+					   lol_list->info.desc_size,
+					   lol_list->def_data,
+					   lol_list->info.data_size)
+			    )
+			    || (!lol_list->info.data_size
+				&& (lol_list->flags & RSBAC_LIST_DEF_DATA)
+				&& !lol_item_p->count)
+			    ) {
+				next_lol_item_p = lol_item_p->next;
+				do_remove_lol_item(lol_list, lol_item_p, i);
+				remove_count++;
+				if (remove_count > rsbac_list_rcu_rate) {
+					rcu_head_lol_p = get_rcu_free_lol(lol_list);
+					spin_unlock(&lol_list->lock);
+					synchronize_rcu();
+					rcu_free_do_cleanup_lol(rcu_head_lol_p);
+					goto restart;
+				}
+				lol_item_p = next_lol_item_p;
+			} else {
+				tmp_count++;
+				tmp_subcount = 0;
+				lol_subitem_p = lol_item_p->head;
+				while (lol_subitem_p) {
+					if ((lol_subitem_p->max_age
+					     && (lol_subitem_p->max_age <=
+						 RSBAC_CURRENT_TIME)
+					    )
+					    || (lol_list->def_subdata
+						&& !memcmp(((char *) lol_subitem_p)
+							   +
+							   sizeof(*lol_subitem_p) +
+							   lol_list->info.
+							   subdesc_size,
+		 					   lol_list->def_subdata,
+							   lol_list->info.
+							   subdata_size)
+					    )
+					    ) {
+						next_lol_subitem_p =
+						    lol_subitem_p->next;
+						do_remove_lol_subitem(lol_item_p,
+								      lol_subitem_p);
+						rcu_free_lol_sub(lol_list, lol_subitem_p);
+						lol_subitem_p = next_lol_subitem_p;
+					} else {
+						tmp_subcount++;
+						lol_subitem_p =
+						    lol_subitem_p->next;
+					}
+				}
+				if (tmp_subcount != lol_item_p->count) {
+					if (correct) {
+						rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): correcting count mismatch for list of lists %s hash %u sublist on %02u:%02u - was %lu, counted %lu!\n",
+							     lol_list->name, i,
+							     RSBAC_MAJOR(lol_list->
+									 device),
+							     RSBAC_MINOR(lol_list->
+									 device),
+							     lol_item_p->count,
+							     tmp_subcount);
+						lol_item_p->count = tmp_subcount;
+					} else {
+						rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): count mismatch for list of lists %s hash %u sublist on %02u:%02u - is %lu, counted %lu!\n",
+							     lol_list->name, i,
+							     RSBAC_MAJOR(lol_list->
+									 device),
+							     RSBAC_MINOR(lol_list->
+									 device),
+							     lol_item_p->count,
+							     tmp_subcount);
+					}
+				}
+	 			lol_item_p = lol_item_p->next;
+			}
+		}
+		if (tmp_count != lol_list->hashed[i].count) {
+			if (correct) {
+				rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): correcting count mismatch for list of lists %s hash %u on %02u:%02u - was %u, counted %lu!\n",
+					     lol_list->name, i,
+					     RSBAC_MAJOR(lol_list->device),
+					     RSBAC_MINOR(lol_list->device),
+					     lol_list->hashed[i].count, tmp_count);
+				lol_list->hashed[i].count = tmp_count;
+			} else {
+				rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): count mismatch for list of lists %s hash %u on %02u:%02u - is %u, counted %lu!\n",
+					     lol_list->name, i,
+					     RSBAC_MAJOR(lol_list->device),
+					     RSBAC_MINOR(lol_list->device),
+					     lol_list->hashed[i].count, tmp_count);
+			}
+		}
+	}
+	rcu_head_lol_p = get_rcu_free_lol(lol_list);
+	spin_unlock(&lol_list->lock);
+	synchronize_rcu();
+	rcu_free_do_cleanup_lol(rcu_head_lol_p);
+	return 0;
+}
+
+
+/********************/
+/* Registration     */
+/********************/
+
+/* get generic list registration version */
+inline rsbac_version_t rsbac_list_version(void)
+{
+	return RSBAC_LIST_VERSION;
+}
+
+#if defined(CONFIG_RSBAC_PROC)
+static int backup_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, backup_proc_show, NULL);
+}
+
+static const struct file_operations backup_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = backup_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int lol_backup_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, lol_backup_proc_show, NULL);
+}
+
+static const struct file_operations lol_backup_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = lol_backup_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+#endif
+
+/* register a new list */
+/*
+ * If list with same name exists in memory, error -RSBAC_EEXISTS is returned.
+ * If list with same name and key exists on device, it is restored depending on the flags.
+ * If list with same name, but different key exists, access is denied (error -EPERM).
+ *
+ * ds_version: for binary modules, must be RSBAC_LIST_VERSION. If version differs, return error.
+ * handle_p: for all list accesses, an opaque handle is put into *handle_p.
+ * key: positive, secret __u32 key, which must be the same as in on-disk version, if persistent
+ * list_version: positive __u32 version number for the list. If old on-disk version is
+   different, upconversion is tried (depending on flags and get_conv function)
+ * flags: see flag values
+ * desc_size: size of the descriptor (error is returned, if value is 0 or list exists and value differs)
+ * data_size: size of data (error is returned, if list exists and value differs). Can be 0 for sets.
+ * compare: for lookup and list optimization, can be NULL, then
+   memcmp(desc1, desc2, desc_size) is used
+ * def_data: default data value for flag RSBAC_LIST_DEF_DATA
+   (if NULL, flag is cleared)
+ * name: the on-disk name, must be distinct and max. 7 or 8.2 chars
+   (only used for statistics, if non-persistent)
+ * device: the device to read list from or to save list to - use 0 for root dev
+   (ignored, if non-persistent)
+ * hash_bits: Number of bits of hashes for this list, minimum is 1,
+   maximum is rsbac_list_max_hash_bits,
+   which is derived from CONFIG_RSBAC_LIST_MAX_HASH_BITS and must not be more than 31
+   Number of hashes is 2^hash_bits.
+   If > maximum, it will be reduced to maximum automatically.
+ * hash_function: Hash function(desc,hash_bits), must always return a value
+   from 0 to 2^hash_bits - 1.
+ * old_base_name: If not NULL and persistent list with name cannot be read,
+   try to read all old_base_name<n> with n from 0 to 31.
+ */
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_register_hashed);
+#endif
+int rsbac_list_register_hashed(rsbac_version_t ds_version,
+			rsbac_list_handle_t * handle_p,
+			struct rsbac_list_info_t *info_p,
+			u_int flags,
+			rsbac_list_compare_function_t * compare,
+			rsbac_list_get_conv_t * get_conv,
+			void *def_data, char *name, kdev_t device,
+			__u8 hash_bits,
+			rsbac_list_hash_function_t hash_function,
+			char * old_base_name)
+{
+	struct rsbac_list_reg_item_t *reg_item_p;
+	struct rsbac_list_reg_item_t *new_reg_item_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (unlikely(ds_version != RSBAC_LIST_VERSION)) {
+		if (name) {
+			rsbac_printk(KERN_WARNING "rsbac_list_register: wrong ds_version %u for list %s, expected %u!\n",
+				     ds_version, name, RSBAC_LIST_VERSION);
+		}
+		return -RSBAC_EINVALIDVERSION;
+	}
+	if (unlikely(!handle_p || !info_p))
+		return -RSBAC_EINVALIDPOINTER;
+	*handle_p = NULL;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	if (unlikely(!info_p->key || !info_p->version || !info_p->desc_size))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(info_p->max_age > RSBAC_LIST_MAX_AGE_LIMIT))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(info_p->desc_size + info_p->data_size >
+	    RSBAC_LIST_MAX_ITEM_SIZE))
+		return -RSBAC_EINVALIDVALUE;
+	if (hash_bits > rsbac_list_max_hash_bits)
+		hash_bits = rsbac_list_max_hash_bits;
+	if (!hash_function) {
+		hash_bits = 0;
+		flags &= ~RSBAC_LIST_AUTO_HASH_RESIZE;
+	}
+	if (name) {
+		struct rsbac_list_lol_reg_item_t *lol_reg_item_p;
+
+		srcu_idx = srcu_read_lock(&reg_list_srcu);
+		reg_item_p = lookup_reg_name(name, device);
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		if (reg_item_p) {
+			rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+			return -RSBAC_EEXISTS;
+		}
+		srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+		lol_reg_item_p = lookup_lol_reg_name(name, device);
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		if (lol_reg_item_p) {
+			rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+			return -RSBAC_EEXISTS;
+		}
+	} else if (flags & RSBAC_LIST_PERSIST) {
+		rsbac_printk(KERN_WARNING "rsbac_list_register: trial to register persistent list without name.\n");
+		return -RSBAC_EINVALIDVALUE;
+	}
+
+	if (flags & RSBAC_LIST_PERSIST) {
+		if (RSBAC_IS_AUTO_DEV(device))
+			device = rsbac_root_dev;
+		if (!RSBAC_MAJOR(device))
+			flags &= ~RSBAC_LIST_PERSIST;
+	}
+	rsbac_pr_debug(lists, "registering list %s for device %02u:%02u.\n",
+		       name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
+	new_reg_item_p =
+	    create_reg(info_p, flags, compare, get_conv, def_data, name,
+		       device, hash_bits, hash_function, old_base_name);
+	if (unlikely(!new_reg_item_p)) {
+		return -RSBAC_ECOULDNOTADDITEM;
+	}
+	/* Restore from disk, but only for real device mounts */
+	if ((flags & RSBAC_LIST_PERSIST)
+	    && RSBAC_MAJOR(device)
+	    && !rsbac_list_noread
+	    ) {
+		rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u.\n",
+			       name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
+		err = read_list(new_reg_item_p);
+		/* not found is no error */
+		if (err == -RSBAC_ENOTFOUND)
+			err = 0;
+		else if (err) {
+			char tmp[RSBAC_MAXNAMELEN];
+
+			if (rsbac_list_recover) {
+				rsbac_printk(KERN_WARNING "restoring list %s from device %02u:%02u failed with error %s, rsbac_list_recover is set so registering anyway.\n",
+					name,
+					RSBAC_MAJOR(device),
+					RSBAC_MINOR(device),
+					get_error_name(tmp, err));
+				err = 0;
+			} else {
+				rsbac_printk(KERN_WARNING "restoring list %s from device %02u:%02u failed with error %s, unregistering list.\n",
+					name,
+					RSBAC_MAJOR(device),
+					RSBAC_MINOR(device),
+					get_error_name(tmp, err));
+				clear_reg(new_reg_item_p);
+				return err;
+			}
+		} else
+			rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u was successful.\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+	}
+
+	spin_lock(&reg_head.lock);
+	reg_item_p = add_reg(new_reg_item_p);
+	spin_unlock(&reg_head.lock);
+	if (unlikely(!reg_item_p)) {
+		rsbac_printk(KERN_WARNING "rsbac_list_register: inserting list %s failed!\n",
+			     name);
+		/* cleanup */
+		clear_reg(new_reg_item_p);
+		return -RSBAC_ECOULDNOTADDITEM;
+	}
+
+	/* finish */
+#if defined(CONFIG_RSBAC_PROC)
+	/* create proc entry, if requested */
+	if (flags & RSBAC_LIST_BACKUP) {
+		reg_item_p->proc_entry_p =
+		proc_create_data(reg_item_p->name, S_IFREG | S_IRUGO,
+				      proc_rsbac_backup_p, &backup_proc_fops,
+				      (void *) reg_item_p);
+	} else {
+		reg_item_p->proc_entry_p = NULL;
+	}
+#endif
+	*handle_p = reg_item_p;
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_register);
+#endif
+int rsbac_list_register(rsbac_version_t ds_version,
+			rsbac_list_handle_t * handle_p,
+			struct rsbac_list_info_t *info_p,
+			u_int flags,
+			rsbac_list_compare_function_t * compare,
+			rsbac_list_get_conv_t * get_conv,
+			void *def_data, char *name, kdev_t device)
+{
+	return rsbac_list_register_hashed(ds_version, handle_p, info_p, flags,
+				compare, get_conv, def_data, name, device,
+  				1, NULL, NULL);
+}
+
+/* register a new list of lists */
+/*
+ * If list with same name exists in memory, error -RSBAC_EEXISTS is returned.
+ * If list with same name and key exists on device, it is restored depending on the flags.
+ * If list with same name, but different key exists, access is denied (error -EPERM).
+ *
+ * ds_version: for binary modules, must be RSBAC_LIST_VERSION. If version differs, return error.
+ * handle_p: for all list accesses, an opaque handle is put into *handle_p.
+ * key: positive, secret __u32 key, which must be the same as in on-disk version, if persistent
+ * list_version: positive __u32 version number for the list. If old on-disk version is
+   different, upconversion is tried (depending on flags and get_conv function)
+ * flags: see flag values
+ * desc_size: size of the descriptor (error is returned, if value is 0 or list exists and value differs)
+ * subdesc_size: size of the sublist descriptor (error is returned, if value is 0 or list exists
+   and value differs)
+ * data_size: size of data (error is returned, if list exists and value differs). Can be 0 for sets.
+ * subdata_size: size of sublist data (error is returned, if list exists and value differs).
+   Can be 0 for sets.
+ * compare: for lookup and list optimization, can be NULL, then
+   memcmp(desc1, desc2, desc_size) is used
+ * subcompare: for item lookup and optimization of sublist, can be NULL, then
+   memcmp(desc1, desc2, desc_size) is used
+ * def_data: default data value for flag RSBAC_LIST_DEF_DATA
+   (if NULL, flag is cleared)
+ * def_subdata: default subdata value for flag RSBAC_LIST_DEF_SUBDATA
+   (if NULL, flag is cleared)
+ * name: the on-disk name, must be distinct and max. 7 or 8.2 chars
+   (only used for info, if non-persistent)
+ * device: the device to read list from or to save list to - use 0 for root dev
+   (ignored, if non-persistent)
+ * hash_bits: Number of bits of hashes for this list, minimum is 1,
+   maximum is rsbac_list_max_hash_bits,
+   which is derived from CONFIG_RSBAC_LIST_MAX_HASH_BITS and must not be more than 31
+   Number of hashes is 2^hash_bits.
+   If > maximum, it will be reduced to maximum automatically.
+ * hash_function: Hash function(desc,hash_bits), must always return a value
+   from 0 to 2^hash_bits - 1.
+ * old_base_name: If not NULL and persistent list with name cannot be read,
+   try to read all old_base_name<n> with n from 0 to 31.
+ */
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_register_hashed);
+#endif
+int rsbac_list_lol_register_hashed(rsbac_version_t ds_version,
+			rsbac_list_handle_t * handle_p,
+			struct rsbac_list_lol_info_t *info_p,
+			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,
+			void *def_data,
+			void *def_subdata, char *name, kdev_t device,
+			__u8 hash_bits,
+			rsbac_list_hash_function_t hash_function,
+			char * old_base_name)
+{
+	struct rsbac_list_lol_reg_item_t *reg_item_p;
+	struct rsbac_list_lol_reg_item_t *new_reg_item_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (unlikely(ds_version != RSBAC_LIST_VERSION))
+		return -RSBAC_EINVALIDVERSION;
+	if (unlikely(!handle_p))
+		return -RSBAC_EINVALIDPOINTER;
+	*handle_p = NULL;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	if (unlikely(!info_p->key || !info_p->version || !info_p->desc_size))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(info_p->max_age > RSBAC_LIST_MAX_AGE_LIMIT))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(info_p->desc_size + info_p->data_size >
+	    RSBAC_LIST_MAX_ITEM_SIZE))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(info_p->subdesc_size + info_p->subdata_size >
+	    RSBAC_LIST_MAX_ITEM_SIZE))
+		return -RSBAC_EINVALIDVALUE;
+	if (hash_bits > rsbac_list_max_hash_bits)
+		hash_bits = rsbac_list_max_hash_bits;
+	if (!hash_function) {
+		hash_bits = 0;
+		flags &= ~RSBAC_LIST_AUTO_HASH_RESIZE;
+	}
+	if (name) {
+		struct rsbac_list_reg_item_t *std_reg_item_p;
+
+		srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+		reg_item_p = lookup_lol_reg_name(name, device);
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		if (reg_item_p) {
+			rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+			return -RSBAC_EEXISTS;
+		}
+		srcu_idx = srcu_read_lock(&reg_list_srcu);
+		std_reg_item_p = lookup_reg_name(name, device);
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		if (std_reg_item_p) {
+			rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+			return -RSBAC_EEXISTS;
+		}
+	} else if (flags & RSBAC_LIST_PERSIST) {
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_register: trial to register persistent list of lists without name.\n");
+		return -RSBAC_EINVALIDVALUE;
+	}
+
+	if (flags & RSBAC_LIST_PERSIST) {
+		if (RSBAC_IS_AUTO_DEV(device))
+			device = rsbac_root_dev;
+		if (!RSBAC_MAJOR(device))
+			flags &= ~RSBAC_LIST_PERSIST;
+	}
+	rsbac_pr_debug(lists, "registering list of lists %s.\n",
+		       name);
+	new_reg_item_p = create_lol_reg(info_p, flags, compare, subcompare,
+					get_conv, get_subconv,
+					def_data, def_subdata,
+					name, device,
+					hash_bits, hash_function,
+					old_base_name);
+	if (unlikely(!new_reg_item_p)) {
+		return -RSBAC_ECOULDNOTADDITEM;
+	}
+	/* Restore from disk, but only for real device mounts */
+	if ((flags & RSBAC_LIST_PERSIST)
+	    && RSBAC_MAJOR(device)
+	    && !rsbac_list_noread
+	    ) {
+		rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u.\n",
+			       name, RSBAC_MAJOR(device),
+			       RSBAC_MINOR(device));
+		err = read_lol_list(new_reg_item_p);
+		/* not found is no error */
+		if (err == -RSBAC_ENOTFOUND)
+			err = 0;
+		else if (err) {
+#ifdef CONFIG_RSBAC_DEBUG
+			char tmp[RSBAC_MAXNAMELEN];
+#endif
+
+			rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u failed with error %s, unregistering list.\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device),
+				       get_error_name(tmp, err));
+			clear_lol_reg(new_reg_item_p);
+			return err;
+		} else
+			rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u was successful.\n",
+				       name, RSBAC_MAJOR(device),
+				       RSBAC_MINOR(device));
+	}
+
+	spin_lock(&lol_reg_head.lock);
+	reg_item_p = add_lol_reg(new_reg_item_p);
+	spin_unlock(&lol_reg_head.lock);
+	if (unlikely(!reg_item_p)) {
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_register: inserting list %s failed!\n",
+			     name);
+		/* cleanup */
+		clear_lol_reg(new_reg_item_p);
+		return -RSBAC_ECOULDNOTADDITEM;
+	}
+
+	/* finish */
+#if defined(CONFIG_RSBAC_PROC)
+	/* create proc entry, if requested */
+	if (flags & RSBAC_LIST_BACKUP) {
+		reg_item_p->proc_entry_p =
+		    proc_create_data(reg_item_p->name, S_IFREG | S_IRUGO,
+				      proc_rsbac_backup_p, &lol_backup_proc_fops,
+				      (void *) reg_item_p);
+	} else {
+		reg_item_p->proc_entry_p = NULL;
+	}
+#endif
+	*handle_p = reg_item_p;
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_register);
+#endif
+int rsbac_list_lol_register(rsbac_version_t ds_version,
+			    rsbac_list_handle_t * handle_p,
+			    struct rsbac_list_lol_info_t *info_p,
+			    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,
+			    void *def_data,
+			    void *def_subdata, char *name, kdev_t device) {
+	return rsbac_list_lol_register_hashed (ds_version, handle_p, info_p,
+				flags, compare, subcompare, get_conv,
+				get_subconv, def_data, def_subdata,
+				name, device,
+  				1, NULL, NULL);
+}
+
+/* destroy list */
+/* list is destroyed, disk file is deleted */
+/* list must have been opened with register */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_destroy);
+#endif
+int rsbac_list_destroy(rsbac_list_handle_t * handle_p,
+		       rsbac_list_key_t key)
+{
+	struct rsbac_list_reg_item_t *reg_item_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (unlikely(!handle_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!*handle_p))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	reg_item_p =
+	    lookup_reg((struct rsbac_list_reg_item_t *) *handle_p);
+	if (!reg_item_p) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_destroy: destroying list failed due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_destroy: destroying list %s denied due to invalid key!\n",
+			     reg_item_p->name);
+		return -EPERM;
+	}
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	rsbac_pr_debug(lists, "destroying list %s.\n",
+		       reg_item_p->name);
+#if defined(CONFIG_RSBAC_PROC)
+	/* delete proc entry, if it exists */
+	if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
+	    && reg_item_p->proc_entry_p) {
+		remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
+		reg_item_p->proc_entry_p = NULL;
+	}
+#endif
+
+#if 0
+	if (reg_item_p->flags & RSBAC_LIST_PERSIST)
+		err = unlink_list(reg_item_p);
+#endif
+
+	spin_lock(&reg_head.lock);
+	remove_reg(reg_item_p);
+	*handle_p = NULL;
+	spin_unlock(&reg_head.lock);
+	synchronize_srcu(&reg_list_srcu);
+	/* now we can remove the item from memory */
+	clear_reg(reg_item_p);
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_destroy);
+#endif
+int rsbac_list_lol_destroy(rsbac_list_handle_t * handle_p,
+			   rsbac_list_key_t key)
+{
+	struct rsbac_list_lol_reg_item_t *reg_item_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (unlikely(!handle_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!*handle_p))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	reg_item_p =
+	    lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) *handle_p);
+	if (!reg_item_p) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_destroy: destroying list failed due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_destroy: destroying list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+	rsbac_pr_debug(lists, "destroying list %s.\n",
+		       reg_item_p->name);
+#if defined(CONFIG_RSBAC_PROC)
+	/* delete proc entry, if it exists */
+	if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
+	    && reg_item_p->proc_entry_p) {
+		remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
+		reg_item_p->proc_entry_p = NULL;
+	}
+#endif
+#if 0
+	if (reg_item_p->flags & RSBAC_LIST_PERSIST)
+		err = unlink_lol_list(reg_item_p);
+#endif
+
+	spin_lock(&lol_reg_head.lock);
+	remove_lol_reg(reg_item_p);
+	spin_unlock(&lol_reg_head.lock);
+	synchronize_srcu(&lol_reg_list_srcu);
+	/* now we can remove the item from memory */
+	clear_lol_reg(reg_item_p);
+	return err;
+}
+
+/* detach from list */
+/* list is saved and removed from memory. Call register for new access. */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_detach);
+#endif
+int rsbac_list_detach(rsbac_list_handle_t * handle_p, rsbac_list_key_t key)
+{
+	struct rsbac_list_reg_item_t *reg_item_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (unlikely(!handle_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!*handle_p))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	reg_item_p =
+	    lookup_reg((struct rsbac_list_reg_item_t *) *handle_p);
+	if (!reg_item_p) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_detach: detaching list failed due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_detach: detaching list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+#if defined(CONFIG_RSBAC_PROC)
+	/* delete proc entry, if it exists */
+	if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
+	    && reg_item_p->proc_entry_p) {
+		remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
+		reg_item_p->proc_entry_p = NULL;
+	}
+#endif
+#ifndef CONFIG_RSBAC_NO_WRITE
+	/* final write, if dirty etc. */
+	if ((reg_item_p->flags & RSBAC_LIST_PERSIST)
+	    && reg_item_p->dirty && !reg_item_p->no_write
+	    && !rsbac_debug_no_write) {
+	    	struct vfsmount *mnt_p;
+		struct rsbac_list_write_head_t write_head;
+		struct rsbac_list_write_item_t *write_item_p;
+
+		mnt_p = rsbac_get_vfsmount(reg_item_p->device);
+		if (mnt_p && rsbac_writable(mnt_p->mnt_sb)) {
+			reg_item_p->dirty = FALSE;
+			err = fill_buffer(reg_item_p, &write_item_p);
+			if (!err) {
+				write_head.head = write_item_p;
+				write_head.tail = write_item_p;
+				write_head.count = 1;
+				rsbac_list_write_buffers(write_head);
+			} else {
+				if (err != -RSBAC_ENOTWRITABLE) {
+					rsbac_printk(KERN_WARNING "rsbac_list_detach(): fill_buffer() for list %s returned error %i\n",
+						     reg_item_p->name, err);
+				}
+			}
+		}
+	}
+#endif
+	/* disable handle */
+	*handle_p = NULL;
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	/* too bad that the list might have been changed again - we do not care anymore */
+	spin_lock(&reg_head.lock);
+	remove_reg(reg_item_p);
+	spin_unlock(&reg_head.lock);
+	synchronize_srcu(&reg_list_srcu);
+	/* now we can remove the item from memory */
+	clear_reg(reg_item_p);
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_detach);
+#endif
+int rsbac_list_lol_detach(rsbac_list_handle_t * handle_p,
+			  rsbac_list_key_t key)
+{
+	struct rsbac_list_lol_reg_item_t *reg_item_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (unlikely(!handle_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!*handle_p))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	reg_item_p =
+	    lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) *handle_p);
+	if (!reg_item_p) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_detach: detaching list failed due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_detach: detaching list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+#if defined(CONFIG_RSBAC_PROC)
+	/* delete proc entry, if it exists */
+	if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
+	    && reg_item_p->proc_entry_p) {
+		remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
+		reg_item_p->proc_entry_p = NULL;
+	}
+#endif
+#ifndef CONFIG_RSBAC_NO_WRITE
+	/* final write, if dirty etc. */
+	if ((reg_item_p->flags & RSBAC_LIST_PERSIST)
+	    && reg_item_p->dirty && !reg_item_p->no_write
+	    && !rsbac_debug_no_write) {
+		struct rsbac_list_lol_write_head_t write_head;
+		struct rsbac_list_lol_write_item_t *write_item_p;
+	    	struct vfsmount *mnt_p;
+
+		mnt_p = rsbac_get_vfsmount(reg_item_p->device);
+		if (mnt_p && rsbac_writable(mnt_p->mnt_sb)) {
+			reg_item_p->dirty = FALSE;
+			err = fill_lol_buffer(reg_item_p, &write_item_p);
+			if (!err) {
+				write_head.head = write_item_p;
+				write_head.tail = write_item_p;
+				write_head.count = 1;
+				rsbac_list_write_lol_buffers(write_head);
+			} else {
+				if (err != -RSBAC_ENOTWRITABLE) {
+					rsbac_printk(KERN_WARNING "rsbac_list_lol_detach(): fill_lol_buffer() for list %s returned error %i\n",
+						     reg_item_p->name, err);
+				}
+			}
+		}
+	}
+#endif
+	/* disable handle */
+	*handle_p = NULL;
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+	/* too bad that the list might have been changed again - we do not care anymore */
+	spin_lock(&lol_reg_head.lock);
+	remove_lol_reg(reg_item_p);
+	spin_unlock(&lol_reg_head.lock);
+	synchronize_srcu(&lol_reg_list_srcu);
+	/* now we can remove the item from memory */
+	clear_lol_reg(reg_item_p);
+	return err;
+}
+
+/* set list's no_write flag */
+/* TRUE: do not write to disk, FALSE: writing allowed */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_no_write);
+#endif
+int rsbac_list_no_write(rsbac_list_handle_t handle, rsbac_list_key_t key,
+			rsbac_boolean_t no_write)
+{
+	struct rsbac_list_reg_item_t *reg_item_p;
+	int srcu_idx;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely((no_write != FALSE) && (no_write != TRUE)))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) handle);
+	if (!reg_item_p) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_no_write: setting no_write for list denied due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_no_write: setting no_write for list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+	reg_item_p->no_write = no_write;
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_no_write);
+#endif
+int rsbac_list_lol_no_write(rsbac_list_handle_t handle,
+			    rsbac_list_key_t key, rsbac_boolean_t no_write)
+{
+	struct rsbac_list_lol_reg_item_t *reg_item_p;
+	int srcu_idx;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely((no_write != FALSE) && (no_write != TRUE)))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	reg_item_p =
+	    lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) handle);
+	if (!reg_item_p) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_no_write: setting no_write for list denied due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_no_write: setting no_write for list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+	reg_item_p->no_write = no_write;
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+/* set list's max_items_per_hash */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_max_items);
+#endif
+int rsbac_list_max_items(rsbac_list_handle_t handle, rsbac_list_key_t key,
+			u_int max_items)
+{
+	struct rsbac_list_reg_item_t *reg_item_p;
+	int srcu_idx;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) handle);
+	if (!reg_item_p) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_max_items: setting max_items_per_hash for list denied due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_max_items: setting max_items_per_hash for list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+	if (!max_items)
+		max_items = RSBAC_LIST_MAX_NR_ITEMS;
+	reg_item_p->max_items_per_hash = rsbac_min(max_items, RSBAC_LIST_MAX_NR_ITEMS_LIMIT);
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+/* set list's max_items_per_hash and max_subitems*/
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_max_items);
+#endif
+int rsbac_list_lol_max_items(rsbac_list_handle_t handle, rsbac_list_key_t key,
+			u_int max_items, u_int max_subitems)
+{
+	struct rsbac_list_lol_reg_item_t *reg_item_p;
+	int srcu_idx;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	reg_item_p = lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) handle);
+	if (!reg_item_p) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_max_items: setting max_items_per_hash for list denied due to invalid handle!\n");
+		return -RSBAC_EINVALIDLIST;
+	}
+	if (reg_item_p->info.key != key) {
+		srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_list_lol_max_items: setting max_items_per_hash for list %s denied due to invalid key %u!\n",
+			     reg_item_p->name, key);
+		return -EPERM;
+	}
+	if (!max_items)
+		max_items = RSBAC_LIST_MAX_NR_ITEMS;
+	if (!max_subitems)
+		max_subitems = RSBAC_LIST_MAX_NR_SUBITEMS;
+	reg_item_p->max_items_per_hash = rsbac_min(max_items, RSBAC_LIST_MAX_NR_ITEMS_LIMIT);
+	reg_item_p->max_subitems = rsbac_min(max_subitems, RSBAC_LIST_MAX_NR_ITEMS_LIMIT);
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+
+/********************/
+/* Transactions     */
+/********************/
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+static int do_commit(rsbac_list_ta_number_t ta_number)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_lol_reg_item_t *lol_list;
+	int i;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+	int srcu_idx;
+	int srcu_idx2;
+	u_int nr_hashes;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	srcu_idx2 = srcu_read_lock(&lol_reg_list_srcu);
+	list = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while (list) {
+		spin_lock(&list->lock);
+		nr_hashes = 1 << list->hash_bits;
+		for (i=0; i<nr_hashes; i++) {
+			if (list->hashed[i].ta_copied == ta_number) {
+				remove_all_items(list, i);
+				rcu_assign_pointer(list->hashed[i].head, list->hashed[i].ta_head);
+				rcu_assign_pointer(list->hashed[i].tail, list->hashed[i].ta_tail);
+				rcu_assign_pointer(list->hashed[i].curr, list->hashed[i].ta_curr);
+				list->hashed[i].count = list->hashed[i].ta_count;
+				list->hashed[i].ta_copied = 0;
+				rcu_assign_pointer(list->hashed[i].ta_head, NULL);
+				rcu_assign_pointer(list->hashed[i].ta_tail, NULL);
+				rcu_assign_pointer(list->hashed[i].ta_curr, NULL);
+				list->hashed[i].ta_count = 0;
+				list->dirty = TRUE;
+			}
+		}
+		rcu_head_p = get_rcu_free(list);
+		spin_unlock(&list->lock);
+		do_call_rcu(rcu_head_p);
+		list = srcu_dereference(list->next, &reg_list_srcu);
+	}
+	lol_list = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while (lol_list) {
+		spin_lock(&lol_list->lock);
+		nr_hashes = 1 << lol_list->hash_bits;
+		for (i=0; i<nr_hashes; i++) {
+			if (lol_list->hashed[i].ta_copied == ta_number) {
+				remove_all_lol_items(lol_list, i);
+				rcu_assign_pointer(lol_list->hashed[i].head, lol_list->hashed[i].ta_head);
+				rcu_assign_pointer(lol_list->hashed[i].tail, lol_list->hashed[i].ta_tail);
+				rcu_assign_pointer(lol_list->hashed[i].curr, lol_list->hashed[i].ta_curr);
+				lol_list->hashed[i].count = lol_list->hashed[i].ta_count;
+				lol_list->hashed[i].ta_copied = 0;
+				rcu_assign_pointer(lol_list->hashed[i].ta_head, NULL);
+				rcu_assign_pointer(lol_list->hashed[i].ta_tail, NULL);
+				rcu_assign_pointer(lol_list->hashed[i].ta_curr, NULL);
+				lol_list->hashed[i].ta_count = 0;
+				lol_list->dirty = TRUE;
+			}
+		}
+		rcu_head_lol_p = get_rcu_free_lol(lol_list);
+		spin_unlock(&lol_list->lock);
+		do_call_rcu_lol(rcu_head_lol_p);
+		lol_list = srcu_dereference(lol_list->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx2);
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	return 0;
+}
+
+int rsbac_list_ta_commit(rsbac_list_ta_number_t ta_number, char *password)
+{
+	int err;
+	struct rsbac_list_ta_data_t ta_data;
+
+	rsbac_printk(KERN_INFO "rsbac_list_ta_commit(): starting commit of transaction %u\n",
+		     ta_number);
+	err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
+	if (err)
+		return err;
+	if ((RSBAC_UID_NUM(ta_data.commit_uid) != RSBAC_ALL_USERS)
+	    && (ta_data.commit_uid != (rsbac_get_vset(),__kuid_val(current_uid())))
+	    )
+		return -EPERM;
+
+	if (ta_data.password[0]) {
+		if (!password)
+			return -EPERM;
+		if (strncmp
+		    (ta_data.password, password,
+		     RSBAC_LIST_TA_MAX_PASSLEN))
+			return -EPERM;
+	}
+	rsbac_printk(KERN_INFO "rsbac_list_ta_commit(): transaction %u data verified\n",
+		     ta_number);
+	spin_lock(&ta_lock);
+	while (ta_committing) {
+		spin_unlock(&ta_lock);
+		schedule();
+		spin_lock(&ta_lock);
+	}
+	rsbac_list_remove(ta_handle, &ta_number);
+	ta_committing = TRUE;
+	spin_unlock(&ta_lock);
+
+	rsbac_printk(KERN_INFO "rsbac_list_ta_commit(): committing transaction %u now\n",
+		     ta_number);
+
+	err = do_commit(ta_number);
+	ta_committing = FALSE;
+#ifdef CONFIG_RSBAC_FD_CACHE
+	if (!err)
+		rsbac_fd_cache_invalidate_all();
+#endif
+	wake_up(&ta_wait);
+	rsbac_printk(KERN_INFO "rsbac_list_ta_commit(): committed transaction %u\n",
+		     ta_number);
+	return err;
+}
+
+static int do_forget(rsbac_list_ta_number_t ta_number)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_lol_reg_item_t *lol_list;
+	int i;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+	int srcu_idx;
+	int srcu_idx2;
+	u_int nr_hashes;
+
+	spin_lock(&ta_lock);
+	while (ta_committing) {
+		spin_unlock(&ta_lock);
+		schedule();
+		spin_lock(&ta_lock);
+	}
+	rsbac_list_remove(ta_handle, &ta_number);
+	ta_committing = TRUE;
+	spin_unlock(&ta_lock);
+
+	rsbac_printk(KERN_INFO "rsbac_list_ta_forget(): removing transaction %u\n",
+		     ta_number);
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	srcu_idx2 = srcu_read_lock(&lol_reg_list_srcu);
+	list = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while (list) {
+		spin_lock(&list->lock);
+		nr_hashes = 1 << list->hash_bits;
+		for (i=0; i<nr_hashes; i++) {
+			if (list->hashed[i].ta_copied == ta_number) {
+				ta_remove_all_items(list, i);
+				list->hashed[i].ta_copied = 0;
+			}
+		}
+		rcu_head_p = get_rcu_free(list);
+		spin_unlock(&list->lock);
+		do_call_rcu(rcu_head_p);
+		list = srcu_dereference(list->next, &reg_list_srcu);
+	}
+	lol_list = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while (lol_list) {
+		spin_lock(&lol_list->lock);
+		nr_hashes = 1 << lol_list->hash_bits;
+		for (i=0; i<nr_hashes; i++) {
+			if (lol_list->hashed[i].ta_copied == ta_number) {
+				ta_remove_all_lol_items(lol_list, i);
+				lol_list->hashed[i].ta_copied = 0;
+			}
+		}
+		rcu_head_lol_p = get_rcu_free_lol(lol_list);
+		spin_unlock(&lol_list->lock);
+		do_call_rcu_lol(rcu_head_lol_p);
+		lol_list = srcu_dereference(lol_list->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx2);
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+
+	ta_committing = FALSE;
+	wake_up(&ta_wait);
+
+	return 0;
+}
+
+int rsbac_list_ta_forget(rsbac_list_ta_number_t ta_number, char *password)
+{
+	int err;
+	struct rsbac_list_ta_data_t ta_data;
+
+	err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
+	if (err)
+		return err;
+	if ((RSBAC_UID_NUM(ta_data.commit_uid) != RSBAC_ALL_USERS)
+	    && (ta_data.commit_uid != (rsbac_get_vset(),__kuid_val(current_uid())))
+	    )
+		return -EPERM;
+	if (ta_data.password[0]) {
+		if (!password)
+			return -EPERM;
+		if (strncmp
+		    (ta_data.password, password,
+		     RSBAC_LIST_TA_MAX_PASSLEN))
+			return -EPERM;
+	}
+	return do_forget(ta_number);
+}
+
+int rsbac_list_ta_begin(rsbac_time_t ttl,
+			rsbac_list_ta_number_t * ta_number_p,
+			rsbac_uid_t commit_uid,
+			char * name, char *password)
+{
+	int err;
+	rsbac_list_ta_number_t ta;
+	struct rsbac_list_ta_data_t ta_data;
+
+	if (unlikely(!ta_number_p))
+		return -RSBAC_EINVALIDPOINTER;
+
+	while(ta_committing)
+		schedule();
+	if (*ta_number_p) {
+	 	if (rsbac_list_exist(ta_handle, ta_number_p))
+			return -RSBAC_EEXISTS;
+		ta = *ta_number_p;
+	} else {
+#ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
+		get_random_bytes(&ta, sizeof(ta));
+#else
+		ta = ta_next++;
+#endif
+		while (!ta || rsbac_list_exist(ta_handle, &ta)
+#ifdef CONFIG_RSBAC_RC_LEARN_TA
+			|| (ta == CONFIG_RSBAC_RC_LEARN_TA)
+#endif
+#ifdef CONFIG_RSBAC_AUTH_LEARN_TA
+			|| (ta == CONFIG_RSBAC_AUTH_LEARN_TA)
+#endif
+#ifdef CONFIG_RSBAC_ACL_LEARN_TA
+			|| (ta == CONFIG_RSBAC_ACL_LEARN_TA)
+#endif
+#ifdef CONFIG_RSBAC_CAP_LEARN_TA
+			|| (ta == CONFIG_RSBAC_CAP_LEARN_TA)
+#endif
+			) {
+#ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
+			get_random_bytes(&ta, sizeof(ta));
+#else
+			ta = ta_next++;
+#endif
+		}
+	}
+	if (!ttl || (ttl > CONFIG_RSBAC_LIST_TRANS_MAX_TTL))
+		ttl = CONFIG_RSBAC_LIST_TRANS_MAX_TTL;
+
+	rsbac_printk(KERN_INFO "rsbac_list_ta_begin(): starting transaction %u with ttl of %us\n",
+		     ta, ttl);
+
+	ta_data.start = RSBAC_CURRENT_TIME;
+	ta_data.timeout = ta_data.start + ttl;
+	ta_data.commit_uid = commit_uid;
+	if (name) {
+		strncpy(ta_data.name, name,
+			RSBAC_LIST_TA_MAX_NAMELEN - 1);
+		ta_data.name[RSBAC_LIST_TA_MAX_NAMELEN - 1] = 0;
+	} else
+		ta_data.name[0] = 0;
+	if (password) {
+		strncpy(ta_data.password, password,
+			RSBAC_LIST_TA_MAX_PASSLEN - 1);
+		ta_data.password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
+	} else
+		ta_data.password[0] = 0;
+	err = rsbac_list_add(ta_handle, &ta, &ta_data);
+	if (!err)
+		*ta_number_p = ta;
+	return err;
+}
+
+int rsbac_list_ta_refresh(rsbac_time_t ttl,
+			  rsbac_list_ta_number_t ta_number, char *password)
+{
+	struct rsbac_list_ta_data_t ta_data;
+	int err;
+
+	if (!rsbac_list_exist(ta_handle, &ta_number)) {
+		return -RSBAC_ENOTFOUND;
+	}
+	if (!ttl || (ttl > CONFIG_RSBAC_LIST_TRANS_MAX_TTL))
+		ttl = CONFIG_RSBAC_LIST_TRANS_MAX_TTL;
+
+	rsbac_printk(KERN_INFO "rsbac_list_ta_refresh(): refreshing transaction %u for %us\n",
+		     ta_number, ttl);
+
+	err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
+	if (err)
+		return err;
+	if ((RSBAC_UID_NUM(ta_data.commit_uid) != RSBAC_ALL_USERS)
+	    && (ta_data.commit_uid != (rsbac_get_vset(),__kuid_val(current_uid())))
+	    )
+		return -EPERM;
+	if (ta_data.password[0]) {
+		if (!password)
+			return -EPERM;
+		if (strncmp
+		    (ta_data.password, password,
+		     RSBAC_LIST_TA_MAX_PASSLEN))
+			return -EPERM;
+	}
+	ta_data.timeout = RSBAC_CURRENT_TIME + ttl;
+	return rsbac_list_add(ta_handle, &ta_number, &ta_data);
+}
+
+int rsbac_list_ta_exist(rsbac_list_ta_number_t ta_number)
+{
+	if (!ta_number)
+		return TRUE;
+	else
+		return rsbac_list_exist(ta_handle, &ta_number);
+}
+#endif
+
+
+/********************/
+/* List Access      */
+/********************/
+
+/* add item */
+/* if item for desc exists, the data is updated */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_add_ttl);
+#endif
+int rsbac_ta_list_add_ttl(rsbac_list_ta_number_t ta_number,
+			  rsbac_list_handle_t handle,
+			  rsbac_time_t ttl, void *desc, void *data)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(!list || (list->self != list)))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(list->info.data_size && !data)) {
+		return -RSBAC_EINVALIDVALUE;
+	}
+
+/*
+	rsbac_pr_debug(lists, "adding to list %s.\n", list->name);
+*/
+	if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
+		if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
+			ttl = RSBAC_LIST_MAX_AGE_LIMIT;
+		ttl += RSBAC_CURRENT_TIME;
+	}
+	spin_lock(&list->lock);
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (!ta_number)
+#endif
+	{
+		item_p = lookup_item_locked(list, desc);
+		if (item_p) {	/* exists -> update data, if any */
+			if (ttl != RSBAC_LIST_TTL_KEEP)
+				item_p->max_age = ttl;
+			if (data && list->info.data_size) {
+				if (list->def_data
+				    && !item_p->max_age
+				    && !memcmp(list->def_data, data,
+					       list->info.data_size)
+				    )
+					do_remove_item(list, item_p, hash);
+				else
+					memcpy(((char *) item_p) +
+					       sizeof(*item_p) +
+					       list->info.desc_size, data,
+					       list->info.data_size);
+			}
+		} else {
+			if (ttl == RSBAC_LIST_TTL_KEEP)
+				ttl = 0;
+			if (!list->def_data
+			    || memcmp(list->def_data, data,
+				      list->info.data_size)
+			    )
+				add_item(list, ttl, desc, data);
+		}
+		touch(list);
+		list->dirty = TRUE;
+	}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied || ta_number) {
+		if (!list->hashed[hash].ta_copied)
+			ta_copy(ta_number, list, hash);
+		else if (ta_number) {
+			if (list->hashed[hash].ta_copied != ta_number) {
+				spin_unlock(&list->lock);
+				return -RSBAC_EBUSY;
+			}
+		} else
+			ta_number = list->hashed[hash].ta_copied;
+		item_p = ta_lookup_item_locked(ta_number, list, desc);
+		if (item_p) {	/* exists -> update data, if any */
+			if (ttl != RSBAC_LIST_TTL_KEEP)
+				item_p->max_age = ttl;
+			if (data && list->info.data_size) {
+				if (list->def_data
+				    && !item_p->max_age
+				    && !memcmp(list->def_data, data,
+					       list->info.data_size)
+				    )
+					ta_do_remove_item(list, item_p, hash);
+				else
+					memcpy(((char *) item_p) +
+					       sizeof(*item_p) +
+					       list->info.desc_size, data,
+					       list->info.data_size);
+			}
+		} else {
+			if (ttl == RSBAC_LIST_TTL_KEEP)
+				ttl = 0;
+			if (!list->def_data
+			    || memcmp(list->def_data, data,
+				      list->info.data_size)
+			    )
+				ta_add_item(ta_number, list, ttl, desc,
+					    data);
+		}
+	}
+#endif
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->write_count++;
+#endif
+	rcu_head_p = get_rcu_free(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu(rcu_head_p);
+	return 0;
+}
+
+/* add list of lists sublist item */
+/* if item for desc exists, the data is updated */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subadd_ttl);
+#endif
+int rsbac_ta_list_lol_subadd_ttl(rsbac_list_ta_number_t ta_number,
+				 rsbac_list_handle_t handle,
+				 rsbac_time_t ttl,
+				 void *desc, void *subdesc, void *subdata)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	int err = 0;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !subdesc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(list->info.subdata_size && !subdata)) {
+		return -RSBAC_EINVALIDVALUE;
+	}
+
+/*
+	rsbac_pr_debug(lists, "adding to list %s.\n", list->name);
+*/
+	spin_lock(&list->lock);
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (!ta_number)
+#endif
+	{
+		sublist = lookup_lol_item_locked(list, desc);
+		if (!sublist && (list->flags & RSBAC_LIST_DEF_DATA))
+			sublist = add_lol_item(list, 0, desc, list->def_data);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				remove_lol_item(list, desc);
+				err = -RSBAC_EINVALIDTARGET;
+			} else {
+				/* exists -> lookup subitem */
+				if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
+					if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
+						ttl = RSBAC_LIST_MAX_AGE_LIMIT;
+					ttl += RSBAC_CURRENT_TIME;
+				}
+				item_p =
+				    lookup_lol_subitem_locked(list, sublist,
+						       subdesc);
+				if (item_p) {	/* exists -> update data, if any */
+					if (ttl != RSBAC_LIST_TTL_KEEP)
+						item_p->max_age = ttl;
+					if (subdata
+					    && list->info.subdata_size) {
+						if (list->def_subdata
+						    && !item_p->max_age
+						    && !memcmp(list->
+							       def_subdata,
+							       subdata,
+							       list->info.
+							       subdata_size)
+						    ) {
+							do_remove_lol_subitem
+							    (sublist,
+							     item_p);
+							rcu_free_lol_sub(list, item_p);
+						} else
+							memcpy(((char *)
+								item_p) +
+							       sizeof
+							       (*item_p) +
+							       list->info.
+							       subdesc_size,
+							       subdata,
+							       list->info.
+							       subdata_size);
+					}
+				} else {
+					if (ttl == RSBAC_LIST_TTL_KEEP)
+						ttl = 0;
+					if (!list->def_subdata
+					    || memcmp(list->def_subdata,
+						      subdata,
+						      list->info.
+						      subdata_size)
+					    ) {
+						if (!add_lol_subitem(list,
+								sublist,
+								ttl,
+								subdesc,
+								subdata))
+							err = -RSBAC_ECOULDNOTADDITEM;
+					}
+				}
+				lol_touch(list);
+				list->dirty = TRUE;
+			}
+		} else {
+			err = -RSBAC_EINVALIDTARGET;
+			goto out_unlock;
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied || ta_number) {
+		if (!list->hashed[hash].ta_copied) {
+			if ((err = ta_lol_copy(ta_number, list, hash)))
+				goto out_unlock;
+		} else if (ta_number) {
+			if (list->hashed[hash].ta_copied != ta_number) {
+				err = -RSBAC_EBUSY;
+				goto out_unlock;
+			}
+		} else
+			ta_number = list->hashed[hash].ta_copied;
+		sublist = ta_lookup_lol_item_locked(ta_number, list, desc);
+		if (!sublist && (list->flags & RSBAC_LIST_DEF_DATA)
+		    )
+			sublist =
+			    ta_add_lol_item(ta_number, list, 0, desc,
+					    list->def_data);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				ta_remove_lol_item(ta_number, list, desc);
+				err = -RSBAC_EINVALIDTARGET;
+			} else {
+				/* exists -> lookup subitem */
+				if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
+					if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
+						ttl =
+						    RSBAC_LIST_MAX_AGE_LIMIT;
+					ttl += RSBAC_CURRENT_TIME;
+				}
+				item_p =
+				    lookup_lol_subitem_locked(list, sublist,
+						       subdesc);
+				if (item_p) {	/* exists -> update data, if any */
+					if (ttl != RSBAC_LIST_TTL_KEEP)
+						item_p->max_age = ttl;
+					if (subdata
+					    && list->info.subdata_size) {
+						if (list->def_subdata
+						    && !item_p->max_age
+						    && !memcmp(list->
+							       def_subdata,
+							       subdata,
+							       list->info.
+							       subdata_size)
+						    ) {
+							do_remove_lol_subitem
+							    (sublist,
+							     item_p);
+							rcu_free_lol_sub(list, item_p);
+						} else
+							memcpy(((char *)
+								item_p) +
+							       sizeof
+							       (*item_p) +
+							       list->info.
+							       subdesc_size,
+							       subdata,
+							       list->info.
+							       subdata_size);
+					}
+				} else {
+					if (ttl == RSBAC_LIST_TTL_KEEP)
+						ttl = 0;
+					if (!list->def_subdata
+					    || memcmp(list->def_subdata,
+						      subdata,
+						      list->info.
+						      subdata_size)
+					    )
+						add_lol_subitem(list,
+								sublist,
+								ttl,
+								subdesc,
+								subdata);
+				}
+			}
+		} else {
+			err = -RSBAC_EINVALIDTARGET;
+		}
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->write_count++;
+#endif
+
+out_unlock:
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return err;
+}
+
+/* add list of lists item */
+/* if item for desc exists, the data is updated */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_add_ttl);
+#endif
+int rsbac_ta_list_lol_add_ttl(rsbac_list_ta_number_t ta_number,
+			      rsbac_list_handle_t handle,
+			      rsbac_time_t ttl, void *desc, void *data)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
+		if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
+			ttl = RSBAC_LIST_MAX_AGE_LIMIT;
+		ttl += RSBAC_CURRENT_TIME;
+	}
+
+	if (list->info.data_size && !data) {
+		return -RSBAC_EINVALIDVALUE;
+	}
+
+/*
+	rsbac_pr_debug(lists, "adding to list %s.\n", list->name);
+*/
+	spin_lock(&list->lock);
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (!ta_number)
+#endif
+	{
+		item_p = lookup_lol_item_locked(list, desc);
+		if (item_p) {	/* exists -> update data, if any */
+			if (ttl != RSBAC_LIST_TTL_KEEP)
+				item_p->max_age = ttl;
+			if (data && list->info.data_size) {
+				if (list->def_data
+				    && !item_p->max_age
+				    && !memcmp(list->def_data, data,
+					       list->info.data_size)
+				    && !item_p->count)
+					do_remove_lol_item(list, item_p, hash);
+				else
+					memcpy(((char *) item_p) +
+					       sizeof(*item_p) +
+					       list->info.desc_size, data,
+					       list->info.data_size);
+			}
+		} else {
+			if (ttl == RSBAC_LIST_TTL_KEEP)
+				ttl = 0;
+			if (!list->def_data
+			    || memcmp(list->def_data, data,
+				      list->info.data_size)
+			    )
+				add_lol_item(list, ttl, desc, data);
+		}
+		lol_touch(list);
+		list->dirty = TRUE;
+	}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied || ta_number) {
+		if (!list->hashed[hash].ta_copied)
+			ta_lol_copy(ta_number, list, hash);
+		else if (ta_number) {
+			if (list->hashed[hash].ta_copied != ta_number) {
+				rcu_head_lol_p = get_rcu_free_lol(list);
+				spin_unlock(&list->lock);
+				do_sync_rcu_lol(rcu_head_lol_p);
+				return -RSBAC_EBUSY;
+			}
+		} else
+			ta_number = list->hashed[hash].ta_copied;
+		item_p = ta_lookup_lol_item_locked(ta_number, list, desc);
+		if (item_p) {	/* exists -> update data, if any */
+			if (ttl != RSBAC_LIST_TTL_KEEP)
+				item_p->max_age = ttl;
+			if (data && list->info.data_size) {
+				if (list->def_data
+				    && !item_p->max_age
+				    && !memcmp(list->def_data, data,
+					       list->info.data_size)
+				    && !item_p->count)
+					ta_do_remove_lol_item(list,
+							      item_p,
+							      hash);
+				else
+					memcpy(((char *) item_p) +
+					       sizeof(*item_p) +
+					       list->info.desc_size, data,
+					       list->info.data_size);
+			}
+		} else {
+			if (ttl == RSBAC_LIST_TTL_KEEP)
+				ttl = 0;
+			if (!list->def_data
+			    || memcmp(list->def_data, data,
+				      list->info.data_size)
+			    )
+				ta_add_lol_item(ta_number, list, ttl, desc,
+						data);
+		}
+	}
+#endif
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->write_count++;
+#endif
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return 0;
+}
+
+/* remove item */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_remove);
+#endif
+int rsbac_ta_list_remove(rsbac_list_ta_number_t ta_number,
+			 rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	u_int hash = 0;
+#endif
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(!list || (list->self != list)))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing from list %s.\n", list->name);
+*/
+	spin_lock(&list->lock);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	if (list->hashed[hash].ta_copied) {
+		if (ta_number) {
+			if (ta_lookup_item_locked(list->hashed[hash].ta_copied, list, desc)) {
+				if (list->hashed[hash].ta_copied != ta_number) {
+					spin_unlock(&list->lock);
+					return -RSBAC_EBUSY;
+				} else
+					ta_remove_item(ta_number, list,
+						       desc);
+			}
+		} else
+			ta_remove_item(list->hashed[hash].ta_copied, list, desc);
+	} else {
+		if (ta_number && lookup_item_locked(list, desc)) {
+			ta_copy(ta_number, list, hash);
+			ta_remove_item(ta_number, list, desc);
+		}
+	}
+	if (!ta_number)
+#endif
+	{
+		if (lookup_item_locked(list, desc)) {	/* exists -> remove */
+			remove_item(list, desc);
+			touch(list);
+			list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+			list->write_count++;
+#endif
+		}
+	}
+	rcu_head_p = get_rcu_free(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu(rcu_head_p);
+	return 0;
+}
+
+/* remove all items */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_remove_all);
+#endif
+int rsbac_ta_list_remove_all(rsbac_list_ta_number_t ta_number,
+			     rsbac_list_handle_t handle)
+{
+	struct rsbac_list_reg_item_t *list;
+	int i;
+	u_int nr_hashes;
+	struct rsbac_list_rcu_free_head_t ** rcu_head_pp = NULL;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	struct rsbac_list_rcu_free_head_t ** ta_rcu_head_pp = NULL;
+#endif
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing all items from list %s.\n", list->name);
+*/
+
+restart:
+	nr_hashes = 1 << list->hash_bits;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (!ta_number)
+#endif
+	{
+		rcu_head_pp = rsbac_kmalloc_clear_unlocked(nr_hashes * sizeof(*rcu_head_pp));
+		if (unlikely(!rcu_head_pp))
+			return -RSBAC_ENOMEM;
+	}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	ta_rcu_head_pp = rsbac_kmalloc_clear_unlocked(nr_hashes * sizeof(*ta_rcu_head_pp));
+	if (unlikely(!ta_rcu_head_pp)) {
+		if (!ta_number)
+			rsbac_kfree(rcu_head_pp);
+		return -RSBAC_ENOMEM;
+	}
+#endif
+
+	spin_lock(&list->lock);
+	if (unlikely(nr_hashes != 1 << list->hash_bits)) {
+		spin_unlock(&list->lock);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (!ta_number)
+#endif
+			rsbac_kfree(rcu_head_pp);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		rsbac_kfree(ta_rcu_head_pp);
+#endif
+		goto restart;
+	}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number)
+		for (i=0; i<nr_hashes; i++)
+			if (list->hashed[i].ta_copied && (list->hashed[i].ta_copied != ta_number)) {
+				spin_unlock(&list->lock);
+				rsbac_kfree(ta_rcu_head_pp);
+				return -RSBAC_EBUSY;
+			}
+
+	for (i=0; i<nr_hashes; i++) {
+		if (list->hashed[i].ta_copied) {
+			ta_remove_all_items(list, i);
+			if (ta_number && !list->hashed[i].head)
+					list->hashed[i].ta_copied = 0;
+		} else {
+			if (ta_number && list->hashed[i].head) {
+				list->hashed[i].ta_head = NULL;
+				list->hashed[i].ta_tail = NULL;
+				list->hashed[i].ta_curr = NULL;
+				list->hashed[i].ta_count = 0;
+				list->hashed[i].ta_copied = ta_number;
+			}
+		}
+		ta_rcu_head_pp[i] = get_rcu_free(list);
+	}
+		
+	if (!ta_number)
+#endif
+		for (i=0; i<nr_hashes; i++) {
+			if (list->hashed[i].head) {
+				remove_all_items(list, i);
+				touch(list);
+				list->dirty = TRUE;
+				rcu_head_pp[i] = get_rcu_free(list);
+			}
+		}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->write_count++;
+#endif
+	spin_unlock(&list->lock);
+	synchronize_rcu();
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	for (i=0; i<nr_hashes; i++)
+		rcu_free_do_cleanup(ta_rcu_head_pp[i]);
+	rsbac_kfree(ta_rcu_head_pp);
+	if (!ta_number)
+#endif
+	{
+		for (i=0; i<nr_hashes; i++)
+			rcu_free_do_cleanup(rcu_head_pp[i]);
+		rsbac_kfree(rcu_head_pp);
+	}
+	return 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_count);
+#endif
+int rsbac_ta_list_lol_subremove_count(rsbac_list_ta_number_t ta_number,
+				      rsbac_list_handle_t handle,
+				      void *desc, u_long count)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+
+	if (!count)
+		return 0;
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+
+/*
+	rsbac_pr_debug(lists, "removing from list of lists %s, device %02u:%02u.\n",
+		       list->name, RSBAC_MAJOR(list->device),
+		       RSBAC_MINOR(list->device));
+*/
+	spin_lock(&list->lock);
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied) {
+		sublist = ta_lookup_lol_item_locked(list->hashed[hash].ta_copied, list, desc);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				ta_do_remove_lol_item(list, sublist, hash);
+			} else {
+				struct rsbac_list_item_t * subitem_p;
+
+				if (ta_number
+				    && (list->hashed[hash].ta_copied != ta_number)) {
+					spin_unlock(&list->lock);
+					return -RSBAC_EBUSY;
+				}
+				while (sublist->head && (count > 0)) {
+					subitem_p = sublist->head;
+					do_remove_lol_subitem(sublist,
+							      subitem_p);
+					rcu_free_lol_sub(list, subitem_p);
+					count--;
+				}
+				if (!sublist->count
+				    && ((list->def_data
+					 && !memcmp(((char *) sublist) +
+						    sizeof(*sublist) +
+						    list->info.desc_size,
+						    list->def_data,
+						    list->info.data_size)
+					)
+					|| (!list->info.data_size
+					    && (list->
+						flags &
+						RSBAC_LIST_DEF_DATA)
+					)
+				    )
+				    ) {
+					ta_do_remove_lol_item(list,
+							      sublist,
+							      hash);
+				}
+			}
+		}
+	} else {
+		if (ta_number && lookup_lol_item_locked(list, desc)) {
+			ta_lol_copy(ta_number, list, hash);
+			ta_remove_lol_item(ta_number, list, desc);
+		}
+	}
+	if (!ta_number)
+#endif
+	{
+		sublist = lookup_lol_item_locked(list, desc);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				do_remove_lol_item(list, sublist, hash);
+				lol_touch(list);
+				list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+				list->write_count++;
+#endif
+			} else {
+				struct rsbac_list_item_t * subitem_p;
+
+				while (sublist->head && (count > 0)) {
+					subitem_p = sublist->head;
+					/* Changes sublist->head */
+					do_remove_lol_subitem(sublist,
+							      subitem_p);
+					rcu_free_lol_sub(list, subitem_p);
+					count--;
+				}
+				lol_touch(list);
+				list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+				list->write_count++;
+#endif
+				if (!sublist->count
+				    && ((list->def_data
+					 && !memcmp(((char *) sublist) +
+						    sizeof(*sublist) +
+						    list->info.desc_size,
+						    list->def_data,
+						    list->info.data_size)
+					)
+					|| (!list->info.data_size
+					    && (list->
+						flags &
+						RSBAC_LIST_DEF_DATA)
+					)
+				    )
+				    ) {
+					do_remove_lol_item(list, sublist, hash);
+				}
+			}
+		}
+	}
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return 0;
+}
+
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subremove);
+#endif
+int rsbac_ta_list_lol_subremove(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle,
+				void *desc, void *subdesc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !subdesc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing from list of lists %s, device %02u:%02u.\n",
+		       list->name, RSBAC_MAJOR(list->device),
+		       RSBAC_MINOR(list->device));
+*/
+	spin_lock(&list->lock);
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied) {
+		sublist = ta_lookup_lol_item_locked(list->hashed[hash].ta_copied, list, desc);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				ta_do_remove_lol_item(list, sublist, hash);
+			} else {
+				if (ta_number
+				    && (list->hashed[hash].ta_copied != ta_number)) {
+					spin_unlock(&list->lock);
+					return -RSBAC_EBUSY;
+				}
+				if (lookup_lol_subitem_locked
+				    (list, sublist, subdesc))
+					remove_lol_subitem(list, sublist,
+							   subdesc);
+				if (!sublist->head
+				    &&
+				    ((list->def_data
+				      && !memcmp(((char *) sublist) +
+						 sizeof(*sublist) +
+						 list->info.desc_size,
+						 list->def_data,
+						 list->info.data_size)
+				     )
+				     || (!list->info.data_size
+					 && (list->
+					     flags & RSBAC_LIST_DEF_DATA)
+				     )
+				    )
+				    ) {
+					ta_do_remove_lol_item(list,
+							      sublist,
+							      hash);
+				}
+			}
+		}
+	} else {
+		if (ta_number && lookup_lol_item_locked(list, desc)) {
+			ta_lol_copy(ta_number, list, hash);
+			ta_remove_lol_item(ta_number, list, desc);
+		}
+	}
+	if (!ta_number)
+#endif
+	{
+		sublist = lookup_lol_item_locked(list, desc);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				do_remove_lol_item(list, sublist, hash);
+				lol_touch(list);
+				list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+				list->write_count++;
+#endif
+			} else {
+				if (lookup_lol_subitem_locked(list, sublist, subdesc)) {	/* exists -> remove and set dirty */
+					remove_lol_subitem(list, sublist,
+							   subdesc);
+					lol_touch(list);
+					list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+					list->write_count++;
+#endif
+				}
+				if (!sublist->head
+				    && ((list->def_data
+					 && !memcmp(((char *) sublist) +
+						    sizeof(*sublist) +
+						    list->info.desc_size,
+						    list->def_data,
+						    list->info.data_size)
+					)
+					|| (!list->info.data_size
+					    && (list->
+						flags &
+						RSBAC_LIST_DEF_DATA)
+					)
+				    )
+				    ) {
+					do_remove_lol_item(list, sublist, hash);
+					lol_touch(list);
+					list->dirty = TRUE;
+				}
+			}
+		}
+	}
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return 0;
+}
+
+/* remove same subitem from all items */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_from_all);
+#endif
+int rsbac_ta_list_lol_subremove_from_all(rsbac_list_ta_number_t ta_number,
+					 rsbac_list_handle_t handle,
+					 void *subdesc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	int i;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!subdesc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing from list of lists %s.\n", list->name);
+*/
+	spin_lock(&list->lock);
+	nr_hashes = 1 << list->hash_bits;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	for (i=0; i<nr_hashes; i++) {
+		if (list->hashed[i].ta_copied) {
+			if (ta_number && (list->hashed[i].ta_copied != ta_number)) {
+				spin_unlock(&list->lock);
+				return -RSBAC_EBUSY;
+			}
+			sublist = list->hashed[i].head;
+			while (sublist) {
+				remove_lol_subitem(list, sublist, subdesc);
+				sublist = sublist->next;
+			}
+		} else {
+			if (ta_number) {
+				ta_lol_copy(ta_number, list, i);
+				sublist = list->hashed[i].head;
+				while (sublist) {
+					remove_lol_subitem(list, sublist, subdesc);
+					sublist = sublist->next;
+				}
+			}
+		}
+	}
+	if (!ta_number)
+#endif
+	{
+		for (i=0; i<nr_hashes; i++) {
+			sublist = list->hashed[i].head;
+			while (sublist) {
+				if (lookup_lol_subitem_locked(list, sublist, subdesc)) {	/* exists -> remove and set dirty */
+					remove_lol_subitem(list, sublist, subdesc);
+					lol_touch(list);
+					list->dirty = TRUE;
+				}
+				sublist = sublist->next;
+			}
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	if (list->dirty)
+		list->write_count++;
+#endif
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return 0;
+}
+
+/* remove all subitems */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_all);
+#endif
+int rsbac_ta_list_lol_subremove_all(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing all subitems from list of lists %s.\n",
+		       list->name);
+*/
+	spin_lock(&list->lock);
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied) {
+		sublist = ta_lookup_lol_item_locked(list->hashed[hash].ta_copied, list, desc);
+		if (sublist) {
+			if (sublist->max_age
+			    && (sublist->max_age <= RSBAC_CURRENT_TIME)
+			    ) {
+				ta_do_remove_lol_item(list, sublist, hash);
+			} else {
+				if (ta_number
+				    && (list->hashed[hash].ta_copied != ta_number)) {
+					spin_unlock(&list->lock);
+					return -RSBAC_EBUSY;
+				}
+				remove_all_lol_subitems(list, sublist);
+				if ((list->def_data
+				     && !memcmp(((char *) sublist) +
+						sizeof(*sublist) +
+						list->info.desc_size,
+						list->def_data,
+						list->info.data_size)
+				    )
+				    || (!list->info.data_size
+					&& (list->
+					    flags & RSBAC_LIST_DEF_DATA)
+				    )
+
+				    ) {
+					ta_do_remove_lol_item(list,
+							      sublist,
+							      hash);
+				}
+			}
+		}
+	} else {
+		if (ta_number && lookup_lol_item_locked(list, desc)) {
+			ta_lol_copy(ta_number, list, hash);
+			sublist =
+			    ta_lookup_lol_item_locked(ta_number, list, desc);
+			if (sublist)
+				remove_all_lol_subitems(list, sublist);
+		}
+	}
+	if (!ta_number)
+#endif
+	{
+		sublist = lookup_lol_item_locked(list, desc);
+		if (sublist && sublist->head) {
+			remove_all_lol_subitems(list, sublist);
+			lol_touch(list);
+			list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+			list->write_count++;
+#endif
+		}
+	}
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_remove);
+#endif
+int rsbac_ta_list_lol_remove(rsbac_list_ta_number_t ta_number,
+			     rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	u_int hash = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing from list of lists %s.\n",
+		       list->name);
+*/
+	spin_lock(&list->lock);
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (list->hashed[hash].ta_copied) {
+		if (ta_number) {
+			if (ta_lookup_lol_item_locked
+			    (list->hashed[hash].ta_copied, list, desc)) {
+				if (list->hashed[hash].ta_copied != ta_number) {
+					spin_unlock(&list->lock);
+					return -RSBAC_EBUSY;
+				} else
+					ta_remove_lol_item(ta_number, list,
+							   desc);
+			}
+		} else
+			ta_remove_lol_item(list->hashed[hash].ta_copied, list, desc);
+	} else {
+		if (ta_number && lookup_lol_item_locked(list, desc)) {
+			ta_lol_copy(ta_number, list, hash);
+			ta_remove_lol_item(ta_number, list, desc);
+		}
+	}
+	if (!ta_number)
+#endif
+	{
+		if (lookup_lol_item_locked(list, desc)) {	/* exists -> remove */
+			remove_lol_item(list, desc);
+			lol_touch(list);
+			list->dirty = TRUE;
+#ifdef CONFIG_RSBAC_LIST_STATS
+			list->write_count++;
+#endif
+		}
+	}
+	rcu_head_lol_p = get_rcu_free_lol(list);
+	spin_unlock(&list->lock);
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return 0;
+}
+
+/* remove all items */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_remove_all);
+#endif
+int rsbac_ta_list_lol_remove_all(rsbac_list_ta_number_t ta_number,
+				 rsbac_list_handle_t handle)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	int i;
+	u_int nr_hashes;
+	struct rsbac_list_rcu_free_head_lol_t ** rcu_head_lol_pp = NULL;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	struct rsbac_list_rcu_free_head_lol_t ** ta_rcu_head_lol_pp = NULL;
+#endif
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "removing all items from list of lists %s.\n",
+		       list->name);
+*/
+restart:
+	nr_hashes = 1 << list->hash_bits;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (!ta_number)
+#endif
+	{
+		rcu_head_lol_pp = rsbac_kmalloc_clear_unlocked(nr_hashes * sizeof(*rcu_head_lol_pp));
+		if (unlikely(!rcu_head_lol_pp))
+			return -RSBAC_ENOMEM;
+	}
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	ta_rcu_head_lol_pp = rsbac_kmalloc_clear_unlocked(nr_hashes * sizeof(*ta_rcu_head_lol_pp));
+	if (unlikely(!ta_rcu_head_lol_pp)) {
+		if (!ta_number)
+			rsbac_kfree(rcu_head_lol_pp);
+		return -RSBAC_ENOMEM;
+	}
+#endif
+	spin_lock(&list->lock);
+	if (unlikely(nr_hashes != 1 << list->hash_bits)) {
+		spin_unlock(&list->lock);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (!ta_number)
+#endif
+			rsbac_kfree(rcu_head_lol_pp);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		rsbac_kfree(ta_rcu_head_lol_pp);
+#endif
+		goto restart;
+	}
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number)
+		for (i=0; i<nr_hashes; i++)
+			if (list->hashed[i].ta_copied && (list->hashed[i].ta_copied != ta_number)) {
+				spin_unlock(&list->lock);
+				rsbac_kfree(ta_rcu_head_lol_pp);
+				return -RSBAC_EBUSY;
+			}
+
+	for (i=0; i<nr_hashes; i++) {
+		if (list->hashed[i].ta_copied) {
+			ta_remove_all_lol_items(list, i);
+			if (ta_number && !list->hashed[i].head)
+				list->hashed[i].ta_copied = 0;
+		} else {
+			if (ta_number && list->hashed[i].head) {
+				list->hashed[i].ta_head = NULL;
+				list->hashed[i].ta_tail = NULL;
+				list->hashed[i].ta_curr = NULL;
+				list->hashed[i].ta_count = 0;
+				list->hashed[i].ta_copied = ta_number;
+			}
+		}
+		ta_rcu_head_lol_pp[i] = get_rcu_free_lol(list);
+	}
+
+	if (!ta_number)
+#endif
+		for (i=0; i<nr_hashes; i++) {
+			if (list->hashed[i].head) {
+				remove_all_lol_items(list, i);
+				lol_touch(list);
+				list->dirty = TRUE;
+				rcu_head_lol_pp[i] = get_rcu_free_lol(list);
+			}
+		}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	if (list->dirty)
+		list->write_count++;
+#endif
+	spin_unlock(&list->lock);
+	synchronize_rcu();
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	for (i=0; i<nr_hashes; i++)
+		rcu_free_do_cleanup_lol(ta_rcu_head_lol_pp[i]);
+	rsbac_kfree(ta_rcu_head_lol_pp);
+	if (!ta_number)
+#endif
+	{
+		for (i=0; i<nr_hashes; i++)
+			rcu_free_do_cleanup_lol(rcu_head_lol_pp[i]);
+		rsbac_kfree(rcu_head_lol_pp);
+	}
+	return 0;
+}
+
+/* get item data */
+/* Item data is copied - we cannot give a pointer, because item could be
+ * removed */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_data_ttl);
+#endif
+int rsbac_ta_list_get_data_ttl(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle,
+			       rsbac_time_t * ttl_p,
+			       void *desc, void *data)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting data from list %s.\n",
+		       list->name);
+*/
+	if (unlikely(data && !list->info.data_size)) {
+		rcu_read_unlock();
+		return -RSBAC_EINVALIDREQUEST;
+	}
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		item_p = ta_lookup_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		item_p = lookup_item(list, hashed, hash, desc);
+	if (item_p
+	    && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
+	    )
+	    ) {			/* exists -> copy data, if any */
+		if (ttl_p) {
+			if (item_p->max_age)
+				*ttl_p =
+				    item_p->max_age - RSBAC_CURRENT_TIME;
+			else
+				*ttl_p = 0;
+		}
+		if (data) {
+			memcpy(data,
+			       ((char *) item_p) + sizeof(*item_p) +
+			       list->info.desc_size, list->info.data_size);
+		}
+	} else {
+		if (!list->def_data)
+			err = -RSBAC_ENOTFOUND;
+		else {
+			if (ttl_p)
+				*ttl_p = 0;
+			if (data)
+				memcpy(data,
+				       list->def_data,
+				       list->info.data_size);
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_max_subdesc);
+#endif
+int rsbac_ta_list_lol_get_max_subdesc(rsbac_list_ta_number_t ta_number,
+				      rsbac_list_handle_t handle,
+				      void *desc, void *subdesc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !subdesc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+/*
+	rsbac_pr_debug(lists, "getting data from list %s.\n",
+		       list->name);
+*/
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist) {		/* exists -> lookup subitem */
+		item_p = rcu_dereference(sublist->tail);
+		while (item_p
+		       && item_p->max_age
+		       && (item_p->max_age > RSBAC_CURRENT_TIME)
+		    )
+			item_p = rcu_dereference(item_p->prev);
+		if (item_p)
+			memcpy(subdesc, (char *) item_p + sizeof(*item_p),
+			       list->info.subdesc_size);
+		else {
+			memset(subdesc, 0, list->info.subdesc_size);
+			err = -RSBAC_ENOTFOUND;
+		}
+	} else {
+		if (!(list->flags & RSBAC_LIST_DEF_DATA))
+			err = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_subdata_ttl);
+#endif
+int rsbac_ta_list_lol_get_subdata_ttl(rsbac_list_ta_number_t ta_number,
+				      rsbac_list_handle_t handle,
+				      rsbac_time_t * ttl_p,
+				      void *desc,
+				      void *subdesc, void *subdata)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !subdesc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(subdata && !list->info.subdata_size)) {
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting data from list %s.\n", list->name);
+*/
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist) {		/* exists -> lookup subitem */
+		item_p = lookup_lol_subitem(list, sublist, subdesc);
+		if (item_p
+		    && (!item_p->max_age
+			|| (item_p->max_age > RSBAC_CURRENT_TIME)
+		    )
+		    ) {		/* exists -> copy data, if any */
+			if (ttl_p) {
+				if (item_p->max_age)
+					*ttl_p =
+					    item_p->max_age -
+					    RSBAC_CURRENT_TIME;
+				else
+					*ttl_p = 0;
+			}
+			if (subdata) {
+				memcpy(subdata,
+				       ((char *) item_p) +
+				       sizeof(*item_p) +
+				       list->info.subdesc_size,
+				       list->info.subdata_size);
+			}
+		} else {
+			if (!list->def_subdata)
+				err = -RSBAC_ENOTFOUND;
+			else {
+				if (ttl_p)
+					*ttl_p = 0;
+				if (subdata)
+					memcpy(subdata,
+					       list->def_subdata,
+					       list->info.subdata_size);
+			}
+		}
+	} else {
+		if (!list->def_subdata)
+			err = -RSBAC_ENOTFOUND;
+		else {
+			if (ttl_p)
+				*ttl_p = 0;
+			if (subdata)
+				memcpy(subdata,
+				       list->def_subdata,
+				       list->info.subdata_size);
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_data_ttl);
+#endif
+int rsbac_ta_list_lol_get_data_ttl(rsbac_list_ta_number_t ta_number,
+				   rsbac_list_handle_t handle,
+				   rsbac_time_t * ttl_p,
+				   void *desc, void *data)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(data && !list->info.data_size)) {
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting data from list %s.\n", list->name);
+*/
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		item_p = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		item_p = lookup_lol_item(list, hashed, hash, desc);
+	if (item_p
+	    && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
+	    )
+	    ) {			/* exists -> copy data, if any */
+		if (ttl_p) {
+			if (item_p->max_age)
+				*ttl_p =
+				    item_p->max_age - RSBAC_CURRENT_TIME;
+			else
+				*ttl_p = 0;
+		}
+		if (data) {
+			memcpy(data,
+			       ((char *) item_p) + sizeof(*item_p) +
+			       list->info.desc_size, list->info.data_size);
+		}
+	} else {
+		if (!list->def_data)
+			err = -RSBAC_ENOTFOUND;
+		else {
+			if (ttl_p)
+				*ttl_p = 0;
+			if (data)
+				memcpy(data,
+				       list->def_data,
+				       list->info.data_size);
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_max_desc);
+#endif
+int rsbac_ta_list_get_max_desc(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p = NULL;
+	struct rsbac_list_item_t *tmp_item_p;
+	int err = 0;
+	int i;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			tmp_item_p = rcu_dereference(hashed[i].ta_tail);
+		else
+#endif
+			tmp_item_p = rcu_dereference(hashed[i].tail);
+		while (tmp_item_p
+		       && tmp_item_p->max_age && (tmp_item_p->max_age > RSBAC_CURRENT_TIME)
+		    )
+			tmp_item_p = rcu_dereference(tmp_item_p->prev);
+		if(tmp_item_p) {
+			if(list->compare) {
+				if(!item_p || list->compare(&tmp_item_p[1], &item_p[1]) > 0)
+					item_p = tmp_item_p;
+			} else {
+				if(!item_p || memcmp(&tmp_item_p[1], &item_p[1], list->info.desc_size) > 0)
+					item_p = tmp_item_p;
+			}
+		}
+	}
+	if (item_p)
+		memcpy(desc, (char *) item_p + sizeof(*item_p),
+		       list->info.desc_size);
+	else {
+		memset(desc, 0, list->info.desc_size);
+		err = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_next_desc);
+#endif
+int rsbac_ta_list_get_next_desc(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle,
+				void *old_desc, void *next_desc)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	if (unlikely(!next_desc))
+		return -RSBAC_EINVALIDPOINTER;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	if (old_desc) {
+		if(list->hash_function)
+			hash = list->hash_function(old_desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = ta_lookup_item(ta_number, list, hashed, hash, old_desc);
+		else
+#endif
+			item_p = lookup_item(list, hashed, hash, old_desc);
+		if(item_p) {
+			item_p = rcu_dereference(item_p->next);
+			while (item_p
+			       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+			    ) {
+				item_p = rcu_dereference(item_p->next);
+			}
+			hash++;
+		} else
+			hash = 0;
+	} else
+		item_p = NULL;
+	while (!item_p && (hash < nr_hashes)) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[hash].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[hash].head);
+		while (item_p
+		       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+		    ) {
+			item_p = rcu_dereference(item_p->next);
+		}
+		hash++;
+	}
+	if (item_p) {
+		memcpy(next_desc, (char *) item_p + sizeof(*item_p),
+		       list->info.desc_size);
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	if (item_p)
+		return 0;
+	else
+		return -RSBAC_ENOTFOUND;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_next_desc_selector);
+#endif
+int rsbac_ta_list_get_next_desc_selector(
+		rsbac_list_ta_number_t ta_number,
+		rsbac_list_handle_t handle,
+		void *old_desc,
+		void *next_desc,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	if (unlikely(!next_desc))
+		return -RSBAC_EINVALIDPOINTER;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	if (old_desc) {
+		if(list->hash_function)
+			hash = list->hash_function(old_desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = ta_lookup_item(ta_number, list, hashed, hash, old_desc);
+		else
+#endif
+			item_p = lookup_item(list, hashed, hash, old_desc);
+		if(item_p) {
+			item_p = rcu_dereference(item_p->next);
+			while (item_p
+			       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+			       && !selector((char *) item_p + sizeof(*item_p), param)
+			    ) {
+				item_p = rcu_dereference(item_p->next);
+			}
+			hash++;
+		} else
+			hash = 0;
+	} else
+		item_p = NULL;
+	while (!item_p && (hash < nr_hashes)) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[hash].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[hash].head);
+		while (item_p
+		       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+		       && !selector((char *) item_p + sizeof(*item_p), param)
+		    ) {
+			item_p = rcu_dereference(item_p->next);
+		}
+		hash++;
+	}
+	if (item_p) {
+		memcpy(next_desc, (char *) item_p + sizeof(*item_p),
+		       list->info.desc_size);
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	if (item_p)
+		return 0;
+	else
+		return -RSBAC_ENOTFOUND;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_next_desc);
+#endif
+int rsbac_ta_list_lol_get_next_desc(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void *old_desc, void *next_desc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	if (unlikely(!next_desc))
+		return -RSBAC_EINVALIDPOINTER;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	if (old_desc) {
+		if(list->hash_function)
+			hash = list->hash_function(old_desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = ta_lookup_lol_item(ta_number, list, hashed, hash, old_desc);
+		else
+#endif
+			item_p = lookup_lol_item(list, hashed, hash, old_desc);
+		if(item_p) {
+			item_p = rcu_dereference(item_p->next);
+			while (item_p
+			       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+			    ) {
+				item_p = rcu_dereference(item_p->next);
+			}
+			hash++;
+		} else
+			hash = 0;
+	} else
+		item_p = NULL;
+	while (!item_p && (hash < nr_hashes)) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[hash].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[hash].head);
+		while (item_p
+		       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+		    ) {
+			item_p = rcu_dereference(item_p->next);
+		}
+		hash++;
+	}
+	if (item_p) {
+		memcpy(next_desc, (char *) item_p + sizeof(*item_p),
+		       list->info.desc_size);
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	if (item_p)
+		return 0;
+	else
+		return -RSBAC_ENOTFOUND;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_next_desc_selector);
+#endif
+int rsbac_ta_list_lol_get_next_desc_selector(
+		rsbac_list_ta_number_t ta_number,
+		rsbac_list_handle_t handle,
+		void *old_desc, void *next_desc,
+		rsbac_list_desc_selector_function_t selector,
+		void * param)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+	if (unlikely(!next_desc))
+		return -RSBAC_EINVALIDPOINTER;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	if (old_desc) {
+		if(list->hash_function)
+			hash = list->hash_function(old_desc, list->hash_bits);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = ta_lookup_lol_item(ta_number, list, hashed, hash, old_desc);
+		else
+#endif
+			item_p = lookup_lol_item(list, hashed, hash, old_desc);
+		if(item_p) {
+			item_p = rcu_dereference(item_p->next);
+			while (item_p
+			       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+			       && !selector((char *) item_p + sizeof(*item_p), param)
+			    ) {
+				item_p = rcu_dereference(item_p->next);
+			}
+			hash++;
+		} else
+			hash = 0;
+	} else
+		item_p = NULL;
+	while (!item_p && (hash < nr_hashes)) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[hash].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[hash].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[hash].head);
+		while (item_p
+		       && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
+		       && !selector((char *) item_p + sizeof(*item_p), param)
+		    ) {
+			item_p = rcu_dereference(item_p->next);
+		}
+		hash++;
+	}
+	if (item_p) {
+		memcpy(next_desc, (char *) item_p + sizeof(*item_p),
+		       list->info.desc_size);
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	if (item_p)
+		return 0;
+	else
+		return -RSBAC_ENOTFOUND;
+}
+
+/* get item desc by data */
+/* Item desc is copied - we cannot give a pointer, because item could be
+ * removed.
+ * If no compare function is provided (NULL value), memcmp is used.
+ * Note: The data value given here is always used as second parameter to the
+ *       compare function, so you can use different types for storage and
+ *       lookup.
+ */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_desc_ttl);
+#endif
+int rsbac_ta_list_get_desc_ttl(rsbac_list_ta_number_t ta_number,
+			   rsbac_list_handle_t handle,
+			   rsbac_time_t * ttl_p,
+			   void *desc,
+			   void *data,
+			   rsbac_list_data_compare_function_t compare)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_hashed_t * hashed;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !data))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting desc from list %s.\n", list->name);
+*/
+	if (unlikely(!list->info.data_size)) {
+		rcu_read_unlock();
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	item_p = ta_lookup_item_data(ta_number, list, hashed, list->hash_bits, data, compare);
+#else
+	item_p = lookup_item_data(list, hashed, list->hash_bits, data, compare);
+#endif
+	if (item_p) {		/* exists -> copy desc */
+		memcpy(desc,
+		       ((char *) item_p) + sizeof(*item_p),
+		       list->info.desc_size);
+		if (ttl_p) {
+			if (item_p->max_age)
+				*ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
+			else
+				*ttl_p = 0;
+		}
+	} else {
+		err = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_desc_selector_ttl);
+#endif
+int rsbac_ta_list_get_desc_selector_ttl(
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	rsbac_time_t * ttl_p,
+	void *desc,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_hashed_t * hashed;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !data))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting desc from list %s.\n", list->name);
+*/
+	if (unlikely(!list->info.data_size)) {
+		rcu_read_unlock();
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	item_p = ta_lookup_item_data_selector(ta_number, list,
+					hashed, list->hash_bits,
+					data, compare,
+					selector,
+					param);
+#else
+	item_p = lookup_item_data_selector(list,
+					hashed, list->hash_bits,
+					data, compare,
+					selector,
+					param);
+#endif
+	if (item_p) {		/* exists -> copy desc */
+		memcpy(desc,
+		       ((char *) item_p) + sizeof(*item_p),
+		       list->info.desc_size);
+		if (ttl_p) {
+			if (item_p->max_age)
+				*ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
+			else
+				*ttl_p = 0;
+		}
+	} else {
+		err = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_desc_ttl);
+#endif
+int rsbac_ta_list_lol_get_desc_ttl(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle,
+			       rsbac_time_t * ttl_p,
+			       void *desc,
+			       void *data,
+			       rsbac_list_data_compare_function_t compare)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !data))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(!list->info.data_size)) {
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting desc from list %s.\n", list->name);
+*/
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	item_p = ta_lookup_lol_item_data(ta_number, list, hashed, list->hash_bits, data, compare);
+#else
+	item_p = lookup_lol_item_data(list, hashed, list->hash_bits, data, compare);
+#endif
+	if (item_p) {		/* exists -> copy desc */
+		memcpy(desc,
+		       ((char *) item_p) + sizeof(*item_p),
+		       list->info.desc_size);
+		if (ttl_p) {
+			if (item_p->max_age)
+				*ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
+			else
+				*ttl_p = 0;
+		}
+	} else {
+		err = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_desc_selector_ttl);
+#endif
+int rsbac_ta_list_lol_get_desc_selector_ttl(
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	rsbac_time_t * ttl_p,
+	void *desc,
+	void *data,
+	rsbac_list_data_compare_function_t compare,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	int err = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!desc || !data))
+		return -RSBAC_EINVALIDVALUE;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(!list->info.data_size)) {
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "getting desc from list %s.\n", list->name);
+*/
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	item_p = ta_lookup_lol_item_data_selector(ta_number,
+						list, hashed, list->hash_bits,
+						data, compare,
+						selector,
+						param);
+#else
+	item_p = lookup_lol_item_data_selector(list, hashed, list->hash_bits,
+						data, compare,
+						selector,
+						param);
+#endif
+	if (item_p) {		/* exists -> copy desc */
+		memcpy(desc,
+		       ((char *) item_p) + sizeof(*item_p),
+		       list->info.desc_size);
+		if (ttl_p) {
+			if (item_p->max_age)
+				*ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
+			else
+				*ttl_p = 0;
+		}
+	} else {
+		err = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return err;
+}
+
+/* returns TRUE, if item exists or def_data is defined, FALSE, if not */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_exist);
+#endif
+int rsbac_ta_list_exist(rsbac_list_ta_number_t ta_number,
+			rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	int result;
+	struct rsbac_list_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle || !desc))
+		return FALSE;
+	if (unlikely(!list_initialized))
+		return FALSE;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return FALSE;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "testing on list %s.\n", list->name);
+*/
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		item_p = ta_lookup_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		item_p = lookup_item(list, hashed, hash, desc);
+	if (item_p
+	    && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
+	    )
+	    ) {			/* exists -> TRUE */
+		result = TRUE;
+	} else {
+		result = FALSE;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+/* does item exist? */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subexist);
+#endif
+int rsbac_ta_list_lol_subexist(rsbac_list_ta_number_t ta_number,
+			       rsbac_list_handle_t handle,
+			       void *desc, void *subdesc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	int result;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle || !desc || !subdesc))
+		return FALSE;
+	if (unlikely(!list_initialized))
+		return FALSE;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return FALSE;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "testing on list %s.\n", list->name);
+*/
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist) {		/* exists -> lookup subitem */
+		item_p = lookup_lol_subitem(list, sublist, subdesc);
+		if (item_p
+		    && (!item_p->max_age
+			|| (item_p->max_age > RSBAC_CURRENT_TIME)
+		    )
+		    ) {		/* exists -> TRUE */
+			result = TRUE;
+		} else {
+			result = FALSE;
+		}
+	} else {
+		result = FALSE;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subexist_compare);
+#endif
+int rsbac_ta_list_lol_subexist_compare(rsbac_list_ta_number_t ta_number,
+				       rsbac_list_handle_t handle,
+				       void *desc,
+				       void *subdesc,
+				       rsbac_list_compare_function_t
+				       compare)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	int result;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle || !desc || !subdesc))
+		return FALSE;
+	if (unlikely(!list_initialized))
+		return FALSE;
+	/* Use standard function, if compare is not provided. */
+	if (!compare)
+		return rsbac_list_lol_subexist(handle, desc, subdesc);
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return FALSE;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "testing on list %s.\n", list->name);
+*/
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist) {		/* exists -> lookup subitem */
+		item_p =
+		    lookup_lol_subitem_user_compare(list, sublist, subdesc,
+						    compare);
+		if (item_p
+		    && (!item_p->max_age
+			|| (item_p->max_age > RSBAC_CURRENT_TIME)
+		    )
+		    ) {		/* exists -> TRUE */
+			result = TRUE;
+		} else {
+			result = FALSE;
+		}
+	} else {
+		result = FALSE;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_exist);
+#endif
+int rsbac_ta_list_lol_exist(rsbac_list_ta_number_t ta_number,
+			    rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	int result;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle || !desc))
+		return FALSE;
+	if (unlikely(!list_initialized))
+		return FALSE;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return FALSE;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "testing on list %s.\n", list->name);
+*/
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		item_p = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		item_p = lookup_lol_item(list, hashed, hash, desc);
+	if (item_p
+	    && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
+	    )
+	    ) {			/* exists -> TRUE */
+		result = TRUE;
+	} else {
+		result = FALSE;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+/* count number of elements */
+/* returns number of elements or negative error code */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_subcount);
+#endif
+long rsbac_ta_list_lol_subcount(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle, void *desc)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	long result;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist) {
+		result = sublist->count;
+	} else {
+		result = -RSBAC_ENOTFOUND;
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_all_subcount);
+#endif
+long rsbac_ta_list_lol_all_subcount(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	long result = 0;
+	int i;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			sublist = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			sublist = rcu_dereference(hashed[i].head);
+		while (sublist) {
+			result += sublist->count;
+			sublist = rcu_dereference(sublist->next);
+		}
+	}
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_count);
+#endif
+long rsbac_ta_list_lol_count(rsbac_list_ta_number_t ta_number,
+			     rsbac_list_handle_t handle)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	long result = 0;
+	int i;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	rcu_read_lock();
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			result += hashed[i].ta_count;
+		else
+#endif
+			result += hashed[i].count;
+	}
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_count);
+#endif
+long rsbac_ta_list_count(rsbac_list_ta_number_t ta_number,
+			 rsbac_list_handle_t handle)
+{
+	struct rsbac_list_reg_item_t *list;
+	long result = 0;
+	int i;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			result += hashed[i].ta_count;
+		else
+#endif
+			result += hashed[i].count;
+	}
+	rcu_read_unlock();
+	return result;
+}
+
+/* Get array of all descriptors */
+/* Returns number of elements or negative error code */
+/* If return value > 0, *array_p contains a pointer to a rsbac_kmalloc'd array
+   of descs, otherwise *array_p is set to NULL. If *array_p has been set,
+   caller must call rsbac_kfree(*array_p) after use! */
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_all_desc);
+#endif
+long rsbac_ta_list_get_all_desc(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle, void **array_p)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	u_long count = 0;
+	long result = 0;
+	u_int item_size;
+	int i;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.desc_size;
+	if(count > RSBAC_MAX_KMALLOC / item_size)
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (!item_p->max_age
+			    || (item_p->max_age >
+				RSBAC_CURRENT_TIME)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p), item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_all_desc_selector);
+#endif
+long rsbac_ta_list_get_all_desc_selector (
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle, void **array_p,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	u_long count = 0;
+	long result = 0;
+	u_int item_size;
+	int i;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p || !selector))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.desc_size;
+	if(count > RSBAC_MAX_KMALLOC / item_size)
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (   (!item_p->max_age
+			        || (item_p->max_age >
+				    RSBAC_CURRENT_TIME)
+			       )
+			    && selector(((char *) item_p) + sizeof(*item_p), param)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p), item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subdesc_ttl);
+#endif
+long rsbac_ta_list_lol_get_all_subdesc_ttl(rsbac_list_ta_number_t
+					   ta_number,
+					   rsbac_list_handle_t handle,
+					   void *desc, void **array_p,
+					   rsbac_time_t ** ttl_array_p)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	rsbac_time_t *ttl_p = NULL;
+	u_long offset = 0;
+	long result = 0;
+	u_long count;
+	u_int item_size;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist && sublist->count) {
+		item_size = list->info.subdesc_size;
+		count = sublist->count;
+		if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+			count = RSBAC_MAX_KMALLOC / item_size;
+		buffer = rsbac_kmalloc(item_size * count);
+		if (buffer) {
+			if (ttl_array_p)
+				ttl_p =
+				    rsbac_kmalloc(sizeof(**ttl_array_p) *
+						  sublist->count);
+			item_p = rcu_dereference(sublist->head);
+			while (item_p && (result < count)) {
+				if (!item_p->max_age
+				    || (item_p->max_age >
+					RSBAC_CURRENT_TIME)
+				    ) {
+					memcpy(buffer + offset,
+					       ((char *) item_p) +
+					       sizeof(*item_p), item_size);
+					if (ttl_p) {
+						if (item_p->max_age)
+							ttl_p[result] =
+							    item_p->
+							    max_age -
+							    RSBAC_CURRENT_TIME;
+						else
+							ttl_p[result] = 0;
+					}
+					offset += item_size;
+					result++;
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+			*array_p = buffer;
+			if (ttl_array_p)
+				*ttl_array_p = ttl_p;
+		} else {
+			result = -RSBAC_ENOMEM;
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_desc);
+#endif
+long rsbac_ta_list_lol_get_all_desc(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void **array_p)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	long result = 0;
+	u_int item_size;
+	int i;
+	u_long count = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.desc_size;
+	if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		rsbac_pr_debug(lists, "list %s: could not allocate buffer  for %u items of size %u!\n",
+			list->name, count, item_size);
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (!item_p->max_age
+			    || (item_p->max_age >
+				RSBAC_CURRENT_TIME)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p), item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_desc_selector);
+#endif
+long rsbac_ta_list_lol_get_all_desc_selector (
+	rsbac_list_ta_number_t ta_number,
+	rsbac_list_handle_t handle,
+	void **array_p,
+	rsbac_list_desc_selector_function_t selector,
+	void * param)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	long result = 0;
+	u_int item_size;
+	int i;
+	u_long count = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p || !selector))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.desc_size;
+	if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		rsbac_pr_debug(lists, "list %s: could not allocate buffer  for %u items of size %u!\n",
+			list->name, count, item_size);
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (   (!item_p->max_age
+			        || (item_p->max_age >
+				    RSBAC_CURRENT_TIME)
+			       )
+			    && selector(((char *) item_p) + sizeof(*item_p), param)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p), item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+/* Get array of all data */
+/* Returns number of elements or negative error code */
+/* If return value > 0, *array_p contains a pointer to a rsbac_kmalloc'd array
+   of datas, otherwise *array_p is set to NULL. If *array_p has been set,
+   caller must call rsbac_kfree(*array_p) after use! */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_all_data);
+#endif
+long rsbac_ta_list_get_all_data(rsbac_list_ta_number_t ta_number,
+				rsbac_list_handle_t handle, void **array_p)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	long result = 0;
+	u_int item_size;
+	u_int item_offset;
+	int i;
+	u_long count = 0;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	if (unlikely(!list->info.data_size)) {
+		rcu_read_unlock();
+		return -RSBAC_EINVALIDREQUEST;
+	}
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.data_size;
+	item_offset = list->info.desc_size;
+	if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (!item_p->max_age
+			    || (item_p->max_age >
+				RSBAC_CURRENT_TIME)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p) +
+				       item_offset, item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subdata);
+#endif
+long rsbac_ta_list_lol_get_all_subdata(rsbac_list_ta_number_t ta_number,
+				       rsbac_list_handle_t handle,
+				       void *desc, void **array_p)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	long result = 0;
+	u_long count;
+	u_int item_size;
+	u_int item_offset;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	if (unlikely(!list->info.subdata_size)) {
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist && sublist->count) {
+		item_size = list->info.subdata_size;
+		item_offset = list->info.subdesc_size;
+		count = sublist->count;
+		if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+			count = RSBAC_MAX_KMALLOC / item_size;
+		buffer = rsbac_kmalloc(item_size * count);
+		if (buffer) {
+			item_p = rcu_dereference(sublist->head);
+			while (item_p && (result < count)) {
+				if (!item_p->max_age
+				    || (item_p->max_age >
+					RSBAC_CURRENT_TIME)
+				    ) {
+					memcpy(buffer + offset,
+					       ((char *) item_p) +
+					       sizeof(*item_p) +
+					       item_offset, item_size);
+					offset += item_size;
+					result++;
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+			*array_p = buffer;
+		} else {
+			result = -RSBAC_ENOMEM;
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_data);
+#endif
+long rsbac_ta_list_lol_get_all_data(rsbac_list_ta_number_t ta_number,
+				    rsbac_list_handle_t handle,
+				    void **array_p)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	long result = 0;
+	u_int item_size;
+	u_int item_offset;
+	int i;
+	u_long count = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	if (unlikely(!list->info.data_size)) {
+		rcu_read_unlock();
+		return -RSBAC_EINVALIDREQUEST;
+	}
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.data_size;
+	item_offset = list->info.desc_size;
+	if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (!item_p->max_age
+			    || (item_p->max_age >
+				RSBAC_CURRENT_TIME)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p) +
+				       item_offset, item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+/* Get item size */
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_get_item_size);
+#endif
+int rsbac_list_get_item_size(rsbac_list_handle_t handle)
+{
+	struct rsbac_list_reg_item_t *list;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	return list->info.desc_size + list->info.data_size;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_get_subitem_size);
+#endif
+int rsbac_list_lol_get_subitem_size(rsbac_list_handle_t handle)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	return list->info.subdesc_size + list->info.subdata_size;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_get_item_size);
+#endif
+int rsbac_list_lol_get_item_size(rsbac_list_handle_t handle)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	return list->info.desc_size + list->info.data_size;
+}
+
+/* Get array of all items */
+/* Returns number of items or negative error code */
+/* If return value > 0, *array_p contains a pointer to a rsbac_kmalloc'd array of items,
+   where desc and data are placed directly behind each other.
+   If *array_p has been set (return value > 0), caller must call rsbac_kfree(*array_p) after use! */
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_get_all_items_ttl);
+#endif
+long rsbac_ta_list_get_all_items_ttl(rsbac_list_ta_number_t ta_number,
+				     rsbac_list_handle_t handle,
+				     void **array_p,
+				     rsbac_time_t ** ttl_array_p)
+{
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	rsbac_time_t *ttl_p = NULL;
+	u_long offset = 0;
+	long result = 0;
+	u_int item_size;
+	int i;
+	u_long count = 0;
+	struct rsbac_list_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.desc_size + list->info.data_size;
+	if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		goto out_unlock;
+	}
+	if (ttl_array_p) {
+		ttl_p = rsbac_kmalloc(sizeof(**ttl_array_p) * count);
+		if (!ttl_p) {
+			result = -ENOMEM;
+			rsbac_kfree(buffer);
+			goto out_unlock;
+		}
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (!item_p->max_age
+			    || (item_p->max_age >
+				RSBAC_CURRENT_TIME)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p), item_size);
+				if (ttl_p) {
+					if (item_p->max_age)
+						ttl_p[result] =
+						    item_p->max_age - RSBAC_CURRENT_TIME;
+					else
+						ttl_p[result] = 0;
+				}
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+	if (ttl_array_p)
+		*ttl_array_p = ttl_p;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subitems_ttl);
+#endif
+long rsbac_ta_list_lol_get_all_subitems_ttl(rsbac_list_ta_number_t
+					    ta_number,
+					    rsbac_list_handle_t handle,
+					    void *desc, void **array_p,
+					    rsbac_time_t ** ttl_array_p)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *sublist;
+	struct rsbac_list_item_t *item_p;
+	char *buffer;
+	rsbac_time_t *ttl_p = NULL;
+	u_long offset = 0;
+	long result = 0;
+	u_long count;
+	u_int item_size;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int hash = 0;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	if(list->hash_function)
+		hash = list->hash_function(desc, list->hash_bits);
+	hashed = rcu_dereference(list->hashed);
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	if (ta_number && (hashed[hash].ta_copied == ta_number))
+		sublist = ta_lookup_lol_item(ta_number, list, hashed, hash, desc);
+	else
+#endif
+		sublist = lookup_lol_item(list, hashed, hash, desc);
+	if (sublist && sublist->count) {
+		count = sublist->count;
+		item_size =
+		    list->info.subdesc_size + list->info.subdata_size;
+		if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+			count = RSBAC_MAX_KMALLOC / item_size;
+		buffer = rsbac_kmalloc(item_size * count);
+		if (likely(buffer)) {
+			if (ttl_array_p)
+				ttl_p =
+				    rsbac_kmalloc(sizeof(**ttl_array_p) *
+						  sublist->count);
+			item_p = rcu_dereference(sublist->head);
+			while (item_p && (result < count)) {
+				if (!item_p->max_age
+				    || (item_p->max_age >
+					RSBAC_CURRENT_TIME)
+				    ) {
+					memcpy(buffer + offset,
+					       ((char *) item_p) +
+					       sizeof(*item_p), item_size);
+					if (ttl_p) {
+						if (item_p->max_age)
+							ttl_p[result] =
+							    item_p->
+							    max_age -
+							    RSBAC_CURRENT_TIME;
+						else
+							ttl_p[result] = 0;
+					}
+					offset += item_size;
+					result++;
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+			*array_p = buffer;
+			if (ttl_array_p)
+				*ttl_array_p = ttl_p;
+		} else {
+			result = -RSBAC_ENOMEM;
+		}
+	}
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+	rcu_read_unlock();
+	return result;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_items);
+#endif
+long rsbac_ta_list_lol_get_all_items(rsbac_list_ta_number_t ta_number,
+				     rsbac_list_handle_t handle,
+				     void **array_p)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+	struct rsbac_list_lol_item_t *item_p;
+	char *buffer;
+	u_long offset = 0;
+	long result = 0;
+	u_int item_size;
+	int i;
+	u_long count = 0;
+	struct rsbac_list_lol_hashed_t * hashed;
+	u_int nr_hashes;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!array_p))
+		return -RSBAC_EINVALIDPOINTER;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+	*array_p = NULL;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s.\n", list->name);
+*/
+	nr_hashes = 1 << list->hash_bits;
+	hashed = rcu_dereference(list->hashed);
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			count += hashed[i].ta_count;
+		else
+#endif
+			count += hashed[i].count;
+	}
+	if(!count) {
+		result = 0;
+		goto out_unlock;
+	}
+	item_size = list->info.desc_size + list->info.data_size;
+	if(unlikely(count > RSBAC_MAX_KMALLOC / item_size))
+		count = RSBAC_MAX_KMALLOC / item_size;
+	buffer = rsbac_kmalloc(item_size * count);
+	if (unlikely(!buffer)) {
+		result = -ENOMEM;
+		goto out_unlock;
+	}
+	for (i=0; i<nr_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number && (hashed[i].ta_copied == ta_number))
+			item_p = rcu_dereference(hashed[i].ta_head);
+		else
+#endif
+			item_p = rcu_dereference(hashed[i].head);
+		while (item_p && (result < count)) {
+			if (!item_p->max_age
+			    || (item_p->max_age >
+				RSBAC_CURRENT_TIME)
+			    ) {
+				memcpy(buffer + offset,
+				       ((char *) item_p) +
+				       sizeof(*item_p), item_size);
+				offset += item_size;
+				result++;
+			}
+			item_p = rcu_dereference(item_p->next);
+		}
+	}
+	*array_p = buffer;
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	list->read_count++;
+#endif
+out_unlock:
+	rcu_read_unlock();
+	return result;
+}
+
+/* List hash functions
+ *
+ * nr_hashes is always 2^n, so we can safely use bit operations
+ */
+
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_u32);
+#endif
+u_int rsbac_list_hash_u32(void * desc, __u8 hash_bits)
+{
+	return hash_32(*((__u32 *) desc), rsbac_min(hash_bits, 32));
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_fd);
+#endif
+u_int rsbac_list_hash_fd(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((rsbac_inode_nr_t *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_old_fd);
+#endif
+u_int rsbac_list_hash_old_fd(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((rsbac_old_inode_nr_t *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_pid);
+#endif
+u_int rsbac_list_hash_pid(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((__u32 *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_uid);
+#endif
+u_int rsbac_list_hash_uid(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((rsbac_uid_t *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_gid);
+#endif
+u_int rsbac_list_hash_gid(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((rsbac_gid_t *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_ipc);
+#endif
+u_int rsbac_list_hash_ipc(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(((struct rsbac_ipc_t *) desc)->id.id_nr, rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_dev);
+#endif
+u_int rsbac_list_hash_dev(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32( ((struct rsbac_dev_desc_t *) desc)->major + ((struct rsbac_dev_desc_t *) desc)->minor,
+				rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_nettemp);
+#endif
+u_int rsbac_list_hash_nettemp(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((rsbac_net_temp_id_t *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_hash_netobj);
+#endif
+u_int rsbac_list_hash_netobj(void * desc, __u8 hash_bits)
+{
+	return hash_bits ? hash_32(*((__u32 *) desc), rsbac_min(hash_bits, 32)) : 0;
+}
+/* Copy a complete list to another */
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_copy);
+#endif
+long rsbac_list_copy(rsbac_list_ta_number_t ta_number,
+			rsbac_list_handle_t from_handle,
+			rsbac_list_handle_t to_handle)
+{
+	struct rsbac_list_reg_item_t *from_list;
+	struct rsbac_list_reg_item_t *to_list;
+	struct rsbac_list_item_t *item_p;
+	int i;
+	int err = 0;
+	struct rsbac_list_rcu_free_head_t * rcu_head_p;
+	struct rsbac_list_hashed_t * from_hashed;
+	u_int nr_from_hashes;
+	u_int nr_to_hashes;
+
+	if (unlikely(!from_handle || !to_handle))
+		return -RSBAC_EINVALIDLIST;
+
+	from_list = (struct rsbac_list_reg_item_t *) from_handle;
+	if (unlikely(from_list->self != from_list))
+		return -RSBAC_EINVALIDLIST;
+	to_list = (struct rsbac_list_reg_item_t *) to_handle;
+	if (unlikely(to_list->self != to_list))
+		return -RSBAC_EINVALIDLIST;
+	if(unlikely((from_list->info.desc_size != to_list->info.desc_size)
+		|| (from_list->info.data_size != to_list->info.data_size)))
+               return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s to list %s.\n",
+		       from_list->name, to_list->name);
+*/
+	spin_lock(&to_list->lock);
+	nr_to_hashes = 1 << to_list->hash_bits;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	/* Check for other transactions at the target list */
+	if(unlikely(ta_number))
+		for (i=0; i<nr_to_hashes; i++)
+			if(unlikely(to_list->hashed[i].ta_copied != ta_number)) {
+				err = -RSBAC_EBUSY;
+				goto out_unlock;
+			}
+#endif
+	for (i=0; i<nr_to_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if(ta_number && (to_list->hashed[i].ta_copied == ta_number))
+			ta_remove_all_items(to_list, i);
+		else
+#endif
+			remove_all_items(to_list, i);
+	}
+	nr_from_hashes = 1 << from_list->hash_bits;
+	from_hashed = rcu_dereference(from_list->hashed);
+	for (i=0; i<nr_from_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (ta_number) {
+			if(from_hashed[i].ta_copied == ta_number)
+				item_p = rcu_dereference(from_hashed[i].ta_head);
+			else
+				item_p = rcu_dereference(from_hashed[i].head);
+			while(item_p) {
+				if (!ta_add_item(ta_number,
+						to_list,
+						item_p->max_age,
+						&item_p[1],
+						&item_p[1] + from_list->info.desc_size)) {
+					err = -RSBAC_EWRITEFAILED;
+					goto out_unlock;
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+		}
+		else
+#endif
+		{
+			item_p = rcu_dereference(from_hashed[i].head);
+			while(item_p) {
+				if (!add_item(to_list,
+						item_p->max_age,
+						&item_p[1],
+						&item_p[1] + from_list->info.desc_size)) {
+					err = -RSBAC_EWRITEFAILED;
+					goto out_unlock;
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+		}
+	}
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	from_list->read_count++;
+	to_list->write_count++;
+#endif
+out_unlock:
+	rcu_head_p = get_rcu_free(to_list);
+	spin_unlock(&to_list->lock);
+	rcu_read_unlock();
+	do_sync_rcu(rcu_head_p);
+	return err;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_copy);
+#endif
+long rsbac_list_lol_copy(rsbac_list_ta_number_t ta_number,
+			rsbac_list_handle_t from_handle,
+			rsbac_list_handle_t to_handle)
+{
+	struct rsbac_list_lol_reg_item_t *from_list;
+	struct rsbac_list_lol_reg_item_t *to_list;
+	struct rsbac_list_lol_item_t *item_p;
+	struct rsbac_list_lol_item_t *new_item_p;
+        struct rsbac_list_item_t *subitem_p;
+        struct rsbac_list_item_t *new_subitem_p;
+	u_int subitem_size;
+	int i;
+	int err = 0;
+	struct rsbac_list_rcu_free_head_lol_t * rcu_head_lol_p;
+	struct rsbac_list_lol_hashed_t * from_hashed;
+	u_int nr_from_hashes;
+	u_int nr_to_hashes;
+
+	if (unlikely(!from_handle || !to_handle))
+		return -RSBAC_EINVALIDLIST;
+
+	from_list = (struct rsbac_list_lol_reg_item_t *) from_handle;
+	if (unlikely(from_list->self != from_list))
+		return -RSBAC_EINVALIDLIST;
+	to_list = (struct rsbac_list_lol_reg_item_t *) to_handle;
+	if (unlikely(to_list->self != to_list))
+		return -RSBAC_EINVALIDLIST;
+	if(unlikely((from_list->info.desc_size != to_list->info.desc_size)
+		|| (from_list->info.data_size != to_list->info.data_size)
+		|| (from_list->info.subdesc_size != to_list->info.subdesc_size)
+		|| (from_list->info.subdata_size != to_list->info.subdata_size)))
+               return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	while(ta_committing)
+		schedule();
+	if (unlikely(ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number)))
+		return -RSBAC_EINVALIDTRANSACTION;
+#endif
+
+	subitem_size = sizeof(*new_subitem_p)
+	    + from_list->info.subdesc_size + from_list->info.subdata_size;
+
+	rcu_read_lock();
+/*
+	rsbac_pr_debug(lists, "list %s to list %s.\n",
+		       from_list->name, to_list->name);
+*/
+	spin_lock(&to_list->lock);
+	nr_to_hashes = 1 << to_list->hash_bits;
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	/* Check for other transactions at the target list */
+	if(unlikely(ta_number))
+		for (i=0; i<nr_to_hashes; i++)
+			if(unlikely(to_list->hashed[i].ta_copied != ta_number)) {
+				err = -RSBAC_EBUSY;
+				goto out_unlock;
+			}
+#endif
+	for (i=0; i<nr_to_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if(ta_number && (to_list->hashed[i].ta_copied == ta_number))
+			ta_remove_all_lol_items(to_list, i);
+		else
+#endif
+			remove_all_lol_items(to_list, i);
+	}
+	nr_from_hashes = 1 << from_list->hash_bits;
+	from_hashed = rcu_dereference(from_list->hashed);
+	for (i=0; i<nr_from_hashes; i++) {
+#ifdef CONFIG_RSBAC_LIST_TRANS
+		if (unlikely(ta_number)) {
+			if(from_hashed[i].ta_copied == ta_number)
+				item_p = rcu_dereference(from_hashed[i].ta_head);
+			else
+				item_p = rcu_dereference(from_hashed[i].head);
+			while(item_p) {
+				new_item_p = ta_add_lol_item(ta_number,
+						to_list,
+						item_p->max_age,
+						&item_p[1],
+						&item_p[1] + from_list->info.desc_size);
+				if(unlikely(!new_item_p)) {
+					err = -RSBAC_EWRITEFAILED;
+					goto out_unlock;
+				}
+				subitem_p = rcu_dereference(item_p->head);
+				while (subitem_p) {
+					if (to_list->subslab)
+						new_subitem_p = rsbac_smalloc(to_list->subslab);
+					else
+						new_subitem_p = rsbac_kmalloc(subitem_size);
+					if (!new_subitem_p) {
+						err = -RSBAC_ENOMEM;
+						goto out_unlock;
+					}
+					memcpy(new_subitem_p, subitem_p, subitem_size);
+					new_subitem_p->prev = NULL;
+					new_subitem_p->next = NULL;
+					if (new_item_p->tail) {
+						new_subitem_p->prev = new_item_p->tail;
+						new_item_p->tail->next = new_subitem_p;
+						new_item_p->tail = new_subitem_p;
+						new_item_p->count++;
+					} else {
+						new_item_p->head = new_subitem_p;
+						new_item_p->tail = new_subitem_p;
+						new_item_p->count = 1;
+						}
+					subitem_p = rcu_dereference(subitem_p->next);
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+		}
+		else
+#endif
+		{
+			item_p = rcu_dereference(from_hashed[i].head);
+			while(item_p) {
+				new_item_p = add_lol_item(to_list,
+						item_p->max_age,
+						&item_p[1],
+						&item_p[1] + from_list->info.desc_size);
+				if(unlikely(!new_item_p)) {
+					err = -RSBAC_EWRITEFAILED;
+					goto out_unlock;
+				}
+				subitem_p = rcu_dereference(item_p->head);
+				while (subitem_p) {
+					if (to_list->subslab)
+						new_subitem_p = rsbac_smalloc(to_list->subslab);
+					else
+						new_subitem_p = rsbac_kmalloc(subitem_size);
+					if (!new_subitem_p) {
+						err = -RSBAC_ENOMEM;
+						goto out_unlock;
+					}
+					memcpy(new_subitem_p, subitem_p, subitem_size);
+					new_subitem_p->prev = NULL;
+					new_subitem_p->next = NULL;
+					if (new_item_p->tail) {
+						new_subitem_p->prev = new_item_p->tail;
+						new_item_p->tail->next = new_subitem_p;
+						new_item_p->tail = new_subitem_p;
+						new_item_p->count++;
+					} else {
+						new_item_p->head = new_subitem_p;
+						new_item_p->tail = new_subitem_p;
+						new_item_p->count = 1;
+						}
+					subitem_p = rcu_dereference(subitem_p->next);
+				}
+				item_p = rcu_dereference(item_p->next);
+			}
+		}
+	}
+
+#ifdef CONFIG_RSBAC_LIST_STATS
+	from_list->read_count++;
+	to_list->write_count++;
+#endif
+out_unlock:
+	rcu_head_lol_p = get_rcu_free_lol(to_list);
+	spin_unlock(&to_list->lock);
+	rcu_read_unlock();
+	do_sync_rcu_lol(rcu_head_lol_p);
+	return err;
+}
+
+static int do_rehash(struct rsbac_list_reg_item_t *list, __u8 new_bits)
+{
+	struct rsbac_list_hashed_t * old_hashed;
+	struct rsbac_list_hashed_t * new_hashed;
+	int i;
+        struct rsbac_list_item_t *item_p;
+        struct rsbac_list_item_t *new_item_p;
+        u_int new_hash;
+        u_int old_nr;
+        u_int new_nr = 1 << new_bits;
+        u_int item_size;
+
+	new_hashed = rsbac_kmalloc_clear_unlocked(new_nr*sizeof(struct rsbac_list_hashed_t));
+	if(unlikely(!new_hashed)) {
+		return -RSBAC_ENOMEM;
+	}
+	spin_lock(&list->lock);
+	old_nr = 1 << list->hash_bits;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	for(i=0; i<old_nr; i++)
+		if(list->hashed[i].ta_copied) {
+			spin_unlock(&list->lock);
+			rsbac_kfree(new_hashed);
+			return -RSBAC_EBUSY;
+		}
+#endif
+	old_hashed = list->hashed;
+	item_size = sizeof(*item_p) + list->info.desc_size + list->info.data_size;
+	for(i=0; i<old_nr; i++) {
+		item_p = old_hashed[i].head;
+		while(item_p) {
+			if (list->slab)
+				new_item_p = rsbac_smalloc(list->slab);
+			else
+				new_item_p = rsbac_kmalloc(item_size);
+			if (!new_item_p)
+				goto out_nomem;
+			memcpy(new_item_p, item_p, item_size);
+			new_hash = list->hash_function(&new_item_p[1], new_bits);
+	                new_item_p->next = NULL;
+		        if (!new_hashed[new_hash].head) {
+		        	new_hashed[new_hash].head = new_item_p;
+		                new_hashed[new_hash].tail = new_item_p;
+		                new_hashed[new_hash].count = 1;
+		                new_item_p->prev = NULL;
+		        } else {
+		        	new_item_p->prev = new_hashed[new_hash].tail;
+		        	new_hashed[new_hash].tail->next = new_item_p;
+		        	new_hashed[new_hash].tail = new_item_p;
+		        	new_hashed[new_hash].count++;
+		        }
+			item_p = item_p->next;
+		}
+	}
+	rcu_assign_pointer(list->hashed, new_hashed);
+	list->hash_bits = new_bits;
+	spin_unlock(&list->lock);
+	synchronize_rcu();
+	for(i=0; i<old_nr; i++) {
+		item_p = old_hashed[i].head;
+		while(item_p) {
+			new_item_p = item_p->next;
+			rsbac_sfree(list->slab, item_p);
+			item_p = new_item_p;
+		}
+	}
+	rsbac_kfree(old_hashed);
+	return 0;
+
+out_nomem:
+	spin_unlock(&list->lock);
+	for(i=0; i<new_nr; i++) {
+		item_p = new_hashed[i].head;
+		while(item_p) {
+			new_item_p = item_p->next;
+			rsbac_sfree(list->slab, item_p);
+			item_p = new_item_p;
+		}
+	}
+	rsbac_kfree(new_hashed);
+	return -RSBAC_ENOMEM;
+}
+
+static int do_lol_rehash(struct rsbac_list_lol_reg_item_t *list, __u8 new_bits)
+{
+	struct rsbac_list_lol_hashed_t * old_hashed;
+	struct rsbac_list_lol_hashed_t * new_hashed;
+	int i;
+        struct rsbac_list_lol_item_t *item_p;
+        struct rsbac_list_lol_item_t *new_item_p;
+        u_int new_hash;
+        u_int old_nr;
+        u_int new_nr = 1 << new_bits;
+        u_int item_size;
+
+	new_hashed = rsbac_kmalloc_clear_unlocked(new_nr*sizeof(struct rsbac_list_lol_hashed_t));
+	if(unlikely(!new_hashed)) {
+		return -RSBAC_ENOMEM;
+	}
+	spin_lock(&list->lock);
+	old_nr = 1 << list->hash_bits;
+#ifdef CONFIG_RSBAC_LIST_TRANS
+	for(i=0; i<old_nr; i++)
+		if(list->hashed[i].ta_copied) {
+			spin_unlock(&list->lock);
+			rsbac_kfree(new_hashed);
+			return -RSBAC_EBUSY;
+		}
+#endif
+	old_hashed = list->hashed;
+	item_size = sizeof(*item_p) + list->info.desc_size + list->info.data_size;
+	for(i=0; i<old_nr; i++) {
+		item_p = old_hashed[i].head;
+		while(item_p) {
+			if (list->slab)
+				new_item_p = rsbac_smalloc(list->slab);
+			else
+				new_item_p = rsbac_kmalloc(item_size);
+			if (!new_item_p)
+				goto out_nomem;
+			memcpy(new_item_p, item_p, item_size);
+			new_hash = list->hash_function(&new_item_p[1], new_bits);
+	                new_item_p->next = NULL;
+		        if (!new_hashed[new_hash].head) {
+		        	new_hashed[new_hash].head = new_item_p;
+		                new_hashed[new_hash].tail = new_item_p;
+		                new_hashed[new_hash].count = 1;
+		                new_item_p->prev = NULL;
+		        } else {
+		        	new_item_p->prev = new_hashed[new_hash].tail;
+		        	new_hashed[new_hash].tail->next = new_item_p;
+		        	new_hashed[new_hash].tail = new_item_p;
+		        	new_hashed[new_hash].count++;
+		        }
+			item_p = item_p->next;
+		}
+	}
+	rcu_assign_pointer(list->hashed, new_hashed);
+	list->hash_bits = new_bits;
+	spin_unlock(&list->lock);
+	synchronize_rcu();
+	for(i=0; i<old_nr; i++) {
+		item_p = old_hashed[i].head;
+		while(item_p) {
+			new_item_p = item_p->next;
+			rsbac_sfree(list->slab, item_p);
+			item_p = new_item_p;
+		}
+	}
+	rsbac_kfree(old_hashed);
+	return 0;
+
+out_nomem:
+	spin_unlock(&list->lock);
+	for(i=0; i<new_nr; i++) {
+		item_p = new_hashed[i].head;
+		while(item_p) {
+			new_item_p = item_p->next;
+			rsbac_sfree(list->slab, item_p);
+			item_p = new_item_p;
+		}
+	}
+	rsbac_kfree(new_hashed);
+	return -RSBAC_ENOMEM;
+}
+
+#ifdef CONFIG_RSBAC_AUTO_WRITE
+/* Work through all lists and resize, if allowed and necessary */
+int rsbac_list_auto_rehash(void)
+{
+	int i;
+	int err;
+	struct rsbac_list_reg_item_t *list;
+	struct rsbac_list_lol_reg_item_t *lol_list;
+	long count;
+	u_int nr_rehashed = 0;
+	u_int nr_hashes;
+	int srcu_idx;
+
+	srcu_idx = srcu_read_lock(&reg_list_srcu);
+	list = srcu_dereference(reg_head.head, &reg_list_srcu);
+	while(list) {
+		if((list->flags & RSBAC_LIST_AUTO_HASH_RESIZE)
+		   && (list->hash_bits < rsbac_list_max_hash_bits)) {
+			count = 0;
+			nr_hashes = 1 << list->hash_bits;
+			for (i=0; i<nr_hashes; i++) {
+				if (list->hashed[i].count <= list->max_items_per_hash) {
+					count += list->hashed[i].count;
+				} else {
+					rsbac_printk(KERN_WARNING "rsbac_list_auto_rehash(): list %s on device %02u:%02u has an invalid count %u in hash %u, skipping it\n",
+							list->name, MAJOR(list->device), MINOR(list->device), list->hashed[i].count, i);
+					i = -1;
+					break;
+				}
+			}
+			if (i == -1) {
+				list = list->next;
+				continue;
+			}
+			if(count / (1 << list->hash_bits) > rsbac_list_auto_rehash_trigger) {
+				u_int new_bits;
+
+				new_bits = list->hash_bits;
+				while((new_bits < rsbac_list_max_hash_bits)
+					&& (count / (1 << new_bits) > rsbac_list_auto_rehash_trigger))
+					new_bits++;
+				if(new_bits > rsbac_list_max_hash_bits)
+					new_bits = rsbac_list_max_hash_bits;
+#ifdef CONFIG_RSBAC_DEBUG
+				if(rsbac_debug_auto)
+					rsbac_printk(KERN_DEBUG "rsbac_list_auto_rehash(): changing list %s hash bits on device %02u:%02u from %u to %u, sum of %li items\n",
+						list->name, MAJOR(list->device), MINOR(list->device), list->hash_bits, new_bits, count);
+#endif
+				err = do_rehash(list, new_bits);
+				if(!err)
+					nr_rehashed++;
+				else {
+					rsbac_printk(KERN_WARNING "rsbac_list_auto_rehash(): changing list %s hash bits on device %02u:%02u from %u to %u failed with error %i\n",
+							list->name, MAJOR(list->device), MINOR(list->device), list->hash_bits, new_bits, err);
+				}
+			}
+		}
+		list = srcu_dereference(list->next, &reg_list_srcu);
+	}
+	srcu_read_unlock(&reg_list_srcu, srcu_idx);
+	srcu_idx = srcu_read_lock(&lol_reg_list_srcu);
+	lol_list = srcu_dereference(lol_reg_head.head, &lol_reg_list_srcu);
+	while(lol_list) {
+		if((lol_list->flags & RSBAC_LIST_AUTO_HASH_RESIZE)
+		   && (lol_list->hash_bits < rsbac_list_max_hash_bits)) {
+			count = 0;
+			nr_hashes = 1 << lol_list->hash_bits;
+			for (i=0; i<nr_hashes; i++) {
+				if (lol_list->hashed[i].count <= lol_list->max_items_per_hash) {
+					count += lol_list->hashed[i].count;
+				} else {
+					rsbac_printk(KERN_WARNING "rsbac_list_auto_rehash(): list of lists %s on device %02u:%02u has an invalid count %u in hash %u, skipping it\n",
+							lol_list->name, MAJOR(lol_list->device), MINOR(lol_list->device), lol_list->hashed[i].count, i);
+					i = -1;
+					break;
+				}
+			}
+			if (i == -1) {
+				lol_list = lol_list->next;
+				continue;
+			}
+			if(count / (1 << lol_list->hash_bits) > rsbac_list_auto_rehash_trigger) {
+				u_int new_bits;
+
+				new_bits = lol_list->hash_bits;
+				while((new_bits < rsbac_list_max_hash_bits)
+					&& (count / (1 << new_bits) > rsbac_list_auto_rehash_trigger))
+					new_bits++;
+				if(new_bits > rsbac_list_max_hash_bits)
+					new_bits = rsbac_list_max_hash_bits;
+#ifdef CONFIG_RSBAC_DEBUG
+				if(rsbac_debug_auto)
+					rsbac_printk(KERN_DEBUG "rsbac_list_auto_rehash(): changing list of lists %s hash bits on device %02u:%02u from %u to %u, sum of %li items\n",
+						lol_list->name, MAJOR(lol_list->device), MINOR(lol_list->device), lol_list->hash_bits, new_bits, count);
+#endif
+				err = do_lol_rehash(lol_list, new_bits);
+				if(!err)
+					nr_rehashed++;
+				else {
+					rsbac_printk(KERN_WARNING "rsbac_list_auto_rehash(): changing list of lists %s hash bits on device %02u:%02u from %u to %u failed with error %i\n",
+							lol_list->name, MAJOR(lol_list->device), MINOR(lol_list->device), lol_list->hash_bits, new_bits, err);
+				}
+			}
+		}
+		lol_list = srcu_dereference(lol_list->next, &lol_reg_list_srcu);
+	}
+	srcu_read_unlock(&lol_reg_list_srcu, srcu_idx);
+
+#ifdef CONFIG_RSBAC_DEBUG
+	if(rsbac_debug_auto && (nr_rehashed > 0))
+		rsbac_printk(KERN_DEBUG "rsbac_list_auto_rehash(): %u lists rehashed\n",
+			nr_rehashed);
+#endif
+	return nr_rehashed;
+}
+#endif
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_get_hash_bits);
+#endif
+int rsbac_list_get_hash_bits(rsbac_list_handle_t handle)
+{
+	struct rsbac_list_reg_item_t *list;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+	return list->hash_bits;
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_list_lol_get_hash_bits);
+#endif
+int rsbac_list_lol_get_hash_bits(rsbac_list_handle_t handle)
+{
+	struct rsbac_list_lol_reg_item_t *list;
+
+	if (unlikely(!handle))
+		return -RSBAC_EINVALIDLIST;
+	if (unlikely(!list_initialized))
+		return -RSBAC_ENOTINITIALIZED;
+
+	list = (struct rsbac_list_lol_reg_item_t *) handle;
+	if (unlikely(list->self != list))
+		return -RSBAC_EINVALIDLIST;
+
+	return list->hash_bits;
+}
diff --git a/rsbac/data_structures/mac_data_structures.c b/rsbac/data_structures/mac_data_structures.c
new file mode 100644
index 0000000..366b912
--- /dev/null
+++ b/rsbac/data_structures/mac_data_structures.c
@@ -0,0 +1,1234 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of MAC data structures            */
+/* Author and (c) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 25/Jan/2016                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/srcu.h>
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/mac_data_structures.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/lists.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/getname.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+static struct rsbac_mac_device_list_head_t device_list_head;
+static struct srcu_struct device_list_srcu;
+static struct lock_class_key device_list_lock_class;
+
+static rsbac_list_handle_t process_handle = NULL;
+
+/**************************************************/
+/*       Declarations of external functions       */
+/**************************************************/
+
+rsbac_boolean_t writable(struct super_block *sb_p);
+
+/**************************************************/
+/*       Declarations of internal functions       */
+/**************************************************/
+
+/************************************************* */
+/*               Internal Help functions           */
+/************************************************* */
+
+static u_int nr_fd_hash_bits = RSBAC_MAC_NR_TRU_FD_LIST_HASH_BITS;
+
+static int fd_conv(void *old_desc,
+		void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_old_inode_nr_t));
+	return 0;
+}
+
+static rsbac_list_conv_function_t *fd_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_MAC_FD_OLD_LIST_VERSION:
+		return fd_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int fd_subconv(void *old_desc,
+		void *old_data, void *new_desc, void *new_data)
+{
+	*((rsbac_uid_t *) new_desc) = *((rsbac_old_uid_t *) old_desc);
+	return 0;
+}
+
+static rsbac_list_conv_function_t *fd_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_MAC_FD_OLD_LIST_VERSION:
+		return fd_subconv;
+	default:
+		return NULL;
+	}
+}
+
+
+
+/* mac_register_fd_lists() */
+/* register fd ACL lists for device */
+
+static int mac_register_fd_lists(struct rsbac_mac_device_list_item_t
+				 *device_p, kdev_t kdev)
+{
+	int err = 0;
+	int tmperr;
+	struct rsbac_list_lol_info_t lol_info;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	lol_info.version = RSBAC_MAC_FD_LIST_VERSION;
+	lol_info.key = RSBAC_MAC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_old_inode_nr_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_uid_t);
+	lol_info.subdata_size = 0;	/* rights */
+	lol_info.max_age = 0;
+	tmperr = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+					 &device_p->handle,
+					 &lol_info,
+					 RSBAC_LIST_PERSIST |
+					 RSBAC_LIST_DEF_DATA,
+					 NULL,
+					 NULL,
+					 fd_get_conv, fd_get_subconv,
+					 NULL, NULL,
+					 RSBAC_MAC_FD_FILENAME, kdev,
+					 nr_fd_hash_bits,
+					 rsbac_list_hash_old_fd,
+					 RSBAC_MAC_FD_OLD_FILENAME);
+	if (tmperr) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "mac_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_MAC_FD_FILENAME,
+				     RSBAC_MAJOR(kdev),
+				     RSBAC_MINOR(kdev),
+				     get_error_name(tmp, tmperr));
+			rsbac_kfree(tmp);
+		}
+		err = tmperr;
+	}
+	return err;
+}
+
+/* mac_detach_fd_lists() */
+/* detach from fd MAC lists for device */
+
+static int mac_detach_fd_lists(struct rsbac_mac_device_list_item_t
+			       *device_p)
+{
+	int err = 0;
+
+	if (!device_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	err = rsbac_list_lol_detach(&device_p->handle,
+				       RSBAC_MAC_LIST_KEY);
+	if (err) {
+		char *tmp;
+
+		tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "mac_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
+				     RSBAC_MAC_FD_FILENAME,
+				     RSBAC_MAJOR(device_p->id),
+				     RSBAC_MINOR(device_p->id),
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+	return err;
+}
+
+/************************************************************************** */
+/* The lookup functions return NULL, if the item is not found, and a        */
+/* pointer to the item otherwise.                                           */
+
+/* first the device item lookup */
+static struct rsbac_mac_device_list_item_t *lookup_device(kdev_t kdev)
+{
+	struct rsbac_mac_device_list_item_t *curr = srcu_dereference(device_list_head.curr, &device_list_srcu);
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!(curr && (RSBAC_MAJOR(curr->id) == RSBAC_MAJOR(kdev))
+	      && (RSBAC_MINOR(curr->id) == RSBAC_MINOR(kdev))
+	    )
+	    ) {
+		curr = srcu_dereference(device_list_head.head, &device_list_srcu);
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = srcu_dereference(curr->next, &device_list_srcu);
+		}
+		if (curr)
+			device_list_head.curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+static struct rsbac_mac_device_list_item_t *lookup_device_locked(kdev_t kdev)
+{
+	struct rsbac_mac_device_list_item_t *curr = device_list_head.curr;
+
+	/* if there is no current item or it is not the right one, search... */
+	if (!(curr && (RSBAC_MAJOR(curr->id) == RSBAC_MAJOR(kdev))
+	      && (RSBAC_MINOR(curr->id) == RSBAC_MINOR(kdev))
+	    )
+	    ) {
+		curr = device_list_head.head;
+		while (curr
+		       && ((RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
+			   || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
+		       )
+		    ) {
+			curr = curr->next;
+		}
+		if (curr)
+			device_list_head.curr = curr;
+	}
+	/* it is the current item -> return it */
+	return curr;
+}
+
+/************************************************************************** */
+/* The add_item() functions add an item to the list, set head.curr to it,   */
+/* and return a pointer to the item.                                        */
+/* These functions will NOT check, if there is already an item under the    */
+/* same ID! If this happens, the lookup functions will return the old item! */
+/* All list manipulation is protected by rw-spinlocks to prevent inconsistency */
+/* and undefined behaviour in other concurrent functions.                   */
+
+/* Create a device item without adding to list. No locking needed. */
+static struct rsbac_mac_device_list_item_t
+*create_device_item(kdev_t kdev)
+{
+	struct rsbac_mac_device_list_item_t *new_item_p;
+
+	/* allocate memory for new device, return NULL, if failed */
+	if (!(new_item_p = (struct rsbac_mac_device_list_item_t *)
+	      rsbac_kmalloc(sizeof(*new_item_p))))
+		return NULL;
+
+	new_item_p->id = kdev;
+	new_item_p->mount_count = 1;
+
+	/* init file/dir sublists */
+	new_item_p->handle = NULL;
+	return new_item_p;
+}
+
+/* Add an existing device item to list. Locking needed. */
+static struct rsbac_mac_device_list_item_t
+*add_device_item(struct rsbac_mac_device_list_item_t *device_p)
+{
+	if (!device_p)
+		return NULL;
+
+	/* add new device to device list */
+	if (!device_list_head.head) {	/* first device */
+		device_p->prev = NULL;
+		device_p->next = NULL;
+		rcu_assign_pointer(device_list_head.head, device_p);
+		rcu_assign_pointer(device_list_head.tail, device_p);
+		rcu_assign_pointer(device_list_head.curr, device_p);
+		device_list_head.count = 1;
+	} else {		/* there is another device -> hang to tail */
+		device_p->prev = device_list_head.tail;
+		device_p->next = NULL;
+		rcu_assign_pointer(device_list_head.tail->next, device_p);
+		rcu_assign_pointer(device_list_head.tail, device_p);
+		rcu_assign_pointer(device_list_head.curr, device_p);
+		device_list_head.count++;
+	}
+	return device_p;
+}
+
+/************************************************************************** */
+/* The remove_item() functions remove an item from the list. If this item   */
+/* is head, tail or curr, these pointers are set accordingly.               */
+/* To speed up removing several subsequent items, curr is set to the next   */
+/* item, if possible.                                                       */
+/* If the item is not found, nothing is done.                               */
+
+static void clear_device_item(struct rsbac_mac_device_list_item_t *item_p)
+{
+	if (!item_p)
+		return;
+
+	/* First deregister lists... */
+	mac_detach_fd_lists(item_p);
+	rsbac_kfree(item_p);
+}
+
+static void remove_device_item(struct rsbac_mac_device_list_item_t *item_p)
+{
+	if (item_p) {	/* ok, item was found */
+		if (device_list_head.head == item_p) {	/* item is head */
+			if (device_list_head.tail == item_p) {	/* item is head and tail = only item -> list will be empty */
+				rcu_assign_pointer(device_list_head.head, NULL);
+				rcu_assign_pointer(device_list_head.tail, NULL);
+			} else {	/* item is head, but not tail -> next item becomes head */
+				rcu_assign_pointer(item_p->next->prev, NULL);
+				rcu_assign_pointer(device_list_head.head, item_p->next);
+			}
+		} else {	/* item is not head */
+			if (device_list_head.tail == item_p) {	/*item is not head, but tail -> previous item becomes tail */
+				rcu_assign_pointer(item_p->prev->next, NULL);
+				rcu_assign_pointer(device_list_head.tail, item_p->prev);
+			} else {	/* item is neither head nor tail -> item is cut out */
+				rcu_assign_pointer(item_p->prev->next, item_p->next);
+				rcu_assign_pointer(item_p->next->prev, item_p->prev);
+			}
+		}
+
+		/* curr is no longer valid -> reset.                              */
+		device_list_head.curr = NULL;
+		/* adjust counter */
+		device_list_head.count--;
+	}
+}
+
+/************************************************************************** */
+/* The copy_fp_tru_set_item() function copies a file cap set to a process   */
+/* cap set */
+
+static int copy_fp_tru_set_item(struct rsbac_mac_device_list_item_t
+				*device_p, rsbac_mac_file_t file,
+				rsbac_pid_t pid)
+{
+	rsbac_uid_t *tru_item_p;
+	rsbac_time_t *ttl_p;
+	int i;
+	long count;
+	enum rsbac_target_t target = T_FILE;
+	union rsbac_target_id_t tid;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	rsbac_list_lol_remove(process_handle, &pid);
+	count = rsbac_list_lol_get_all_subdesc_ttl(device_p->handle,
+					       &inode_nr,
+					       (void **) &tru_item_p,
+					       &ttl_p);
+	if (!count || (count == -RSBAC_ENOTFOUND)
+	    ) {
+		tid.file = file;
+		if (!rsbac_get_parent(target, tid, &target, &tid)) {
+		        inode_nr = tid.file.inode;
+			count = rsbac_list_lol_get_all_subdesc_ttl(device_p->handle,
+							       &inode_nr,
+							       (void **)
+							       &tru_item_p,
+							       &ttl_p);
+		}
+	}
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(process_handle,
+						  ttl_p[i],
+						  &pid,
+						  &tru_item_p[i], NULL);
+		}
+		rsbac_kfree(tru_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if ((count < 0)
+		    && (count != -RSBAC_ENOTFOUND)
+		    )
+			return count;
+	}
+
+	return 0;
+}				/* end of copy_fp_tru_set_item() */
+
+/************************************************************************** */
+/* The copy_pp_tru_set_item() function copies a process cap set to another  */
+
+static int copy_pp_tru_set_item_handle(rsbac_list_handle_t handle,
+				       rsbac_pid_t old_pid,
+				       rsbac_pid_t new_pid)
+{
+	rsbac_uid_t *tru_item_p;
+	rsbac_time_t *ttl_p;
+	int i;
+	long count;
+
+	rsbac_list_lol_remove(handle, &new_pid);
+	count = rsbac_list_lol_get_all_subdesc_ttl(handle,
+						   &old_pid,
+						   (void **) &tru_item_p,
+						   &ttl_p);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			rsbac_list_lol_subadd_ttl(handle,
+						  ttl_p[i],
+						  &new_pid,
+						  &tru_item_p[i], NULL);
+		}
+		rsbac_kfree(tru_item_p);
+		rsbac_kfree(ttl_p);
+	} else {
+		if (count < 0)
+			return count;
+	}
+	return 0;
+}
+
+static int copy_pp_tru_set_item(rsbac_pid_t old_pid, rsbac_pid_t new_pid)
+{
+	return copy_pp_tru_set_item_handle(process_handle, old_pid,
+					   new_pid);
+}				/* end of copy_pp_tru_set_item() */
+
+/************************************************* */
+/*               proc functions                    */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+static int
+mac_devices_proc_show(struct seq_file *m, void *v)
+{
+	struct rsbac_mac_device_list_item_t *device_p;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized())
+		return -ENOSYS;
+
+	seq_printf(m, "%u RSBAC MAC Devices\n-------------------\n",
+		    device_list_head.count);
+
+	/* wait for read access to device_list_head */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	/* OK, go on */
+	for (device_p = srcu_dereference(device_list_head.head, &device_list_srcu); device_p;
+	     device_p = srcu_dereference(device_p->next, &device_list_srcu)) {
+		seq_printf(m,
+			    "%02u:%02u with mount_count = %u\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id),
+			    device_p->mount_count);
+	}
+
+	/* free access to device_list_head */
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int mac_devices_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mac_devices_proc_show, NULL);
+}
+
+static const struct file_operations mac_devices_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mac_devices_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct proc_dir_entry *mac_devices;
+
+static int
+stats_mac_proc_show(struct seq_file *m, void *v)
+{
+	struct rsbac_mac_device_list_item_t *device_p;
+	int srcu_idx;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "stats_mac_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_mac, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "MAC Status\n----------\n");
+
+	seq_printf(m,
+		    "%lu process trusted user set items, sum of %lu members\n",
+		    rsbac_list_lol_count(process_handle),
+		    rsbac_list_lol_all_subcount(process_handle));
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = srcu_dereference(device_list_head.head, &device_list_srcu);
+	while (device_p) {
+		/* reset counters */
+		seq_printf(m,
+			    "device %02u:%02u has %lu file trusted user set items, sum of %lu members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id),
+			    rsbac_list_lol_count(device_p->handle),
+			    rsbac_list_lol_all_subcount(device_p->handle));
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	/* unprotect device list */
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int stats_mac_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_mac_proc_show, NULL);
+}
+
+static const struct file_operations stats_mac_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= stats_mac_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct proc_dir_entry *stats_mac;
+
+static int
+mac_trulist_proc_show(struct seq_file *m, void *v)
+{
+	u_int count = 0;
+	u_int member_count = 0;
+	u_long all_member_count;
+	int i, j;
+	struct rsbac_mac_device_list_item_t *device_p;
+	rsbac_pid_t *p_list;
+	rsbac_old_inode_nr_t *f_list;
+	rsbac_uid_t *tru_list;
+	int srcu_idx;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "mac_trulist_proc_info(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_mac, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m,
+		    "MAC Trusted User Lists\n---------------------\n");
+
+	/* protect process cap set list */
+	seq_printf(m,
+		    "Process trusted user sets:\nset-id  count   members");
+
+	all_member_count = 0;
+	count = rsbac_list_lol_get_all_desc(process_handle,
+					    (void **) &p_list);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			member_count =
+			    rsbac_list_lol_get_all_subdesc(process_handle,
+							   &p_list[i],
+							   (void **)
+							   &tru_list);
+			seq_printf(m, "\n %u\t%u\t", pid_vnr(p_list[i]),
+				    member_count);
+			if (member_count > 0) {
+				for (j = 0; j < member_count; j++) {
+					if (RSBAC_UID_SET(tru_list[j]))
+						seq_printf(m, "%u/%u ",
+						       RSBAC_UID_SET(tru_list[j]),
+						       RSBAC_UID_NUM(tru_list[j]));
+					else
+						seq_printf(m, "%u ",
+						       RSBAC_UID_NUM(tru_list[j]));
+				}
+				rsbac_kfree(tru_list);
+				all_member_count += member_count;
+			}
+		}
+		rsbac_kfree(p_list);
+	}
+	seq_printf(m,
+		    "\n%u process trusted user set items, sum of %lu members\n",
+		    count, all_member_count);
+
+	seq_printf(m,
+		    "\nFile trusted user sets:\nset-id  count   members");
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = srcu_dereference(device_list_head.head, &device_list_srcu);
+	while (device_p) {
+		/* reset counters */
+		all_member_count = 0;
+		count = rsbac_list_lol_get_all_desc(device_p->handle,
+							(void **) &f_list);
+		if (count > 0) {
+			for (i = 0; i < count; i++) {
+				member_count =
+				    rsbac_list_lol_get_all_subdesc
+				    (device_p->handle,
+				     &f_list[i],
+				     (void **) &tru_list);
+				    seq_printf(m,
+					    "\n %u\t%u\t",
+					    f_list[i],
+					    member_count);
+				if (member_count > 0) {
+					for (j = 0;
+					     j < member_count;
+					     j++) {
+					        if (RSBAC_UID_SET(tru_list[j]))
+						  seq_printf(m,
+							    "%u/%u ",
+							    RSBAC_UID_SET(tru_list[j]),
+							    RSBAC_UID_NUM(tru_list[j]));
+					        else
+						    seq_printf(m,
+							    "%u ",
+							    RSBAC_UID_NUM(tru_list[j]));
+					}
+					rsbac_kfree(tru_list);
+					all_member_count +=
+					    member_count;
+				}
+			}
+			rsbac_kfree(f_list);
+		}
+		seq_printf(m,
+			    "\ndevice %02u:%02u has %u file trusted user set items, sum of %lu members\n",
+			    RSBAC_MAJOR(device_p->id),
+			    RSBAC_MINOR(device_p->id), count,
+			    all_member_count);
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	/* unprotect device list */
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	return 0;
+}
+
+static int mac_trulist_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mac_trulist_proc_show, NULL);
+}
+
+static const struct file_operations mac_trulist_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mac_trulist_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct proc_dir_entry *mac_trulist;
+
+#endif				/* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */
+
+/************************************************* */
+/*               Init functions                    */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac/error.h.                 */
+
+/************************************************************************** */
+/* Initialization of all MAC data structures. After this call, all MAC    */
+/* data is kept in memory for performance reasons, but is written to disk   */
+/* on every change. */
+
+/* Because there can be no access to aci data structures before init,       */
+/* rsbac_init_mac() will initialize all rw-spinlocks to unlocked.          */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_mac(void)
+#else
+int __init rsbac_init_mac(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_mac_device_list_item_t *device_p = NULL;
+	struct rsbac_list_lol_info_t lol_info;
+
+	if (rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_init_mac(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+
+	rsbac_printk(KERN_INFO "rsbac_init_mac(): Initializing RSBAC: MAC subsystem\n");
+
+	lol_info.version = RSBAC_MAC_P_LIST_VERSION;
+	lol_info.key = RSBAC_MAC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_pid_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_uid_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register(RSBAC_LIST_VERSION,
+				      &process_handle,
+				      &lol_info,
+				      RSBAC_LIST_DEF_DATA,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      NULL,
+				      RSBAC_MAC_P_LIST_NAME,
+				      RSBAC_AUTO_DEV);
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_mac(): Registering MAC process trusted user list failed with error %s\n",
+				     get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+
+	/* Init FD lists */
+	spin_lock_init(&device_list_head.lock);
+	init_srcu_struct(&device_list_srcu);
+	lockdep_set_class(&device_list_head.lock, &device_list_lock_class);
+	device_list_head.head = NULL;
+	device_list_head.tail = NULL;
+	device_list_head.curr = NULL;
+	device_list_head.count = 0;
+
+	/* read all data */
+	rsbac_pr_debug(ds_mac, "rsbac_init_mac(): Registering FD lists\n");
+	device_p = create_device_item(rsbac_root_dev);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_init_mac(): Could not add device!\n");
+		return -RSBAC_ECOULDNOTADDDEVICE;
+	}
+	if ((err = mac_register_fd_lists(device_p, rsbac_root_dev))) {
+		char tmp[RSBAC_MAXNAMELEN];
+
+		rsbac_printk(KERN_WARNING "rsbac_init_mac(): File/Dir trusted user set registration failed for dev %02u:%02u, err %s!\n",
+			     RSBAC_MAJOR(rsbac_root_dev),
+			     RSBAC_MINOR(rsbac_root_dev),
+			     get_error_name(tmp, err));
+	}
+	/* wait for write access to device_list_head */
+	spin_lock(&device_list_head.lock);
+	device_p = add_device_item(device_p);
+	/* device was added, allow access */
+	spin_unlock(&device_list_head.lock);
+	if (!device_p) {
+		rsbac_printk(KERN_CRIT
+			     "rsbac_init_mac(): Could not add device!\n");
+		return -RSBAC_ECOULDNOTADDDEVICE;
+	}
+#if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
+	mac_devices = proc_create("mac_devices",
+			S_IFREG | S_IRUGO | S_IWUGO,
+			proc_rsbac_root_p, &mac_devices_proc_fops);
+	stats_mac = proc_create("stats_mac",
+			S_IFREG | S_IRUGO,
+			proc_rsbac_root_p, &stats_mac_proc_fops);
+	mac_trulist = proc_create("mac_trusted",
+			S_IFREG | S_IRUGO,
+			proc_rsbac_root_p, &mac_trulist_proc_fops);
+#endif
+
+	rsbac_pr_debug(aef_mac, "Ready.\n");
+	return err;
+}
+
+int rsbac_mount_mac(kdev_t kdev)
+{
+	int err = 0;
+	struct rsbac_mac_device_list_item_t *device_p;
+	struct rsbac_mac_device_list_item_t *new_device_p;
+	int srcu_idx;
+
+	rsbac_pr_debug(aef_mac, "mounting device %02u:%02u\n",
+		       RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(kdev);
+	/* repeated mount? */
+	if (device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mount_mac: repeated mount %u of device %02u:%02u\n",
+			     device_p->mount_count, RSBAC_MAJOR(kdev),
+			     RSBAC_MINOR(kdev));
+		device_p->mount_count++;
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return 0;
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+
+	new_device_p = create_device_item(kdev);
+	if (!new_device_p)
+		return -RSBAC_ECOULDNOTADDDEVICE;
+
+	/* register lists */
+	if ((err = mac_register_fd_lists(new_device_p, kdev))) {
+		char tmp[RSBAC_MAXNAMELEN];
+
+		rsbac_printk(KERN_WARNING "rsbac_mount_mac(): File/Dir ACL registration failed for dev %02u:%02u, err %s!\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev),
+			     get_error_name(tmp, err));
+	}
+
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	/* make sure to only add, if this device item has not been added in the meantime */
+	device_p = lookup_device(kdev);
+	if (device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mount_mac(): mount race for device %02u:%02u detected!\n",
+			     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+		device_p->mount_count++;
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		clear_device_item(new_device_p);
+	} else {
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		spin_lock(&device_list_head.lock);
+		device_p = add_device_item(new_device_p);
+		spin_unlock(&device_list_head.lock);
+		if (!device_p) {
+			rsbac_printk(KERN_WARNING "rsbac_mount_mac: adding device %02u:%02u failed!\n",
+				     RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+			clear_device_item(new_device_p);
+			err = -RSBAC_ECOULDNOTADDDEVICE;
+		}
+	}
+	return err;
+}
+
+/* When umounting a device, its file lists must be removed. */
+
+int rsbac_umount_mac(kdev_t kdev)
+{
+	struct rsbac_mac_device_list_item_t *device_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_umount(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_mac, "umounting device %02u:%02u\n",
+		       RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
+	/* sync of attribute lists was done in rsbac_umount */
+	spin_lock(&device_list_head.lock);
+	/* OK, nobody else is working on it... */
+	device_p = lookup_device_locked(kdev);
+	if (device_p) {
+		if (device_p->mount_count == 1) {
+			remove_device_item(device_p);
+			spin_unlock(&device_list_head.lock);
+			synchronize_srcu(&device_list_srcu);
+			clear_device_item(device_p);
+		} else {
+			if (device_p->mount_count > 1) {
+				device_p->mount_count--;
+			} else {
+				rsbac_printk(KERN_WARNING "rsbac_mount_mac: device %02u:%02u has mount_count < 1!\n",
+					     RSBAC_MAJOR(kdev),
+					     RSBAC_MINOR(kdev));
+			}
+			spin_unlock(&device_list_head.lock);
+		}
+	} else
+		spin_unlock(&device_list_head.lock);
+	return 0;
+}
+
+/***************************************************/
+/* We also need some status information...         */
+
+int rsbac_stats_mac(void)
+{
+	struct rsbac_mac_device_list_item_t *device_p;
+	int srcu_idx;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_stats_mac(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	rsbac_pr_debug(aef_mac, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	rsbac_printk(KERN_INFO "MAC Status\n----------\n");
+
+	rsbac_printk(KERN_INFO "%lu process trusted user set items, sum of %lu members\n",
+		     rsbac_list_lol_count(process_handle),
+		     rsbac_list_lol_all_subcount(process_handle));
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = srcu_dereference(device_list_head.head, &device_list_srcu);
+	while (device_p) {
+		rsbac_printk(KERN_INFO "device %02u:%02u has %u file trusted user set items, sum of %u members\n",
+			     RSBAC_MAJOR(device_p->id),
+			     RSBAC_MINOR(device_p->id),
+			     rsbac_list_lol_count(device_p->handle),
+			     rsbac_list_lol_all_subcount(device_p->handle));
+		device_p = srcu_dereference(device_p->next, &device_list_srcu);
+	}
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return 0;
+}
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* All these procedures handle the rw-spinlocks to protect the targets during */
+/* access.                                                                  */
+/* Trying to access a never created or removed set returns an error! */
+
+/* rsbac_mac_add_to_truset */
+/* Add a set member to a set sublist. Set behaviour: also returns success, */
+/* if member was already in set! */
+
+int rsbac_mac_add_to_p_truset(rsbac_list_ta_number_t ta_number,
+			      rsbac_pid_t pid,
+			      rsbac_uid_t member, rsbac_time_t ttl)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_add_to_p_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_add_to_p_truset(): called from interrupt!\n");
+	}
+	return rsbac_ta_list_lol_subadd_ttl(ta_number, process_handle, ttl,
+					    &pid, &member, NULL);
+}
+
+int rsbac_mac_add_to_f_truset(rsbac_list_ta_number_t ta_number,
+			      rsbac_mac_file_t file,
+			      rsbac_uid_t member, rsbac_time_t ttl)
+{
+	int err = 0;
+	struct rsbac_mac_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_add_to_f_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_add_to_f_truset(): called from interrupt!\n");
+	}
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		rsbac_printk(KERN_WARNING "rsbac_mac_add_to_f_truset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		return -RSBAC_EINVALIDDEV;
+	}
+
+	err = rsbac_ta_list_lol_subadd_ttl(ta_number,
+					   device_p->handle,
+					   ttl, &inode_nr, &member,
+					   NULL);
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+/* rsbac_mac_remove_from_truset */
+/* Remove a set member from a sublist. Set behaviour: Returns no error, if */
+/* member is not in list.                                                  */
+
+int rsbac_mac_remove_from_p_truset(rsbac_list_ta_number_t ta_number,
+				   rsbac_pid_t pid, rsbac_uid_t member)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_p_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_p_truset(): called from interrupt!\n");
+	}
+	return rsbac_ta_list_lol_subremove(ta_number, process_handle, &pid,
+					   &member);
+}
+
+int rsbac_mac_remove_from_f_truset(rsbac_list_ta_number_t ta_number,
+				   rsbac_mac_file_t file,
+				   rsbac_uid_t member)
+{
+	int err = 0;
+	struct rsbac_mac_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_f_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_f_truset(): called from interrupt!\n");
+	}
+
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_f_truset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	err = rsbac_ta_list_lol_subremove(ta_number,
+					  device_p->handle,
+					  &inode_nr, &member);
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+/* rsbac_mac_clear_truset */
+/* Remove all set members from a sublist. Set behaviour: Returns no error, */
+/* if list is empty.                                                       */
+
+int rsbac_mac_clear_p_truset(rsbac_list_ta_number_t ta_number,
+			     rsbac_pid_t pid)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_clear_p_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_clear_p_truset(): called from interrupt!\n");
+	}
+	return rsbac_ta_list_lol_remove(ta_number, process_handle, &pid);
+}
+
+int rsbac_mac_clear_f_truset(rsbac_list_ta_number_t ta_number,
+			     rsbac_mac_file_t file)
+{
+	int err = 0;
+	struct rsbac_mac_device_list_item_t *device_p;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_clear_f_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_clear_f_truset(): called from interrupt!\n");
+	}
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_clear_f_truset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	err = rsbac_ta_list_lol_remove(ta_number,
+				     device_p->handle,
+				     &inode_nr);
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+/* rsbac_mac_truset_member */
+/* Return truth value, whether member is in set */
+
+rsbac_boolean_t rsbac_mac_p_truset_member(rsbac_pid_t pid,
+					  rsbac_uid_t member)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_p_truset_member(): RSBAC not initialized\n");
+		return FALSE;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_p_truset_member(): called from interrupt!\n");
+	}
+	if (rsbac_list_lol_subexist(process_handle, &pid, &member))
+		return TRUE;
+	member = RSBAC_ALL_USERS;
+	return rsbac_list_lol_subexist(process_handle, &pid, &member);
+}
+
+/* rsbac_mac_remove_truset */
+/* Remove a full set. For cleanup, if object is deleted. */
+/* To empty an existing set use rsbac_mac_clear_truset. */
+
+int rsbac_mac_remove_p_trusets(rsbac_pid_t pid)
+{
+	return rsbac_mac_clear_p_truset(FALSE, pid);
+}
+
+int rsbac_mac_remove_f_trusets(rsbac_mac_file_t file)
+{
+	return rsbac_mac_clear_f_truset(FALSE, file);
+}
+
+int rsbac_mac_copy_fp_truset(rsbac_mac_file_t file,
+			     rsbac_pid_t p_tru_set_id)
+{
+	struct rsbac_mac_device_list_item_t *device_p;
+	int err = 0;
+	int srcu_idx;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_copy_fp_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_copy_fp_truset(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_mac, "Copying file cap set data to process cap set\n");
+*/
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_copy_fp_truset(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	/* call the copy function */
+	err = copy_fp_tru_set_item(device_p, file, p_tru_set_id);
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return err;
+}
+
+int rsbac_mac_copy_pp_truset(rsbac_pid_t old_p_set_id,
+			     rsbac_pid_t new_p_set_id)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_copy_pp_truset(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_copy_pp_truset(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_mac, "Copying process cap set data to process cap set\n");
+*/
+	/* call the copy function */
+	return copy_pp_tru_set_item(old_p_set_id, new_p_set_id);
+}
+
+int rsbac_mac_get_f_trulist(rsbac_list_ta_number_t ta_number,
+			    rsbac_mac_file_t file,
+			    rsbac_uid_t ** trulist_p,
+			    rsbac_time_t ** ttllist_p)
+{
+	struct rsbac_mac_device_list_item_t *device_p;
+	long count;
+	int srcu_idx;
+	rsbac_old_inode_nr_t inode_nr = file.inode;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_get_f_trulist(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_get_f_trulist(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_mac, "Getting file/dir trusted user set list\n");
+*/
+	/* protect device list */
+	srcu_idx = srcu_read_lock(&device_list_srcu);
+	device_p = lookup_device(file.device);
+	if (!device_p) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_get_f_trulist(): invalid device %02u:%02u!\n",
+			     RSBAC_MAJOR(file.device),
+			     RSBAC_MINOR(file.device));
+		srcu_read_unlock(&device_list_srcu, srcu_idx);
+		return -RSBAC_EINVALIDDEV;
+	}
+	count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+						      device_p->handle,
+						      &inode_nr,
+						      (void **) trulist_p,
+						      ttllist_p);
+	srcu_read_unlock(&device_list_srcu, srcu_idx);
+	return count;
+}
+
+int rsbac_mac_get_p_trulist(rsbac_list_ta_number_t ta_number,
+			    rsbac_pid_t pid,
+			    rsbac_uid_t ** trulist_p,
+			    rsbac_time_t ** ttllist_p)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_get_p_trulist(): RSBAC not initialized\n");
+		return -RSBAC_ENOTINITIALIZED;
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_mac_get_p_trulist(): called from interrupt!\n");
+	}
+/*
+	rsbac_pr_debug(ds_mac, "Getting process trusted user set list\n");
+*/
+	return rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+						     process_handle,
+						     &pid,
+						     (void **) trulist_p,
+						     ttllist_p);
+}
diff --git a/rsbac/data_structures/rc_data_structures.c b/rsbac/data_structures/rc_data_structures.c
new file mode 100644
index 0000000..e98cdd5
--- /dev/null
+++ b/rsbac/data_structures/rc_data_structures.c
@@ -0,0 +1,4437 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of RC data structures              */
+/* Author and (C) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 07/Jan/2016                        */
+/*************************************************** */
+
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/rc_types.h>
+#include <rsbac/rc_data_structures.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/fs.h>
+#include <rsbac/adf.h>
+#include <rsbac/acl.h>
+#include <rsbac/getname.h>
+#include <rsbac/rc_getname.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/request_groups.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+/* The following global variables are needed for access to RC data.         */
+
+static rsbac_list_handle_t role_handle = NULL;
+static rsbac_list_handle_t role_rc_handle = NULL;
+static rsbac_list_handle_t role_adr_handle = NULL;
+static rsbac_list_handle_t role_asr_handle = NULL;
+static rsbac_list_handle_t role_dfdc_handle = NULL;
+static rsbac_list_handle_t role_tcfd_handle = NULL;
+static rsbac_list_handle_t role_tcdv_handle = NULL;
+static rsbac_list_handle_t role_tcus_handle = NULL;
+static rsbac_list_handle_t role_tcpr_handle = NULL;
+static rsbac_list_handle_t role_tcip_handle = NULL;
+static rsbac_list_handle_t role_tcsc_handle = NULL;
+static rsbac_list_handle_t role_tcgr_handle = NULL;
+static rsbac_list_handle_t role_tcnd_handle = NULL;
+static rsbac_list_handle_t role_tcnt_handle = NULL;
+static rsbac_list_handle_t role_tcno_handle = NULL;
+
+static rsbac_list_handle_t type_fd_handle = NULL;
+static rsbac_list_handle_t type_dev_handle = NULL;
+static rsbac_list_handle_t type_ipc_handle = NULL;
+static rsbac_list_handle_t type_user_handle = NULL;
+static rsbac_list_handle_t type_process_handle = NULL;
+static rsbac_list_handle_t type_group_handle = NULL;
+static rsbac_list_handle_t type_netdev_handle = NULL;
+static rsbac_list_handle_t type_nettemp_handle = NULL;
+static rsbac_list_handle_t type_netobj_handle = NULL;
+
+/**************************************************/
+/*       Declarations of external functions       */
+/**************************************************/
+
+/**************************************************/
+/*       Declarations of internal functions       */
+/**************************************************/
+
+/* As some function use later defined functions, we declare those here.   */
+
+/************************************************* */
+/*               Internal Help functions           */
+/************************************************* */
+
+/* nr_hashes is always 2^n, no matter what the macros say */
+/* We ignore the lowest bit */
+static u_int nr_role_hash_bits = RSBAC_RC_NR_ROLE_LIST_HASH_BITS;
+static u_int nr_type_hash_bits = RSBAC_RC_NR_TYPE_LIST_HASH_BITS;
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int role_conv(
+#else
+static int __init role_conv(
+#endif
+				   void *old_desc,
+				   void *old_data,
+				   void *new_desc, void *new_data)
+{
+	struct rsbac_rc_role_entry_t *new = new_data;
+	struct rsbac_rc_old_role_entry_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_rc_role_id_t));
+	new->admin_type = old->admin_type;
+	memcpy(new->name, old->name, RSBAC_RC_NAME_LEN);
+	new->def_fd_create_type = old->def_fd_create_type;
+	new->def_user_create_type = old->def_user_create_type;
+	new->def_process_create_type = old->def_process_create_type;
+	new->def_process_chown_type = old->def_process_chown_type;
+	new->def_process_execute_type = old->def_process_execute_type;
+	new->def_ipc_create_type = old->def_ipc_create_type;
+	new->def_group_create_type = RSBAC_RC_GENERAL_TYPE;
+	new->def_unixsock_create_type = RC_type_use_fd;
+	new->boot_role = old->boot_role;
+	new->req_reauth = old->req_reauth;
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int old_role_conv(
+#else
+static int __init old_role_conv(
+#endif
+				   void *old_desc,
+				   void *old_data,
+				   void *new_desc, void *new_data)
+{
+	struct rsbac_rc_role_entry_t *new = new_data;
+	struct rsbac_rc_old_role_entry_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_rc_role_id_t));
+	new->admin_type = old->admin_type;
+	memcpy(new->name, old->name, RSBAC_RC_NAME_LEN);
+	new->def_fd_create_type = old->def_fd_create_type;
+	new->def_user_create_type = old->def_user_create_type;
+	new->def_process_create_type = old->def_process_create_type;
+	new->def_process_chown_type = old->def_process_chown_type;
+	new->def_process_execute_type = old->def_process_execute_type;
+	new->def_ipc_create_type = old->def_ipc_create_type;
+	new->def_group_create_type = RSBAC_RC_GENERAL_TYPE;
+	new->def_unixsock_create_type = RC_type_use_fd;
+	new->boot_role = old->boot_role;
+	new->req_reauth = FALSE;
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int old_old_role_conv(
+#else
+static int __init old_old_role_conv(
+#endif
+				       void *old_desc,
+				       void *old_data,
+				       void *new_desc, void *new_data)
+{
+	struct rsbac_rc_role_entry_t *new = new_data;
+	struct rsbac_rc_old_role_entry_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_rc_role_id_t));
+	new->admin_type = old->admin_type;
+	memcpy(new->name, old->name, RSBAC_RC_NAME_LEN);
+	new->def_fd_create_type = old->def_fd_create_type;
+	new->def_user_create_type = old->def_user_create_type;
+	new->def_process_create_type = old->def_process_create_type;
+	new->def_process_chown_type = old->def_process_chown_type;
+	new->def_process_execute_type = old->def_process_execute_type;
+	new->def_ipc_create_type = old->def_ipc_create_type;
+	new->def_group_create_type = RSBAC_RC_GENERAL_TYPE;
+	new->def_unixsock_create_type = RC_type_use_fd;
+	new->boot_role = old->boot_role;
+	new->req_reauth = FALSE;
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int old_old_old_role_conv(
+#else
+static int __init old_old_old_role_conv(
+#endif
+					   void *old_desc,
+					   void *old_data,
+					   void *new_desc, void *new_data)
+{
+	struct rsbac_rc_role_entry_t *new = new_data;
+	struct rsbac_rc_old_role_entry_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_rc_role_id_t));
+	new->admin_type = old->admin_type;
+	memcpy(new->name, old->name, RSBAC_RC_NAME_LEN);
+	new->def_fd_create_type = old->def_fd_create_type;
+	new->def_user_create_type = RSBAC_RC_GENERAL_TYPE;
+	new->def_process_create_type = old->def_process_create_type;
+	new->def_process_chown_type = old->def_process_chown_type;
+	new->def_process_execute_type = old->def_process_execute_type;
+	new->def_ipc_create_type = old->def_ipc_create_type;
+	new->def_group_create_type = RSBAC_RC_GENERAL_TYPE;
+	new->def_unixsock_create_type = RC_type_use_fd;
+	new->boot_role = FALSE;
+	new->req_reauth = FALSE;
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static rsbac_list_conv_function_t *role_get_conv(rsbac_version_t
+						 old_version)
+#else
+static rsbac_list_conv_function_t *__init role_get_conv(rsbac_version_t
+							old_version)
+#endif
+{
+	switch (old_version) {
+	case RSBAC_RC_ROLE_OLD_LIST_VERSION:
+		return role_conv;
+	case RSBAC_RC_ROLE_OLD_OLD_LIST_VERSION:
+		return old_role_conv;
+	case RSBAC_RC_ROLE_OLD_OLD_OLD_LIST_VERSION:
+		return old_old_role_conv;
+	case RSBAC_RC_ROLE_OLD_OLD_OLD_OLD_LIST_VERSION:
+		return old_old_old_role_conv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int tc_subconv(
+#else
+static int __init tc_subconv(
+#endif
+				    void *old_desc,
+				    void *old_data,
+				    void *new_desc, void *new_data)
+{
+	rsbac_rc_rights_vector_t *new = new_data;
+	rsbac_rc_rights_vector_t *old = old_data;
+
+	memcpy(new_desc, old_desc, sizeof(rsbac_rc_type_id_t));
+	*new = (*old & RSBAC_ALL_REQUEST_VECTOR)
+	    | ((*old & ~(RSBAC_ALL_REQUEST_VECTOR)) <<
+	       (RSBAC_RC_SPECIAL_RIGHT_BASE -
+		RSBAC_RC_OLD_SPECIAL_RIGHT_BASE));
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static rsbac_list_conv_function_t *tcfd_get_subconv(rsbac_version_t
+						    old_version)
+#else
+static rsbac_list_conv_function_t *__init tcfd_get_subconv(rsbac_version_t
+							   old_version)
+#endif
+{
+	switch (old_version) {
+	case RSBAC_RC_ROLE_TCFD_OLD_LIST_VERSION:
+		return tc_subconv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int tc_conv(
+#else
+static int __init tc_conv(
+#endif
+				 void *old_desc,
+				 void *old_data,
+				 void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(rsbac_rc_role_id_t));
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static rsbac_list_conv_function_t *tcfd_get_conv(rsbac_version_t
+						 old_version)
+#else
+static rsbac_list_conv_function_t *__init tcfd_get_conv(rsbac_version_t
+							old_version)
+#endif
+{
+	switch (old_version) {
+	case RSBAC_RC_ROLE_TCFD_OLD_LIST_VERSION:
+		return tc_conv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static int rsbac_rc_role_compare_data(void *data1, void *data2)
+#else
+static int __init rsbac_rc_role_compare_data(void *data1, void *data2)
+#endif
+{
+	struct rsbac_rc_role_entry_t *role = data1;
+
+	if (!data1)
+		return 1;
+	if (role->boot_role)
+		return 0;
+	else
+		return 1;
+}
+
+/************************************************* */
+/*               proc functions                    */
+/************************************************* */
+
+#if defined(CONFIG_RSBAC_PROC)
+static int
+stats_rc_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "stats_rc_proc_info(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	rsbac_pr_debug(aef_rc, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "RC Status\n---------\n");
+	seq_printf(m,
+		    "Role entry size is %Zd, %lu entries used\n",
+		    sizeof(struct rsbac_rc_role_entry_t),
+		    rsbac_list_count(role_handle));
+	seq_printf(m,
+		    "Used type entries: fd: %lu, dev: %lu, ipc: %lu, user: %lu, process: %lu, group: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
+		    rsbac_list_count(type_fd_handle),
+		    rsbac_list_count(type_dev_handle),
+		    rsbac_list_count(type_ipc_handle),
+		    rsbac_list_count(type_user_handle),
+		    rsbac_list_count(type_process_handle),
+		    rsbac_list_count(type_group_handle),
+		    rsbac_list_count(type_netdev_handle),
+		    rsbac_list_count(type_nettemp_handle),
+		    rsbac_list_count(type_netobj_handle));
+	return 0;
+}
+
+static int stats_rc_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_rc_proc_show, NULL);
+}
+
+static const struct file_operations stats_rc_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= stats_rc_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct proc_dir_entry *stats_rc;
+
+#endif				/* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */
+
+/************************************************* */
+/*               Init functions                    */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac/error.h.                 */
+
+/************************************************************************** */
+/* Initialization of all RC data structures. After this call, all RC data   */
+/* is kept in memory for performance reasons, but is written to disk on     */
+/* every change.    */
+
+/* There can be no access to aci data structures before init.               */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static void registration_error(int err, char *listname)
+#else
+static void __init registration_error(int err, char *listname)
+#endif
+{
+	if (err) {
+		char *tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_rc(): Registering RC %s list failed with error %s\n",
+				     listname, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static void create_def_roles(void)
+#else
+static void __init create_def_roles(void)
+#endif
+{
+	rsbac_rc_role_id_t role;
+	rsbac_rc_type_id_t type;
+	rsbac_rc_rights_vector_t rights;
+	struct rsbac_rc_role_entry_t gen_entry =
+	    RSBAC_RC_GENERAL_ROLE_ENTRY;
+	struct rsbac_rc_role_entry_t ra_entry =
+	    RSBAC_RC_ROLE_ADMIN_ROLE_ENTRY;
+	struct rsbac_rc_role_entry_t sa_entry =
+	    RSBAC_RC_SYSTEM_ADMIN_ROLE_ENTRY;
+
+	rsbac_printk(KERN_WARNING "rsbac_init_rc(): no RC roles read, generating default role entries!\n");
+
+	role = RSBAC_RC_GENERAL_ROLE;
+	if (!rsbac_list_add(role_handle, &role, &gen_entry)) {
+		if (!rsbac_list_lol_add
+		    (role_tcfd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_EXECUTE_REQUEST_VECTOR)
+			    & RSBAC_FD_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcdv_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_DEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcus_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) |
+			    RSBAC_REQUEST_VECTOR
+			    (R_GET_STATUS_DATA);
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcpr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = CONFIG_RSBAC_RC_KERNEL_PROCESS_TYPE;
+			rights =
+			    RSBAC_READ_REQUEST_VECTOR &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcip_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_IPC_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcgr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR
+			    (R_GET_STATUS_DATA);
+			rsbac_list_lol_subadd(role_tcgr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_NETDEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcno_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_NETOBJ_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcno_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcsc_handle, &role, NULL)) {
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+			type = ST_ioports;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_PERMISSIONS_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+#endif
+			type = ST_rlimit;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_SYSTEM_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_other;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR(R_MAP_EXEC);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_network;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+		}
+	}
+	role = RSBAC_RC_ROLE_ADMIN_ROLE;
+	if (!rsbac_list_add(role_handle, &role, &ra_entry)) {
+		if (!rsbac_list_lol_add
+		    (role_tcfd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights = ((RSBAC_READ_WRITE_REQUEST_VECTOR
+				   | RSBAC_EXECUTE_REQUEST_VECTOR
+				   | RSBAC_SECURITY_REQUEST_VECTOR)
+				  & RSBAC_FD_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_REQUEST_VECTOR &
+			     RSBAC_FD_REQUEST_VECTOR)
+			    | RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcdv_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_DEV_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_DEV_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcus_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR |
+			      RSBAC_REQUEST_VECTOR(R_AUTHENTICATE))
+			     & RSBAC_USER_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR |
+			      RSBAC_REQUEST_VECTOR(R_AUTHENTICATE))
+			     & RSBAC_USER_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR |
+			      RSBAC_REQUEST_VECTOR(R_AUTHENTICATE))
+			     & RSBAC_USER_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcpr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_PROCESS_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_PROCESS_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = CONFIG_RSBAC_RC_KERNEL_PROCESS_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_PROCESS_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcip_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_IPC_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_IPC_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcgr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_GROUP_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcgr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_REQUEST_VECTOR
+			      (R_GET_STATUS_DATA) |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_NETDEV_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnt_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_NETTEMP_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcnt_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_NETTEMP_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcnt_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcno_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    ((RSBAC_READ_WRITE_REQUEST_VECTOR |
+			      RSBAC_SECURITY_REQUEST_VECTOR)
+			     & RSBAC_NETOBJ_REQUEST_VECTOR) |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcno_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcsc_handle, &role, NULL)) {
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+			type = ST_ioports;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_PERMISSIONS_DATA)
+			    | RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+#endif
+			type = ST_rlimit;
+			rights =
+			    RSBAC_SCD_REQUEST_VECTOR |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_rsbac;
+			rights =
+			    RSBAC_SCD_REQUEST_VECTOR |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_rsbac_log;
+			rights =
+			    RSBAC_SCD_REQUEST_VECTOR |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_other;
+			rights = RSBAC_RC_RIGHTS_VECTOR(R_MAP_EXEC)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_PERMISSIONS_DATA)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_SWITCH_LOG)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR(R_SWITCH_MODULE)
+			    | RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_network;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA)
+			    | RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_firewall;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA)
+			    | RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = RST_auth_administration;
+			rights =
+			    RSBAC_SCD_REQUEST_VECTOR |
+			    RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_sysfs;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA)
+			    | RSBAC_RC_SPECIAL_RIGHTS_VECTOR;
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+		}
+	}
+	role = RSBAC_RC_SYSTEM_ADMIN_ROLE;
+	if (!rsbac_list_add(role_handle, &role, &sa_entry)) {
+		if (!rsbac_list_lol_add
+		    (role_tcfd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights = (RSBAC_READ_WRITE_REQUEST_VECTOR
+				  | RSBAC_EXECUTE_REQUEST_VECTOR
+				  | RSBAC_SYSTEM_REQUEST_VECTOR)
+			    & RSBAC_FD_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcdv_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_DEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_DEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcus_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) |
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR(R_GET_STATUS_DATA) |
+			    RSBAC_REQUEST_VECTOR(R_AUTHENTICATE);
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR(R_GET_STATUS_DATA) |
+			    RSBAC_REQUEST_VECTOR(R_AUTHENTICATE);
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR(R_AUTHENTICATE);
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcpr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_REQUEST_VECTOR(R_CONNECT) |
+			     RSBAC_REQUEST_VECTOR(R_SEND) |
+			     RSBAC_REQUEST_VECTOR(R_RECEIVE) |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = CONFIG_RSBAC_RC_KERNEL_PROCESS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcip_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_IPC_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_IPC_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcgr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR(R_GET_STATUS_DATA) |
+			    RSBAC_REQUEST_VECTOR(R_READ);
+			rsbac_list_lol_subadd(role_tcgr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_NETDEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnt_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_REQUEST_VECTOR) &
+			    RSBAC_NETTEMP_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcnt_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcno_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_NETOBJ_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcno_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcsc_handle, &role, NULL)) {
+			rights =
+			    RSBAC_SCD_REQUEST_VECTOR &
+			    (RSBAC_SYSTEM_REQUEST_VECTOR |
+			     RSBAC_READ_WRITE_REQUEST_VECTOR);
+			for (type = ST_time_strucs;
+			     type <= ST_rsbac; type++) {
+				rsbac_list_lol_subadd
+				    (role_tcsc_handle, &role,
+				     &type, &rights);
+			}
+			for (type = ST_network; type < ST_none;
+			     type++) {
+				rsbac_list_lol_subadd
+				    (role_tcsc_handle, &role,
+				     &type, &rights);
+			}
+			type = ST_other;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR(R_ADD_TO_KERNEL)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_MAP_EXEC)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_SYSTEM_DATA)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_MOUNT)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_REMOVE_FROM_KERNEL)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_UMOUNT)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_SHUTDOWN);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+		}
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+static void create_def_roles2(void)
+#else
+static void __init create_def_roles2(void)
+#endif
+{
+	rsbac_rc_role_id_t role;
+	rsbac_rc_type_id_t type;
+	rsbac_rc_rights_vector_t rights;
+	struct rsbac_rc_role_entry_t au_entry =
+	    RSBAC_RC_AUDITOR_ROLE_ENTRY;
+	struct rsbac_rc_role_entry_t bo_entry =
+	    RSBAC_RC_BOOT_ROLE_ENTRY;
+
+	rsbac_printk(KERN_WARNING "rsbac_init_rc(): no RC roles read, generating default role entries!\n");
+
+	role = RSBAC_RC_AUDITOR_ROLE;
+	if (!rsbac_list_add(role_handle, &role, &au_entry)) {
+		if (!rsbac_list_lol_add
+		    (role_tcfd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_EXECUTE_REQUEST_VECTOR)
+			    & RSBAC_FD_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcdv_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_DEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcus_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) |
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR
+			    (R_GET_STATUS_DATA);
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcgr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+			    RSBAC_REQUEST_VECTOR
+			    (R_GET_STATUS_DATA);
+			rsbac_list_lol_subadd(role_tcgr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcpr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcip_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_IPC_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_NETDEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcno_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    RSBAC_READ_WRITE_REQUEST_VECTOR &
+			    RSBAC_NETOBJ_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcno_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcsc_handle, &role, NULL)) {
+#ifdef CONFIG_RSBAC_USER_MOD_IOPERM
+			type = ST_ioports;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_PERMISSIONS_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+#endif
+			type = ST_rlimit;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_SYSTEM_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_rsbac_log;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_SYSTEM_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_other;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR(R_MAP_EXEC);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+			type = ST_network;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_GET_STATUS_DATA);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+		}
+	}
+	role = RSBAC_RC_BOOT_ROLE;
+	if (!rsbac_list_add(role_handle, &role, &bo_entry)) {
+		if (!rsbac_list_lol_add
+		    (role_tcfd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights = (RSBAC_READ_WRITE_REQUEST_VECTOR
+				  | RSBAC_EXECUTE_REQUEST_VECTOR
+				  | RSBAC_SYSTEM_REQUEST_VECTOR)
+			    & RSBAC_FD_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rsbac_list_lol_subadd(role_tcfd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcdv_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_DEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_DEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcdv_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcus_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_REQUEST_VECTOR |
+			     RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) |
+			     RSBAC_SYSTEM_REQUEST_VECTOR |
+			     RSBAC_REQUEST_VECTOR(R_AUTHENTICATE)) &
+			    RSBAC_USER_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SEC_TYPE;
+			rights =
+			    RSBAC_REQUEST_VECTOR(R_SEARCH) |
+		            RSBAC_REQUEST_VECTOR(R_CHANGE_OWNER) |
+			    RSBAC_REQUEST_VECTOR(R_AUTHENTICATE);
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_USER_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcus_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcpr_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+			type = CONFIG_RSBAC_RC_KERNEL_PROCESS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_PROCESS_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcpr_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcip_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_IPC_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+			type = RSBAC_RC_SYS_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_IPC_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcip_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnd_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_NETDEV_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcnd_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcnt_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_REQUEST_VECTOR) &
+			    RSBAC_NETTEMP_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcnt_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcno_handle, &role, NULL)) {
+			type = RSBAC_RC_GENERAL_TYPE;
+			rights =
+			    (RSBAC_READ_WRITE_REQUEST_VECTOR |
+			     RSBAC_SYSTEM_REQUEST_VECTOR) &
+			    RSBAC_NETOBJ_REQUEST_VECTOR;
+			rsbac_list_lol_subadd(role_tcno_handle,
+					      &role, &type,
+					      &rights);
+		}
+		if (!rsbac_list_lol_add
+		    (role_tcsc_handle, &role, NULL)) {
+			rights =
+			    RSBAC_SCD_REQUEST_VECTOR &
+			    (RSBAC_SYSTEM_REQUEST_VECTOR |
+			     RSBAC_READ_WRITE_REQUEST_VECTOR);
+			for (type = ST_time_strucs;
+			     type <= ST_rsbac; type++) {
+				rsbac_list_lol_subadd
+				    (role_tcsc_handle, &role,
+				     &type, &rights);
+			}
+			for (type = ST_network; type < ST_none;
+			     type++) {
+				rsbac_list_lol_subadd
+				    (role_tcsc_handle, &role,
+				     &type, &rights);
+			}
+			type = ST_other;
+			rights =
+			    RSBAC_RC_RIGHTS_VECTOR(R_ADD_TO_KERNEL)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_MAP_EXEC)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_MODIFY_SYSTEM_DATA)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_MOUNT)
+			    |
+			    RSBAC_RC_RIGHTS_VECTOR
+			    (R_REMOVE_FROM_KERNEL)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_UMOUNT)
+			    | RSBAC_RC_RIGHTS_VECTOR(R_SHUTDOWN);
+			rsbac_list_lol_subadd(role_tcsc_handle,
+					      &role, &type,
+					      &rights);
+		}
+	}
+}
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_rc(void)
+#else
+int __init rsbac_init_rc(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_lol_info_t lol_info;
+	struct rsbac_list_info_t list_info;
+	rsbac_rc_rights_vector_t def_tc = RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+
+	if (rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_init_rc(): RSBAC already initialized\n");
+		return -RSBAC_EREINIT;
+	}
+
+	/* init data structures */
+	rsbac_printk(KERN_INFO "rsbac_init_rc(): Initializing RSBAC: RC subsystem\n");
+	rsbac_pr_debug(stack, "free stack: %lu\n", rsbac_stack_free_space());
+
+	list_info.version = RSBAC_RC_ROLE_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	list_info.data_size = sizeof(struct rsbac_rc_role_entry_t);
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &role_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE | RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, role_get_conv,
+				  NULL, RSBAC_RC_ROLE_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_role_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "role");
+	}
+
+	lol_info.version = RSBAC_RC_ROLE_RC_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_rc_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL, NULL, NULL,
+				      NULL, NULL,
+				      RSBAC_RC_ROLE_RC_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "role compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_ADR_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_adr_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL, NULL, NULL,
+				      NULL, NULL,
+				      RSBAC_RC_ROLE_ADR_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "admin roles");
+	}
+	lol_info.version = RSBAC_RC_ROLE_ASR_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.subdata_size = 0;
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_asr_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL, NULL, NULL,
+				      NULL, NULL,
+				      RSBAC_RC_ROLE_ASR_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "assign roles");
+	}
+	lol_info.version = RSBAC_RC_ROLE_DFDC_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_dfdc_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL, NULL, NULL,
+				      NULL, NULL,
+				      RSBAC_RC_ROLE_DFDC_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role default FD create types");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCFD_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcfd_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCFD_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role FD type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCDV_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcdv_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCDV_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role DEV type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCUS_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcus_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCUS_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role User type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCPR_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcpr_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCPR_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err,
+				   "Role Process type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCIP_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcip_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCIP_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role IPC type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCSC_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcsc_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCSC_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role SCD type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCGR_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcgr_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCGR_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err, "Role Group type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCND_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcnd_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCND_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err,
+				   "Role NETDEV type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCNT_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcnt_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCNT_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err,
+				   "Role NETTEMP type compatibilities");
+	}
+	lol_info.version = RSBAC_RC_ROLE_TCNO_LIST_VERSION;
+	lol_info.key = RSBAC_RC_LIST_KEY;
+	lol_info.desc_size = sizeof(rsbac_rc_role_id_t);
+	lol_info.data_size = 0;
+	lol_info.subdesc_size = sizeof(rsbac_rc_type_id_t);
+	lol_info.subdata_size = sizeof(rsbac_rc_rights_vector_t);
+	lol_info.max_age = 0;
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				      &role_tcno_handle, &lol_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				      RSBAC_LIST_BACKUP |
+#endif
+				      RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				      RSBAC_LIST_REPLICATE |
+				      RSBAC_LIST_DEF_DATA |
+				      RSBAC_LIST_DEF_SUBDATA |
+				      RSBAC_LIST_AUTO_HASH_RESIZE,
+				      NULL,
+				      NULL,
+				      tcfd_get_conv, tcfd_get_subconv,
+				      NULL, &def_tc,
+				      RSBAC_RC_ROLE_TCNO_FILENAME,
+				      RSBAC_AUTO_DEV,
+				      nr_role_hash_bits,
+				      rsbac_list_hash_u32,
+				      NULL);
+	if (err) {
+		registration_error(err,
+				   "Role NETOBJ type compatibilities");
+	}
+
+	/* Create default role settings, if none there */
+	if (!rsbac_no_defaults && !rsbac_list_count(role_handle)) {
+		create_def_roles();
+		create_def_roles2();
+	}
+
+	list_info.version = RSBAC_RC_TYPE_FD_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = sizeof(struct rsbac_rc_type_fd_entry_t);
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_fd_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_FD_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type FD");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_fd_handle)) {
+		rsbac_rc_type_id_t type;
+		struct rsbac_rc_type_fd_entry_t entry;
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(entry.name, "General FD");
+		entry.need_secdel = 0;
+		rsbac_list_add(type_fd_handle, &type, &entry);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(entry.name, "Security FD");
+		entry.need_secdel = 0;
+		rsbac_list_add(type_fd_handle, &type, &entry);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(entry.name, "System FD");
+		entry.need_secdel = 0;
+		rsbac_list_add(type_fd_handle, &type, &entry);
+	}
+	list_info.version = RSBAC_RC_TYPE_DEV_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_dev_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_DEV_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type DEV");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_dev_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General Device");
+		rsbac_list_add(type_dev_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Security Device");
+		rsbac_list_add(type_dev_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System Device");
+		rsbac_list_add(type_dev_handle, &type, &name);
+	}
+	list_info.version = RSBAC_RC_TYPE_IPC_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_ipc_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_IPC_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type IPC");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_ipc_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General IPC");
+		rsbac_list_add(type_ipc_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Security IPC");
+		rsbac_list_add(type_ipc_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System IPC");
+		rsbac_list_add(type_ipc_handle, &type, &name);
+	}
+	list_info.version = RSBAC_RC_TYPE_USER_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_user_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_USER_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type USER");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_user_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General User");
+		rsbac_list_add(type_user_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Security User");
+		rsbac_list_add(type_user_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System User");
+		rsbac_list_add(type_user_handle, &type, &name);
+	}
+	list_info.version = RSBAC_RC_TYPE_PROCESS_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_process_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_PROCESS_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type PROCESS");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_process_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General Process");
+		rsbac_list_add(type_process_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Security Proc");
+		rsbac_list_add(type_process_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System Process");
+		rsbac_list_add(type_process_handle, &type, &name);
+	}
+	if (!rsbac_no_defaults) {
+		rsbac_rc_type_id_t type =
+		    CONFIG_RSBAC_RC_KERNEL_PROCESS_TYPE;
+
+		if (!rsbac_list_exist(type_process_handle, &type)) {
+			char name[RSBAC_RC_NAME_LEN];
+			rsbac_rc_role_id_t *role_array;
+			u_long count;
+			rsbac_rc_rights_vector_t rights;
+
+			strcpy(name, "Kernel Process");
+			rsbac_list_add(type_process_handle, &type, &name);
+
+			/* Set type compatibilities for the new type for all roles */
+			rights = RSBAC_READ_WRITE_REQUEST_VECTOR
+			    & RSBAC_PROCESS_REQUEST_VECTOR;
+
+			count =
+			    rsbac_list_lol_get_all_desc(role_tcpr_handle,
+							(void **)
+							&role_array);
+			if (count > 0) {
+				u_int i;
+
+				for (i = 0; i < count; i++) {
+					if (!rsbac_list_lol_subexist
+					    (role_tcpr_handle,
+					     &role_array[i], &type))
+						rsbac_list_lol_subadd
+						    (role_tcpr_handle,
+						     &role_array[i], &type,
+						     &rights);
+				}
+				rsbac_kfree(role_array);
+			}
+		}
+	}
+	list_info.version = RSBAC_RC_TYPE_GROUP_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_group_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_GROUP_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type GROUP");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_group_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General Group");
+		rsbac_list_add(type_group_handle, &type, name);
+	}
+	list_info.version = RSBAC_RC_TYPE_NETDEV_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_netdev_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_NETDEV_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type NETDEV");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_netdev_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General NETDEV");
+		rsbac_list_add(type_netdev_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Security NETDEV");
+		rsbac_list_add(type_netdev_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System NETDEV");
+		rsbac_list_add(type_netdev_handle, &type, &name);
+	}
+	list_info.version = RSBAC_RC_TYPE_NETTEMP_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_nettemp_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_NETTEMP_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type NETTEMP");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_nettemp_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General NETTEMP");
+		rsbac_list_add(type_nettemp_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Securit NETTEMP");
+		rsbac_list_add(type_nettemp_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System NETTEMP");
+		rsbac_list_add(type_nettemp_handle, &type, &name);
+	}
+	list_info.version = RSBAC_RC_TYPE_NETOBJ_LIST_VERSION;
+	list_info.key = RSBAC_RC_LIST_KEY;
+	list_info.desc_size = sizeof(rsbac_rc_type_id_t);
+	list_info.data_size = RSBAC_RC_NAME_LEN;
+	list_info.max_age = 0;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				  &type_netobj_handle, &list_info,
+#if defined(CONFIG_RSBAC_RC_BACKUP)
+				  RSBAC_LIST_BACKUP |
+#endif
+				  RSBAC_LIST_PERSIST | RSBAC_LIST_OWN_SLAB |
+				  RSBAC_LIST_REPLICATE |
+				  RSBAC_LIST_AUTO_HASH_RESIZE,
+				  NULL, NULL, NULL,
+				  RSBAC_RC_TYPE_NETOBJ_FILENAME,
+				  RSBAC_AUTO_DEV,
+				  nr_type_hash_bits,
+				  rsbac_list_hash_u32,
+				  NULL);
+	if (err) {
+		registration_error(err, "type NETOBJ");
+	}
+	if (!rsbac_no_defaults && !rsbac_list_count(type_netobj_handle)) {
+		rsbac_rc_type_id_t type;
+		char name[RSBAC_RC_NAME_LEN];
+
+		type = RSBAC_RC_GENERAL_TYPE;
+		strcpy(name, "General NETOBJ");
+		rsbac_list_add(type_netobj_handle, &type, name);
+		type = RSBAC_RC_SEC_TYPE;
+		strcpy(name, "Security NETOBJ");
+		rsbac_list_add(type_netobj_handle, &type, name);
+		type = RSBAC_RC_SYS_TYPE;
+		strcpy(name, "System NETOBJ");
+		rsbac_list_add(type_netobj_handle, &type, &name);
+	}
+	rsbac_pr_debug(stack, "free stack before adding proc entry: %lu\n",
+		       rsbac_stack_free_space());
+#if defined(CONFIG_RSBAC_PROC)
+	stats_rc = proc_create("stats_rc",
+					S_IFREG | S_IRUGO,
+					proc_rsbac_root_p, &stats_rc_proc_fops);
+#endif
+	rsbac_pr_debug(stack, "final free stack: %lu\n",
+		       rsbac_stack_free_space());
+	rsbac_pr_debug(ds_rc, "Ready.\n");
+	return (err);
+}
+
+/***************************************************/
+/* We also need some status information...         */
+
+int rsbac_stats_rc(void)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_stats_rc(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+
+	rsbac_printk(KERN_INFO "Role entry size is %u, %lu entries used\n",
+		     sizeof(struct rsbac_rc_role_entry_t),
+		     rsbac_list_count(role_handle));
+
+	rsbac_printk(KERN_INFO "Used type entries: fd: %lu, dev: %lu, ipc: %lu, user: %lu, process: %lu, group: %lu, netdev: %lu, nettemp: %lu, netobj: %lu\n",
+		     rsbac_list_count(type_fd_handle),
+		     rsbac_list_count(type_dev_handle),
+		     rsbac_list_count(type_ipc_handle),
+		     rsbac_list_count(type_user_handle),
+		     rsbac_list_count(type_process_handle),
+		     rsbac_list_count(type_group_handle),
+		     rsbac_list_count(type_netdev_handle),
+		     rsbac_list_count(type_nettemp_handle),
+		     rsbac_list_count(type_netobj_handle));
+	return 0;
+}
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* Find the boot role */
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_rc_get_boot_role(rsbac_rc_role_id_t * role_p)
+#else
+int __init rsbac_rc_get_boot_role(rsbac_rc_role_id_t * role_p)
+#endif
+{
+	/* Try to find role marked as boot role */
+	if (rsbac_list_get_desc(role_handle,
+				role_p, role_p, rsbac_rc_role_compare_data)
+	    ) {			/* none found */
+		return -RSBAC_ENOTFOUND;
+	}
+	return 0;
+}
+
+/* Checking whether role exists */
+rsbac_boolean_t rsbac_rc_role_exists(rsbac_list_ta_number_t ta_number,
+				     rsbac_rc_role_id_t role)
+{
+	return rsbac_ta_list_exist(ta_number, role_handle, &role);
+}
+
+rsbac_boolean_t rsbac_rc_type_exists(rsbac_list_ta_number_t ta_number,
+				     enum rsbac_target_t target,
+				     rsbac_rc_type_id_t type)
+{
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_FD:
+		return rsbac_ta_list_exist(ta_number, type_fd_handle,
+					   &type);
+	case T_DEV:
+		return rsbac_ta_list_exist(ta_number, type_dev_handle,
+					   &type);
+	case T_IPC:
+		return rsbac_ta_list_exist(ta_number, type_ipc_handle,
+					   &type);
+	case T_USER:
+		return rsbac_ta_list_exist(ta_number, type_user_handle,
+					   &type);
+	case T_PROCESS:
+		return rsbac_ta_list_exist(ta_number, type_process_handle,
+					   &type);
+	case T_NETDEV:
+		return rsbac_ta_list_exist(ta_number, type_netdev_handle,
+					   &type);
+	case T_NETTEMP:
+		return rsbac_ta_list_exist(ta_number, type_nettemp_handle,
+					   &type);
+	case T_NETOBJ:
+		return rsbac_ta_list_exist(ta_number, type_netobj_handle,
+					   &type);
+	case T_SCD:
+		if (type < ST_none)
+			return TRUE;
+		else
+			return FALSE;
+	default:
+		return FALSE;
+	}
+}
+
+/* Invalid parameter combinations return an error. */
+
+int rsbac_rc_copy_role(rsbac_list_ta_number_t ta_number,
+		       rsbac_rc_role_id_t from_role,
+		       rsbac_rc_role_id_t to_role)
+{
+	struct rsbac_rc_role_entry_t entry;
+	rsbac_rc_role_id_t *role_array;
+	char *item_array;
+	long count;
+	u_long i;
+	int err;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_copy_role(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if ((from_role > RC_role_max_value)
+	    || (to_role > RC_role_max_value)
+	    || (to_role == from_role)
+	    )
+		return (-RSBAC_EINVALIDTARGET);
+
+	/* copy */
+	err =
+	    rsbac_ta_list_get_data_ttl(ta_number, role_handle, NULL,
+				       &from_role, &entry);
+	if (err)
+		return err;
+	err =
+	    rsbac_ta_list_add_ttl(ta_number, role_handle, 0, &to_role,
+				  &entry);
+	if (err)
+		return err;
+
+	rsbac_ta_list_lol_remove(ta_number, role_rc_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+						  role_rc_handle,
+						  &from_role,
+						  (void **) &role_array,
+						  NULL);
+	if (count > 0) {
+		for (i = 0; i < count; i++)
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_rc_handle, 0,
+						     &to_role,
+						     &role_array[i], 0);
+		rsbac_kfree(role_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_adr_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+						  role_adr_handle,
+						  &from_role,
+						  (void **) &role_array,
+						  NULL);
+	if (count > 0) {
+		for (i = 0; i < count; i++)
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_adr_handle, 0,
+						     &to_role,
+						     &role_array[i], 0);
+		rsbac_kfree(role_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_asr_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+						  role_asr_handle,
+						  &from_role,
+						  (void **) &role_array,
+						  NULL);
+	if (count > 0) {
+		for (i = 0; i < count; i++)
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_asr_handle, 0,
+						     &to_role,
+						     &role_array[i], 0);
+		rsbac_kfree(role_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_dfdc_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_dfdc_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_dfdc_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_dfdc_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcfd_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcfd_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcfd_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcfd_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcdv_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcdv_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcdv_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcdv_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcus_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcus_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcus_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcus_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcpr_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcpr_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcpr_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcpr_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcip_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcip_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcip_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcip_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcsc_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcsc_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcsc_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcsc_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcgr_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcgr_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcgr_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcgr_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcnd_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcnd_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcnd_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcnd_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcnt_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcnt_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcnt_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcnt_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	rsbac_ta_list_lol_remove(ta_number, role_tcno_handle, &to_role);
+	count =
+	    rsbac_ta_list_lol_get_all_subitems_ttl(ta_number,
+						   role_tcno_handle,
+						   &from_role,
+						   (void **) &item_array,
+						   NULL);
+	if (count > 0) {
+		char *tmp = item_array;
+		int size =
+		    rsbac_list_lol_get_subitem_size(role_tcno_handle);
+
+		for (i = 0; i < count; i++) {
+			rsbac_ta_list_lol_subadd_ttl(ta_number,
+						     role_tcno_handle, 0,
+						     &to_role, tmp,
+						     tmp +
+						     sizeof
+						     (rsbac_rc_role_id_t));
+			tmp += size;
+		}
+		rsbac_kfree(item_array);
+	}
+	return 0;
+}
+
+int rsbac_rc_copy_type(rsbac_list_ta_number_t ta_number,
+		       enum rsbac_target_t target,
+		       rsbac_rc_type_id_t from_type,
+		       rsbac_rc_type_id_t to_type)
+{
+	rsbac_rc_role_id_t *role_array;
+	rsbac_list_handle_t i_type_handle = NULL;
+	rsbac_list_handle_t i_comp_handle = NULL;
+	struct rsbac_rc_type_fd_entry_t type_fd_entry;
+	char type_name[RSBAC_RC_NAME_LEN];
+	long count;
+	rsbac_time_t ttl;
+	u_long i;
+	int err;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_copy_type(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if ((from_type > RC_type_max_value)
+	    || (to_type > RC_type_max_value)
+	    || (to_type == from_type)
+	    )
+		return (-RSBAC_EINVALIDTARGET);
+
+	switch (target) {
+	case T_FILE:
+	case T_DIR:
+	case T_FIFO:
+	case T_SYMLINK:
+	case T_FD:
+		i_type_handle = type_fd_handle;
+		i_comp_handle = role_tcfd_handle;
+		break;
+	case T_DEV:
+		i_type_handle = type_dev_handle;
+		i_comp_handle = role_tcdv_handle;
+		break;
+	case T_USER:
+		i_type_handle = type_user_handle;
+		i_comp_handle = role_tcus_handle;
+		break;
+	case T_PROCESS:
+		i_type_handle = type_process_handle;
+		i_comp_handle = role_tcpr_handle;
+		break;
+	case T_IPC:
+		i_type_handle = type_ipc_handle;
+		i_comp_handle = role_tcip_handle;
+		break;
+	case T_GROUP:
+		i_type_handle = type_group_handle;
+		i_comp_handle = role_tcgr_handle;
+		break;
+	case T_NETDEV:
+		i_type_handle = type_netdev_handle;
+		i_comp_handle = role_tcnd_handle;
+		break;
+	case T_NETTEMP:
+		i_type_handle = type_nettemp_handle;
+		i_comp_handle = role_tcnt_handle;
+		break;
+	case T_NETOBJ:
+		i_type_handle = type_netobj_handle;
+		i_comp_handle = role_tcno_handle;
+		break;
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+
+	/* copy */
+	if (i_type_handle == type_fd_handle) {
+		err =
+		    rsbac_ta_list_get_data_ttl(ta_number, i_type_handle,
+					       &ttl, &from_type,
+					       &type_fd_entry);
+		if (err)
+			return err;
+		err =
+		    rsbac_ta_list_add_ttl(ta_number, i_type_handle, ttl,
+					  &to_type, &type_fd_entry);
+		if (err)
+			return err;
+	} else {
+		err =
+		    rsbac_ta_list_get_data_ttl(ta_number, i_type_handle,
+					       NULL, &from_type,
+					       &type_name);
+		if (err)
+			return err;
+		err =
+		    rsbac_ta_list_add_ttl(ta_number, i_type_handle, 0,
+					  &to_type, &type_name);
+		if (err)
+			return err;
+	}
+
+	err =
+	    rsbac_ta_list_lol_subremove_from_all(ta_number, i_comp_handle,
+						 &to_type);
+	if (err)
+		return err;
+
+	count = rsbac_ta_list_get_all_desc(ta_number, role_handle,
+					   (void **) &role_array);
+	if (count > 0) {
+		rsbac_rc_rights_vector_t rights;
+
+		for (i = 0; i < count; i++) {
+			err = rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+								i_comp_handle,
+								&ttl,
+								&role_array
+								[i],
+								&from_type,
+								&rights);
+			if (!err)
+				err =
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 i_comp_handle,
+								 ttl,
+								 &role_array
+								 [i],
+								 &to_type,
+								 &rights);
+		}
+		rsbac_kfree(role_array);
+	}
+	return 0;
+}
+
+
+/* Getting values */
+int rsbac_rc_get_item(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_rc_target_t target,
+		      union rsbac_rc_target_id_t tid,
+		      union rsbac_rc_target_id_t subtid,
+		      enum rsbac_rc_item_t item,
+		      union rsbac_rc_item_value_t *value_p,
+		      rsbac_time_t * ttl_p)
+{
+	int err = 0;
+	struct rsbac_rc_role_entry_t role_entry;
+	struct rsbac_rc_type_fd_entry_t type_fd_entry;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_get_item(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_get_item(): called from interrupt!\n");
+	}
+	if (ttl_p)
+		*ttl_p = 0;
+	switch (target) {
+	case RT_ROLE:
+		if (tid.role > RC_role_max_value)
+			return (-RSBAC_EINVALIDTARGET);
+/*
+		rsbac_pr_debug(ds_rc, "getting role item value\n");
+*/
+		switch (item) {
+		case RI_role_comp:
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       role_rc_handle,
+							       ttl_p,
+							       &tid.role,
+							       &subtid.
+							       role, NULL))
+				value_p->comp = TRUE;
+			else
+				value_p->comp = FALSE;
+			return 0;
+		case RI_admin_roles:
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       role_adr_handle,
+							       ttl_p,
+							       &tid.role,
+							       &subtid.
+							       role, NULL))
+				value_p->comp = TRUE;
+			else
+				value_p->comp = FALSE;
+			return 0;
+		case RI_assign_roles:
+			if (!rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							       role_asr_handle,
+							       ttl_p,
+							       &tid.role,
+							       &subtid.
+							       role, NULL))
+				value_p->comp = TRUE;
+			else
+				value_p->comp = FALSE;
+			return 0;
+		case RI_type_comp_fd:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcfd_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_dev:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcdv_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_user:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcus_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_process:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcpr_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_ipc:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcip_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_scd:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcsc_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_group:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcgr_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_netdev:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcnd_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_nettemp:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcnt_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_type_comp_netobj:
+			if (rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+							      role_tcno_handle,
+							      ttl_p,
+							      &tid.role,
+							      &subtid.type,
+							      &value_p->
+							      rights)) {
+				value_p->rights =
+				    RSBAC_RC_DEFAULT_RIGHTS_VECTOR;
+				if (ttl_p)
+					*ttl_p = 0;
+			}
+			return 0;
+		case RI_admin_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->admin_type =
+				    role_entry.admin_type;
+			return err;
+		case RI_name:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry))) {
+				strncpy(value_p->name, role_entry.name,
+					RSBAC_RC_NAME_LEN - 1);
+				value_p->name[RSBAC_RC_NAME_LEN - 1] =
+				    (char) 0;
+			}
+			return err;
+		case RI_def_fd_create_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_fd_create_type;
+			return err;
+		case RI_def_fd_ind_create_type:
+			return rsbac_ta_list_lol_get_subdata_ttl(ta_number,
+								 role_dfdc_handle,
+								 ttl_p,
+								 &tid.role,
+								 &subtid.
+								 type,
+								 &value_p->
+								 type_id);
+		case RI_def_user_create_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_user_create_type;
+			return err;
+		case RI_def_process_create_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_process_create_type;
+			return err;
+		case RI_def_process_chown_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_process_chown_type;
+			return err;
+		case RI_def_process_execute_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_process_execute_type;
+			return err;
+		case RI_def_ipc_create_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_ipc_create_type;
+			return err;
+		case RI_def_group_create_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_group_create_type;
+			return err;
+		case RI_def_unixsock_create_type:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->type_id =
+				    role_entry.def_unixsock_create_type;
+			return err;
+		case RI_boot_role:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->boot_role = role_entry.boot_role;
+			return err;
+		case RI_req_reauth:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							role_handle, NULL,
+							&tid.role,
+							&role_entry)))
+				value_p->req_reauth =
+				    role_entry.req_reauth;
+			return err;
+		default:
+			return -RSBAC_EINVALIDATTR;
+		}
+		/* return */
+		return (err);
+		break;
+
+	case RT_TYPE:
+		if (tid.type > RC_type_max_value)
+			return (-RSBAC_EINVALIDTARGET);
+/*
+ 		rsbac_pr_debug(ds_rc, "getting type item value\n");
+*/
+		switch (item) {
+		case RI_type_fd_name:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							type_fd_handle,
+							NULL, &tid.type,
+							&type_fd_entry))) {
+				strncpy(value_p->name, type_fd_entry.name,
+					RSBAC_RC_NAME_LEN - 1);
+				value_p->name[RSBAC_RC_NAME_LEN - 1] =
+				    (char) 0;
+			}
+			return err;
+		case RI_type_fd_need_secdel:
+			if (!
+			    (err =
+			     rsbac_ta_list_get_data_ttl(ta_number,
+							type_fd_handle,
+							NULL, &tid.type,
+							&type_fd_entry))) {
+				value_p->need_secdel =
+				    type_fd_entry.need_secdel;
+			}
+			return err;
+		case RI_type_dev_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_dev_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_ipc_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_ipc_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_user_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_user_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_process_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_process_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_group_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_group_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_netdev_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_netdev_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_nettemp_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_nettemp_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_netobj_name:
+			return rsbac_ta_list_get_data_ttl(ta_number,
+							  type_netobj_handle,
+							  NULL, &tid.type,
+							  value_p->name);
+		case RI_type_scd_name:
+			{
+				char *tmp;
+
+				tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+				if (!tmp)
+					err = -RSBAC_ENOMEM;
+				else {
+					get_rc_scd_type_name(tmp,
+							     tid.type);
+					strncpy(value_p->name, tmp,
+						RSBAC_RC_NAME_LEN - 1);
+					value_p->name[RSBAC_RC_NAME_LEN -
+						      1] = (char) 0;
+					rsbac_kfree(tmp);
+				}
+				break;
+			}
+		default:
+			err = -RSBAC_EINVALIDATTR;
+		}
+		/* and return */
+		return (err);
+		break;
+
+		/* switch target: no valid target */
+	default:
+		err = -RSBAC_EINVALIDTARGET;
+	}
+	return err;
+}				/* end of rsbac_rc_get_item() */
+
+/* Checking role's compatibility */
+rsbac_boolean_t rsbac_rc_check_comp(rsbac_rc_role_id_t role,
+				    union rsbac_rc_target_id_t subtid,
+				    enum rsbac_rc_item_t item,
+				    enum rsbac_rc_special_rights_t right)
+{
+	rsbac_rc_rights_vector_t rights_vector;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_check_comp(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_check_comp(): called from interrupt!\n");
+	}
+	if (role > RC_role_max_value)
+		return FALSE;
+/*
+	rsbac_pr_debug(ds_rc, "checking role compatibility\n");
+*/
+	switch (item) {
+	case RI_role_comp:
+		return rsbac_list_lol_subexist(role_rc_handle, &role,
+					       &subtid.role);
+	case RI_admin_roles:
+		return rsbac_list_lol_subexist(role_adr_handle, &role,
+					       &subtid.role);
+	case RI_assign_roles:
+		return rsbac_list_lol_subexist(role_asr_handle, &role,
+					       &subtid.role);
+	case RI_type_comp_fd:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcfd_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_dev:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcdv_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_user:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcus_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_process:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcpr_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_ipc:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcip_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_scd:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcsc_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_group:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcgr_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_netdev:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcnd_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_nettemp:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcnt_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+	case RI_type_comp_netobj:
+		if (!rsbac_list_lol_get_subdata
+		    (role_tcno_handle, &role, &subtid.type, &rights_vector)
+		    && (rights_vector & RSBAC_RC_RIGHTS_VECTOR(right))
+		    )
+			return TRUE;
+		else
+			return FALSE;
+
+	default:
+		rsbac_printk(KERN_WARNING "rsbac_rc_check_comp(): called for invalid item %u\n",
+			     item);
+		return FALSE;
+	}
+}				/* end of rsbac_rc_check_comp() */
+
+/* Get list of defined items. Returns number or negative error.
+ * item is to distinguish type targets, use RI_type_xx_name */
+int rsbac_rc_get_list(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_rc_target_t target,
+		      union rsbac_rc_target_id_t tid,
+		      enum rsbac_rc_item_t item,
+		      __u32 ** array_pp, rsbac_time_t ** ttl_array_pp)
+{
+	int res;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_get_list(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_get_list(): called from interrupt!\n");
+	}
+	if (ttl_array_pp)
+		*ttl_array_pp = NULL;
+	switch (target) {
+	case RT_ROLE:
+/*
+		rsbac_pr_debug(ds_rc, "getting role list\n");
+*/
+		switch (item) {
+		case RI_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       role_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   role_handle);
+		case RI_role_comp:
+			if (array_pp)
+				res =
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_rc_handle, &tid.role,
+				     (void **) array_pp, ttl_array_pp);
+			else
+				res =
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_rc_handle,
+							       &tid.role);
+			if (res == -RSBAC_ENOTFOUND)
+				return 0;
+			else
+				return res;
+		case RI_admin_roles:
+			if (array_pp)
+				res =
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_adr_handle, &tid.role,
+				     (void **) array_pp, ttl_array_pp);
+			else
+				res =
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_adr_handle,
+							       &tid.role);
+			if (res == -RSBAC_ENOTFOUND)
+				return 0;
+			else
+				return res;
+		case RI_assign_roles:
+			if (array_pp)
+				res =
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_asr_handle, &tid.role,
+				     (void **) array_pp, ttl_array_pp);
+			else
+				res =
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_asr_handle,
+							       &tid.role);
+			if (res == -RSBAC_ENOTFOUND)
+				return 0;
+			else
+				return res;
+		case RI_def_fd_ind_create_type:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_dfdc_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_dfdc_handle,
+							       &tid.role);
+		case RI_type_comp_fd:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcfd_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcfd_handle,
+							       &tid.role);
+		case RI_type_comp_dev:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcdv_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcdv_handle,
+							       &tid.role);
+		case RI_type_comp_user:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcus_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcus_handle,
+							       &tid.role);
+		case RI_type_comp_process:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcpr_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcpr_handle,
+							       &tid.role);
+		case RI_type_comp_ipc:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcip_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcip_handle,
+							       &tid.role);
+		case RI_type_comp_scd:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcsc_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcsc_handle,
+							       &tid.role);
+		case RI_type_comp_group:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcgr_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcgr_handle,
+							       &tid.role);
+		case RI_type_comp_netdev:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcnd_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcnd_handle,
+							       &tid.role);
+		case RI_type_comp_nettemp:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcnt_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcnt_handle,
+							       &tid.role);
+		case RI_type_comp_netobj:
+			if (array_pp)
+				return
+				    rsbac_ta_list_lol_get_all_subdesc_ttl
+				    (ta_number, role_tcno_handle,
+				     &tid.role, (void **) array_pp,
+				     ttl_array_pp);
+			else
+				return
+				    rsbac_ta_list_lol_subcount(ta_number,
+							       role_tcno_handle,
+							       &tid.role);
+
+		default:
+			return -RSBAC_EINVALIDATTR;
+		}
+
+	case RT_TYPE:
+/*
+		rsbac_pr_debug(ds_rc, "getting type item value\n");
+*/
+		switch (item) {
+		case RI_type_fd_name:
+		case RI_type_fd_need_secdel:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_fd_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_fd_handle);
+		case RI_type_dev_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_dev_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_dev_handle);
+		case RI_type_ipc_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_ipc_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_ipc_handle);
+		case RI_type_user_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_user_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_user_handle);
+		case RI_type_process_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_process_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_process_handle);
+		case RI_type_group_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_group_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_group_handle);
+		case RI_type_netdev_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_netdev_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_netdev_handle);
+		case RI_type_nettemp_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_nettemp_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_nettemp_handle);
+		case RI_type_netobj_name:
+			if (array_pp)
+				return
+				    rsbac_ta_list_get_all_desc(ta_number,
+							       type_netobj_handle,
+							       (void **)
+							       array_pp);
+			else
+				return rsbac_ta_list_count(ta_number,
+							   type_netobj_handle);
+
+		default:
+			return -RSBAC_EINVALIDATTR;
+		}
+
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}				/* end of rsbac_rc_get_list() */
+
+
+/* Setting values */
+int rsbac_rc_set_item(rsbac_list_ta_number_t ta_number,
+		      enum rsbac_rc_target_t target,
+		      union rsbac_rc_target_id_t tid,
+		      union rsbac_rc_target_id_t subtid,
+		      enum rsbac_rc_item_t item,
+		      union rsbac_rc_item_value_t value, rsbac_time_t ttl)
+{
+	int err = 0;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_set_item(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (in_interrupt()) {
+		rsbac_printk(KERN_WARNING "rsbac_rc_set_item(): called from interrupt!\n");
+	}
+	switch (target) {
+	case RT_ROLE:
+		if (tid.role > RC_role_max_value)
+			return (-RSBAC_EINVALIDTARGET);
+		if ((item != RI_name)
+		    && !rsbac_ta_list_exist(ta_number, role_handle,
+					    &tid.role)
+		    )
+			return (-RSBAC_EINVALIDTARGET);
+		rsbac_pr_debug(ds_rc, "Setting role item value\n");
+		switch (item) {
+		case RI_role_comp:
+			if (value.comp) {
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 role_rc_handle,
+								 ttl,
+								 &tid.role,
+								 &subtid.
+								 role,
+								 NULL);
+			} else {
+				rsbac_ta_list_lol_subremove(ta_number,
+							    role_rc_handle,
+							    &tid.role,
+							    &subtid.role);
+				return 0;
+			}
+		case RI_admin_roles:
+			if (value.comp) {
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 role_adr_handle,
+								 ttl,
+								 &tid.role,
+								 &subtid.
+								 role,
+								 NULL);
+			} else {
+				rsbac_ta_list_lol_subremove(ta_number,
+							    role_adr_handle,
+							    &tid.role,
+							    &subtid.role);
+				return 0;
+			}
+		case RI_assign_roles:
+			if (value.comp) {
+				return
+				    rsbac_ta_list_lol_subadd_ttl(ta_number,
+								 role_asr_handle,
+								 ttl,
+								 &tid.role,
+								 &subtid.
+								 role,
+								 NULL);
+			} else {
+				rsbac_ta_list_lol_subremove(ta_number,
+							    role_asr_handle,
+							    &tid.role,
+							    &subtid.role);
+				return 0;
+			}
+		case RI_type_comp_fd:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_fd_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcfd_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_dev:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_dev_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcdv_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_user:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_user_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcus_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_process:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_process_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcpr_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_ipc:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_ipc_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcip_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_scd:
+			if ((subtid.type >= ST_none)
+			    && (subtid.type < RST_min)
+			    )
+				return -RSBAC_EINVALIDVALUE;
+			if (subtid.type >= RST_none)
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcsc_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_group:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_group_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcgr_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_netdev:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_netdev_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcnd_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_nettemp:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_nettemp_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcnt_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_type_comp_netobj:
+			if (!rsbac_ta_list_exist
+			    (ta_number, type_netobj_handle, &subtid.type))
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_tcno_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.rights);
+		case RI_admin_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.admin_type = value.admin_type;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_name:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				/* no empty names */
+				if (!value.name[0])
+					return -RSBAC_EINVALIDVALUE;
+				/* create, if necessary, and set name */
+				memset(&entry, 0,
+				       sizeof(struct
+					      rsbac_rc_role_entry_t));
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   role_handle,
+							   NULL, &tid.role,
+							   &entry);
+				strncpy(entry.name, value.name,
+					RSBAC_RC_NAME_LEN - 1);
+				entry.name[RSBAC_RC_NAME_LEN - 1] = 0;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_remove_role:
+			if (!tid.role)
+				return -RSBAC_EINVALIDVALUE;
+			/* remove role compat. */
+			rsbac_ta_list_lol_remove(ta_number, role_rc_handle,
+						 &tid.role);
+			/* remove from other roles' role compat */
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_rc_handle,
+							     &tid.role);
+
+			/* remove admin roles */
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_adr_handle,
+						 &tid.role);
+			/* remove from other roles' admin roles */
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_adr_handle,
+							     &tid.role);
+
+			/* remove assign roles */
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_asr_handle,
+						 &tid.role);
+			/* remove from other roles' assign roles */
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_asr_handle,
+							     &tid.role);
+
+			/* remove def_fd_ind_create_type */
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_dfdc_handle,
+						 &tid.role);
+
+			/* remove type compatibilities */
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcfd_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcdv_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcus_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcpr_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcip_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcsc_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcgr_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcnd_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcnt_handle,
+						 &tid.role);
+			rsbac_ta_list_lol_remove(ta_number,
+						 role_tcno_handle,
+						 &tid.role);
+
+#ifdef CONFIG_RSBAC_ACL
+			/* remove ACL entries */
+			{
+				struct rsbac_acl_entry_desc_t desc;
+
+				desc.subj_type = ACLS_ROLE;
+				desc.subj_id = tid.role;
+				rsbac_acl_remove_subject(ta_number, desc);
+			}
+#endif
+
+			return rsbac_ta_list_remove(ta_number, role_handle,
+						    &tid.role);
+
+		case RI_def_fd_create_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_fd_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_fd_create_type = value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_fd_ind_create_type:
+			if ((value.type_id <= RC_type_max_value)
+			    && !rsbac_ta_list_exist(ta_number,
+						    type_fd_handle,
+						    &value.type_id)
+			    )
+				return -RSBAC_EINVALIDVALUE;
+			if ((value.type_id > RC_type_max_value)
+			    && (value.type_id < RC_type_min_special)
+			    )
+				return -RSBAC_EINVALIDVALUE;
+			return rsbac_ta_list_lol_subadd_ttl(ta_number,
+							    role_dfdc_handle,
+							    ttl,
+							    &tid.role,
+							    &subtid.type,
+							    &value.
+							    type_id);
+		case RI_def_fd_ind_create_type_remove:
+			return rsbac_ta_list_lol_subremove(ta_number,
+							   role_dfdc_handle,
+							   &tid.role,
+							   &subtid.type);
+
+		case RI_def_user_create_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_user_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_user_create_type = value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_process_create_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_process_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_process_create_type =
+				    value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_process_chown_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_process_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_process_chown_type =
+				    value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_process_execute_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_process_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_process_execute_type =
+				    value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_ipc_create_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_ipc_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_ipc_create_type = value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_group_create_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_group_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_group_create_type =
+				    value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_def_unixsock_create_type:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				if ((value.type_id <= RC_type_max_value)
+				    && !rsbac_ta_list_exist(ta_number,
+							    type_fd_handle,
+							    &value.type_id)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				if ((value.type_id > RC_type_max_value)
+				    && (value.type_id <
+					RC_type_min_special)
+				    )
+					return -RSBAC_EINVALIDVALUE;
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.def_unixsock_create_type =
+				    value.type_id;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_boot_role:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.boot_role = value.boot_role;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+		case RI_req_reauth:
+			{
+				struct rsbac_rc_role_entry_t entry;
+
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       role_handle,
+							       NULL,
+							       &tid.role,
+							       &entry);
+				if (err)
+					return err;
+				entry.req_reauth = value.req_reauth;
+//				printk(KERN_WARNING "entry %u value %u\n",
+//				       entry.req_reauth, value.req_reauth);
+				return rsbac_ta_list_add_ttl(ta_number,
+							     role_handle,
+							     0, &tid.role,
+							     &entry);
+			}
+
+		default:
+			return -RSBAC_EINVALIDATTR;
+		}
+
+	case RT_TYPE:
+		if (tid.type > RC_type_max_value)
+			return (-RSBAC_EINVALIDTARGET);
+		rsbac_pr_debug(ds_rc, "Setting type item value\n");
+		switch (item) {
+		case RI_type_fd_name:
+			{
+				struct rsbac_rc_type_fd_entry_t entry;
+
+				/* no empty names */
+				if (!value.name[0])
+					return -RSBAC_EINVALIDVALUE;
+				/* create, if necessary, and set name */
+				memset(&entry, 0,
+				       sizeof(struct
+					      rsbac_rc_type_fd_entry_t));
+				rsbac_ta_list_get_data_ttl(ta_number,
+							   type_fd_handle,
+							   NULL, &tid.type,
+							   &entry);
+				strncpy(entry.name, value.name,
+					RSBAC_RC_NAME_LEN - 1);
+				entry.name[RSBAC_RC_NAME_LEN - 1] = 0;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     type_fd_handle,
+							     0, &tid.type,
+							     &entry);
+			}
+		case RI_type_fd_need_secdel:
+			{
+				struct rsbac_rc_type_fd_entry_t entry;
+
+				err =
+				    rsbac_ta_list_get_data_ttl(ta_number,
+							       type_fd_handle,
+							       NULL,
+							       &tid.type,
+							       &entry);
+				if (err)
+					return err;
+				entry.need_secdel = value.need_secdel;
+				return rsbac_ta_list_add_ttl(ta_number,
+							     type_fd_handle,
+							     0, &tid.type,
+							     &entry);
+			}
+		case RI_type_dev_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_dev_handle, 0,
+						     &tid.type,
+						     &value.name);
+		case RI_type_ipc_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_ipc_handle, 0,
+						     &tid.type,
+						     &value.name);
+		case RI_type_user_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_user_handle, 0,
+						     &tid.type,
+						     &value.name);
+		case RI_type_process_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_process_handle,
+						     0, &tid.type,
+						     &value.name);
+		case RI_type_group_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_group_handle, 0,
+						     &tid.type,
+						     &value.name);
+		case RI_type_netdev_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_netdev_handle, 0,
+						     &tid.type,
+						     &value.name);
+		case RI_type_nettemp_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_nettemp_handle,
+						     0, &tid.type,
+						     &value.name);
+		case RI_type_netobj_name:
+			/* no empty names */
+			if (!value.name[0])
+				return -RSBAC_EINVALIDVALUE;
+			/* create, if necessary, and set name */
+			value.name[RSBAC_RC_NAME_LEN - 1] = 0;
+			return rsbac_ta_list_add_ttl(ta_number,
+						     type_netobj_handle, 0,
+						     &tid.type,
+						     &value.name);
+
+		case RI_type_fd_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcfd_handle,
+							     &tid.type);
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_dfdc_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_fd_handle,
+						    &tid.type);
+		case RI_type_dev_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcdv_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_dev_handle,
+						    &tid.type);
+		case RI_type_user_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcus_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_user_handle,
+						    &tid.type);
+		case RI_type_process_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcpr_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_process_handle,
+						    &tid.type);
+		case RI_type_ipc_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcip_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_ipc_handle,
+						    &tid.type);
+		case RI_type_group_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcgr_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_group_handle,
+						    &tid.type);
+		case RI_type_netdev_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcnd_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_netdev_handle,
+						    &tid.type);
+		case RI_type_nettemp_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcnt_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_nettemp_handle,
+						    &tid.type);
+		case RI_type_netobj_remove:
+			if (!tid.type)
+				return -RSBAC_EINVALIDVALUE;
+			rsbac_ta_list_lol_subremove_from_all(ta_number,
+							     role_tcno_handle,
+							     &tid.type);
+			return rsbac_ta_list_remove(ta_number,
+						    type_netobj_handle,
+						    &tid.type);
+
+		default:
+			return -RSBAC_EINVALIDATTR;
+		}
+
+		/* switch target: no valid target */
+	default:
+		return -RSBAC_EINVALIDTARGET;
+	}
+}
diff --git a/rsbac/data_structures/um_data_structures.c b/rsbac/data_structures/um_data_structures.c
new file mode 100644
index 0000000..46a2e90
--- /dev/null
+++ b/rsbac/data_structures/um_data_structures.c
@@ -0,0 +1,2474 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of User Management data structures */
+/* Author and (c) 1999-2017: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 05/Sep/2017                        */
+/*************************************************** */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/export.h>
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/um_types.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/adf.h>
+#include <rsbac/aci.h>
+#include <rsbac/um.h>
+#include <rsbac/lists.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/getname.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#ifdef CONFIG_RSBAC_UM_DIGEST
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#endif
+#include <linux/seq_file.h>
+#include <linux/hash.h>
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+static rsbac_list_handle_t user_handle;
+static rsbac_list_handle_t group_handle;
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+static rsbac_list_handle_t user_pwhistory_handle;
+#endif
+#ifdef CONFIG_RSBAC_UM_ONETIME
+static rsbac_list_handle_t onetime_handle;
+#endif
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+static rsbac_list_handle_t uid_cache_handle;
+static rsbac_list_handle_t gid_cache_handle;
+u_long uid_cache_hits = 0;
+u_long uid_cache_misses = 0;
+u_long gid_cache_hits = 0;
+u_long gid_cache_misses = 0;
+#endif
+#define EXTRA_ROOM 20
+
+/**************************************************/
+/*       Declarations of external functions       */
+/**************************************************/
+
+/**************************************************/
+/*       Declarations of internal functions       */
+/**************************************************/
+
+/************************************************* */
+/*               Internal Help functions           */
+/************************************************* */
+
+static u_int nr_user_hash_bits = RSBAC_UM_NR_USER_LIST_HASH_BITS;
+static u_int nr_group_hash_bits = RSBAC_UM_NR_GROUP_LIST_HASH_BITS;
+
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+static u_int nr_user_pwhistory_hash_bits = RSBAC_UM_NR_USER_PWHISTORY_LIST_HASH_BITS;
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+static u_int nr_uid_cache_hash_bits = RSBAC_UM_NR_NAME_CACHE_LIST_HASH_BITS;
+static u_int nr_gid_cache_hash_bits = RSBAC_UM_NR_NAME_CACHE_LIST_HASH_BITS;
+#endif
+
+static int user_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_um_user_entry_t * new_aci = new_data;
+	struct rsbac_um_old_user_entry_t * old_aci = old_data;
+
+	memcpy(&new_aci->name, &old_aci->name, RSBAC_UM_OLD_NAME_LEN);
+	memcpy(&new_aci->pass, &old_aci->pass, RSBAC_UM_PASS_LEN);
+	memcpy(&new_aci->fullname, &old_aci->fullname, RSBAC_UM_OLD_FULLNAME_LEN);
+	memcpy(&new_aci->homedir, &old_aci->homedir, RSBAC_UM_OLD_HOMEDIR_LEN);
+	memcpy(&new_aci->shell, &old_aci->shell, RSBAC_UM_OLD_SHELL_LEN);
+	new_aci->group = old_aci->group;
+	new_aci->lastchange = old_aci->lastchange;
+	new_aci->minchange = old_aci->minchange;
+	new_aci->maxchange = old_aci->maxchange;
+	new_aci->warnchange = old_aci->warnchange;
+	new_aci->inactive = old_aci->inactive;
+	new_aci->expire = old_aci->expire;
+	*((rsbac_uid_t *)new_desc) = *((rsbac_uid_t *)old_desc);
+	return 0;
+}
+
+static int user_old_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_um_user_entry_t * new_aci = new_data;
+	struct rsbac_um_old_user_entry_t * old_aci = old_data;
+
+	memcpy(&new_aci->name, &old_aci->name, RSBAC_UM_OLD_NAME_LEN);
+	memcpy(&new_aci->pass, &old_aci->pass, RSBAC_UM_PASS_LEN);
+	memcpy(&new_aci->fullname, &old_aci->fullname, RSBAC_UM_OLD_FULLNAME_LEN);
+	memcpy(&new_aci->homedir, &old_aci->homedir, RSBAC_UM_OLD_HOMEDIR_LEN);
+	memcpy(&new_aci->shell, &old_aci->shell, RSBAC_UM_OLD_SHELL_LEN);
+	new_aci->group = old_aci->group;
+	new_aci->lastchange = old_aci->lastchange;
+	new_aci->minchange = old_aci->minchange;
+	new_aci->maxchange = old_aci->maxchange;
+	new_aci->warnchange = old_aci->warnchange;
+	new_aci->inactive = old_aci->inactive;
+	new_aci->expire = old_aci->expire;
+	*((rsbac_uid_t *)new_desc) = *((rsbac_old_uid_t *)old_desc);
+	return 0;
+}
+
+rsbac_list_conv_function_t *user_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_UM_USER_OLD_LIST_VERSION:
+		return user_conv;
+	case RSBAC_UM_USER_OLD_OLD_LIST_VERSION:
+		return user_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int user_subconv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	*((rsbac_gid_num_t *)new_desc) = *((rsbac_gid_num_t *)old_desc);
+	return 0;
+}
+
+static int user_old_subconv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	*((rsbac_gid_num_t *)new_desc) = *((rsbac_old_gid_t *)old_desc);
+	return 0;
+}
+
+rsbac_list_conv_function_t *user_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_UM_USER_OLD_LIST_VERSION:
+		return user_subconv;
+	case RSBAC_UM_USER_OLD_OLD_LIST_VERSION:
+		return user_old_subconv;
+	default:
+		return NULL;
+	}
+}
+
+static int group_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_um_group_entry_t * new_aci = new_data;
+	struct rsbac_um_old_group_entry_t * old_aci = old_data;
+
+	memcpy(&new_aci->name, &old_aci->name, RSBAC_UM_OLD_NAME_LEN);
+	memcpy(&new_aci->pass, &old_aci->pass, RSBAC_UM_PASS_LEN);
+	*((rsbac_gid_t *)new_desc) = *((rsbac_gid_t *)old_desc);
+	return 0;
+}
+
+static int group_old_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	struct rsbac_um_group_entry_t * new_aci = new_data;
+	struct rsbac_um_old_group_entry_t * old_aci = old_data;
+
+	memcpy(&new_aci->name, &old_aci->name, RSBAC_UM_OLD_NAME_LEN);
+	memcpy(&new_aci->pass, &old_aci->pass, RSBAC_UM_PASS_LEN);
+	*((rsbac_gid_t *)new_desc) = *((rsbac_old_gid_t *)old_desc);
+	return 0;
+}
+
+rsbac_list_conv_function_t *group_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_UM_GROUP_OLD_LIST_VERSION:
+		return group_conv;
+	case RSBAC_UM_GROUP_OLD_OLD_LIST_VERSION:
+		return group_old_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int user_pwh_conv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_data, old_data, sizeof(__u8));
+	*((rsbac_uid_t *) new_desc) = *((rsbac_old_uid_t *) old_desc);
+	return 0;
+}
+
+rsbac_list_conv_function_t *user_pwh_get_conv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_UM_USER_PWHISTORY_OLD_LIST_VERSION:
+		return user_pwh_conv;
+	default:
+		return NULL;
+	}
+}
+
+static int user_pwh_subconv(void *old_desc,
+		       void *old_data, void *new_desc, void *new_data)
+{
+	memcpy(new_desc, old_desc, sizeof(__u32));
+	memcpy(new_data, old_data, RSBAC_UM_PASS_LEN);
+	return 0;
+}
+
+rsbac_list_conv_function_t *user_pwh_get_subconv(rsbac_version_t old_version)
+{
+	switch (old_version) {
+	case RSBAC_UM_USER_PWHISTORY_OLD_LIST_VERSION:
+		return user_pwh_subconv;
+	default:
+		return NULL;
+	}
+}
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+static int vset_selector(void *desc, void * param)
+{
+  if (RSBAC_UID_SET(*((rsbac_uid_t *) desc)) == *((rsbac_um_set_t *) param))
+    return TRUE;
+  else
+    return FALSE;
+}
+#endif
+
+#if defined(CONFIG_RSBAC_PROC)
+static int
+stats_um_proc_show(struct seq_file *m, void *v)
+{
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "stats_um_proc_info(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	rsbac_pr_debug(aef_um, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	seq_printf(m, "UM Status\n---------\n");
+	seq_printf(m,
+		   "%lu user items with sum of %lu group memberships, %lu group items\n",
+		   rsbac_list_lol_count(user_handle), rsbac_list_lol_all_subcount(user_handle), rsbac_list_count(group_handle));
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	seq_printf(m,
+		   "user name cache: %lu cache items, %lu hits, %lu misses, hm-ratio %lu\n",
+		   rsbac_list_count(uid_cache_handle), uid_cache_hits, uid_cache_misses, uid_cache_misses ? uid_cache_hits / uid_cache_misses : 0);
+	seq_printf(m,
+		   "group name cache: %lu cache items, %lu hits, %lu misses, hm-ratio %lu\n",
+		   rsbac_list_count(gid_cache_handle), gid_cache_hits, gid_cache_misses, gid_cache_misses ? gid_cache_hits / gid_cache_misses : 0);
+	seq_printf(m,
+		   "name cache ttl is %u\n", rsbac_um_name_cache_ttl);
+	if (rsbac_um_name_cache_disable)
+		seq_printf(m,
+			   "name cache is disabled!\n");
+#endif
+	return 0;
+}
+
+static int stats_um_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stats_um_proc_show, NULL);
+}
+
+static const struct file_operations stats_um_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = stats_um_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *stats_um;
+
+#endif				/* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */
+
+static int name_compare(void *data1, void *data2)
+{
+	struct rsbac_um_user_entry_t *entry_p = data1;
+	char *name = data2;
+
+	if (!entry_p || !name)
+		return 1;
+
+	return strcmp(entry_p->name, name);
+}
+
+static int group_name_compare(void *data1, void *data2)
+{
+	struct rsbac_um_group_entry_t *entry_p = data1;
+	char *name = data2;
+
+	if (!entry_p || !name)
+		return 1;
+
+	return strcmp(entry_p->name, name);
+}
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+static int name_cache_compare(void *data1, void *data2)
+{
+	struct rsbac_um_name_cache_desc_t *desc1_p = data1;
+	struct rsbac_um_name_cache_desc_t *desc2_p = data2;
+
+	if (!desc1_p || !desc2_p)
+		return 1;
+
+	if (desc1_p->vset < desc2_p->vset)
+		return -1;
+	else if (desc1_p->vset > desc2_p->vset)
+		return 1;
+	else
+		return strcmp(desc1_p->name, desc2_p->name);
+}
+#else
+static int name_cache_compare(void *data1, void *data2)
+{
+	return strcmp((char *) data1, (char *) data2);
+}
+#endif
+
+u_int rsbac_list_hash_name_cache(void * desc, __u8 hash_bits)
+{
+	u_int hash = 0;
+	char * p = desc;
+
+	while (*p) {
+		hash += *p;
+		p++;
+	}
+	return hash_32(hash, rsbac_min(hash_bits, 32));
+}
+#endif
+
+/************************************************* */
+/*               Init functions                    */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac/error.h.                 */
+
+/************************************************************************** */
+/* Initialization of all MAC data structures. After this call, all MAC    */
+/* data is kept in memory for performance reasons, but is written to disk   */
+/* on every change. */
+
+/* Because there can be no access to aci data structures before init,       */
+/* rsbac_init_mac() will initialize all rw-spinlocks to unlocked.          */
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int rsbac_init_um(void)
+#else
+int __init rsbac_init_um(void)
+#endif
+{
+	int err = 0;
+	struct rsbac_list_info_t *list_info_p;
+	struct rsbac_list_lol_info_t *lol_info_p;
+
+	if (rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_init_um(): RSBAC already initialized\n");
+		return (-RSBAC_EREINIT);
+	}
+
+	/* set rw-spinlocks to unlocked status and init data structures */
+	rsbac_printk(KERN_INFO "rsbac_init_um(): Initializing RSBAC: User Management subsystem\n");
+
+	list_info_p = rsbac_kmalloc_unlocked(sizeof(*list_info_p));
+	if (!list_info_p) {
+		return -ENOMEM;
+	}
+	lol_info_p = rsbac_kmalloc_unlocked(sizeof(*lol_info_p));
+	if (!lol_info_p) {
+		rsbac_kfree(list_info_p);
+		return -ENOMEM;
+	}
+
+	lol_info_p->version = RSBAC_UM_USER_LIST_VERSION;
+	lol_info_p->key = RSBAC_UM_USER_LIST_KEY;
+	lol_info_p->desc_size = sizeof(rsbac_uid_t);
+	lol_info_p->data_size = sizeof(struct rsbac_um_user_entry_t);
+	lol_info_p->subdesc_size = sizeof(rsbac_gid_num_t);
+	lol_info_p->subdata_size = 0;
+	lol_info_p->max_age = 0;
+	nr_user_hash_bits = RSBAC_UM_NR_USER_LIST_HASH_BITS;
+
+	err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+				&user_handle, lol_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+				RSBAC_LIST_BACKUP |
+#endif
+				RSBAC_LIST_PERSIST |
+				RSBAC_LIST_REPLICATE |
+				RSBAC_LIST_AUTO_HASH_RESIZE |
+				RSBAC_LIST_OWN_SLAB,
+				NULL, NULL,
+				user_get_conv,
+				user_get_subconv,
+				NULL, NULL,
+				RSBAC_UM_USER_LIST_NAME,
+				RSBAC_AUTO_DEV,
+				nr_user_hash_bits,
+				rsbac_list_hash_uid,
+				RSBAC_UM_OLD_USER_LIST_NAME);
+	if (err) {
+		char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering user list of lists %s failed with error %s\n",
+				     RSBAC_UM_USER_LIST_NAME, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+
+	list_info_p->version = RSBAC_UM_GROUP_LIST_VERSION;
+	list_info_p->key = RSBAC_UM_GROUP_LIST_KEY;
+	list_info_p->desc_size = sizeof(rsbac_gid_t);
+	list_info_p->data_size = sizeof(struct rsbac_um_group_entry_t);
+	list_info_p->max_age = 0;
+	nr_group_hash_bits = RSBAC_UM_NR_GROUP_LIST_HASH_BITS;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				&group_handle, list_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+				RSBAC_LIST_BACKUP |
+#endif
+				RSBAC_LIST_PERSIST |
+				RSBAC_LIST_REPLICATE |
+				RSBAC_LIST_AUTO_HASH_RESIZE |
+				RSBAC_LIST_OWN_SLAB,
+				NULL,
+				group_get_conv,
+				NULL, RSBAC_UM_GROUP_LIST_NAME,
+				RSBAC_AUTO_DEV,
+				nr_group_hash_bits,
+				rsbac_list_hash_gid,
+				RSBAC_UM_OLD_GROUP_LIST_NAME);
+	if (err) {
+		char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering group list %s failed with error %s\n",
+				     RSBAC_UM_GROUP_LIST_NAME, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+	{
+		__u8 def_max_history = CONFIG_RSBAC_UM_PWHISTORY_MAX;
+
+		lol_info_p->version = RSBAC_UM_USER_PWHISTORY_LIST_VERSION;
+		lol_info_p->key = RSBAC_UM_USER_PWHISTORY_LIST_KEY;
+		lol_info_p->desc_size = sizeof(rsbac_uid_t);
+		lol_info_p->data_size = sizeof(__u8);
+		lol_info_p->subdesc_size = sizeof(__u32);
+		lol_info_p->subdata_size = RSBAC_UM_PASS_LEN;
+		lol_info_p->max_age = 0;
+		nr_user_pwhistory_hash_bits = RSBAC_UM_NR_USER_LIST_HASH_BITS;
+		err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+						&user_pwhistory_handle,
+						lol_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+						RSBAC_LIST_BACKUP |
+#endif
+						RSBAC_LIST_PERSIST |
+						RSBAC_LIST_DEF_DATA |
+						RSBAC_LIST_AUTO_HASH_RESIZE,
+						NULL, NULL,
+						user_pwh_get_conv, user_pwh_get_subconv,
+						&def_max_history, NULL,
+						RSBAC_UM_USER_PWHISTORY_LIST_NAME,
+						RSBAC_AUTO_DEV,
+						nr_user_pwhistory_hash_bits,
+						rsbac_list_hash_uid,
+						RSBAC_UM_OLD_USER_PWHISTORY_LIST_NAME);
+		if (err) {
+			char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering user password history list of lists %s failed with error %s\n",
+					     RSBAC_UM_USER_PWHISTORY_LIST_NAME,
+					     get_error_name(tmp,
+							    err));
+				rsbac_kfree(tmp);
+			}
+		}
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_UM_ONETIME
+	{
+		lol_info_p->version = RSBAC_UM_ONETIME_LIST_VERSION;
+		lol_info_p->key = RSBAC_UM_ONETIME_LIST_KEY;
+		lol_info_p->desc_size = sizeof(rsbac_uid_t);
+		lol_info_p->data_size = 0;
+		lol_info_p->subdesc_size = RSBAC_UM_PASS_LEN;
+		lol_info_p->subdata_size = 0;
+		lol_info_p->max_age = 0;
+		err = rsbac_list_lol_register_hashed(RSBAC_LIST_VERSION,
+						&onetime_handle,
+						lol_info_p,
+#ifdef CONFIG_RSBAC_DEV_USER_BACKUP
+						RSBAC_LIST_BACKUP |
+#endif
+						RSBAC_LIST_PERSIST |
+						RSBAC_LIST_DEF_DATA |
+						RSBAC_LIST_AUTO_HASH_RESIZE |
+						RSBAC_LIST_OWN_SLAB,
+						NULL, NULL,
+						NULL, NULL, /* conv */
+						NULL, NULL,
+						RSBAC_UM_ONETIME_LIST_NAME,
+						RSBAC_AUTO_DEV,
+						1,
+						rsbac_list_hash_uid,
+						NULL);
+		if (err) {
+			char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+			if (tmp) {
+				rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering user password one-time list of lists %s failed with error %s\n",
+					     RSBAC_UM_USER_PWHISTORY_LIST_NAME,
+					     get_error_name(tmp,
+							    err));
+				rsbac_kfree(tmp);
+			}
+		} else {
+			rsbac_list_lol_max_items(onetime_handle,
+				RSBAC_UM_ONETIME_LIST_KEY,
+				RSBAC_LIST_MAX_NR_ITEMS,
+				CONFIG_RSBAC_UM_ONETIME_MAX);
+		}
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	list_info_p->version = RSBAC_UM_NAME_CACHE_LIST_VERSION;
+	list_info_p->key = RSBAC_UM_UID_CACHE_LIST_KEY;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	list_info_p->desc_size = sizeof(struct rsbac_um_name_cache_desc_t);
+#else
+	list_info_p->desc_size = RSBAC_UM_NAME_LEN;
+#endif
+	list_info_p->data_size = sizeof(rsbac_uid_t);
+	list_info_p->max_age = 0;
+	nr_uid_cache_hash_bits = RSBAC_UM_NR_NAME_CACHE_LIST_HASH_BITS;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				&uid_cache_handle, list_info_p,
+				RSBAC_LIST_AUTO_HASH_RESIZE |
+				RSBAC_LIST_OWN_SLAB,
+				name_cache_compare,
+				NULL,
+				NULL, RSBAC_UM_UID_CACHE_LIST_NAME,
+				RSBAC_AUTO_DEV,
+				nr_uid_cache_hash_bits,
+				rsbac_list_hash_name_cache,
+				NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering user name cache list %s failed with error %s\n",
+				     RSBAC_UM_UID_CACHE_LIST_NAME, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+
+	list_info_p->version = RSBAC_UM_NAME_CACHE_LIST_VERSION;
+	list_info_p->key = RSBAC_UM_GID_CACHE_LIST_KEY;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	list_info_p->desc_size = sizeof(struct rsbac_um_name_cache_desc_t);
+#else
+	list_info_p->desc_size = RSBAC_UM_NAME_LEN;
+#endif
+	list_info_p->data_size = sizeof(rsbac_gid_t);
+	list_info_p->max_age = 0;
+	nr_gid_cache_hash_bits = RSBAC_UM_NR_NAME_CACHE_LIST_HASH_BITS;
+	err = rsbac_list_register_hashed(RSBAC_LIST_VERSION,
+				&gid_cache_handle, list_info_p,
+				RSBAC_LIST_AUTO_HASH_RESIZE |
+				RSBAC_LIST_OWN_SLAB,
+				name_cache_compare,
+				NULL,
+				NULL, RSBAC_UM_GID_CACHE_LIST_NAME,
+				RSBAC_AUTO_DEV,
+				nr_gid_cache_hash_bits,
+				rsbac_list_hash_name_cache,
+				NULL);
+	if (err) {
+		char *tmp = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+
+		if (tmp) {
+			rsbac_printk(KERN_WARNING "rsbac_init_um(): Registering group name cache list %s failed with error %s\n",
+				     RSBAC_UM_GID_CACHE_LIST_NAME, get_error_name(tmp, err));
+			rsbac_kfree(tmp);
+		}
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_PROC)
+	stats_um = proc_create("stats_um", S_IFREG | S_IRUGO,
+					proc_rsbac_root_p, &stats_um_proc_fops);
+#endif
+
+	rsbac_pr_debug(ds_um, "Ready.\n");
+	rsbac_kfree(list_info_p);
+	rsbac_kfree(lol_info_p);
+	return err;
+}
+
+/***************************************************/
+/* We also need some status information...         */
+
+int rsbac_stats_um(void)
+{
+	u_long user_count;
+	u_long group_count;
+	u_long member_count;
+
+	union rsbac_target_id_t rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_stats_um(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	rsbac_pr_debug(aef_um, "calling ADF\n");
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if (!rsbac_adf_request(R_GET_STATUS_DATA,
+			       task_pid(current),
+			       T_SCD,
+			       rsbac_target_id,
+			       A_none, rsbac_attribute_value)) {
+		return -EPERM;
+	}
+
+	user_count = rsbac_list_lol_count(user_handle);
+	member_count = rsbac_list_lol_all_subcount(user_handle);
+	group_count = rsbac_list_count(group_handle);
+	rsbac_printk(KERN_INFO "UM Status\n---------\n");
+
+	rsbac_printk(KERN_INFO "%lu user items with sum of %lu group memberships, %lu group items\n",
+		     user_count, member_count, group_count);
+	return 0;
+}
+
+/************************************************* */
+/*               Access functions                  */
+/************************************************* */
+
+/* Trying to access a never created or removed user entry returns an error! */
+#ifndef offset_in_page
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+#endif
+
+static inline void new_salt(__u32 * salt_p)
+{
+	*salt_p = 0;
+	while (!*salt_p)
+		get_random_bytes(salt_p, sizeof(*salt_p));
+}
+
+int rsbac_um_hash(char *pass, __u32 salt)
+{
+#ifdef CONFIG_RSBAC_UM_DIGEST
+	char *buffer;
+	struct scatterlist sg[1];
+	struct crypto_hash *tfm;
+	struct hash_desc hd;
+	u_int len;
+	u_int plen;
+	int err = 0;
+
+	plen = strlen(pass);
+	len = rsbac_max(plen + sizeof(salt), RSBAC_UM_PASS_LEN);
+	buffer = rsbac_kmalloc_clear_unlocked(len);
+	if (!buffer)
+		return -RSBAC_ENOMEM;
+
+	if (!crypto_has_hash("sha1", 0, 0)) {
+		rsbac_printk(KERN_WARNING "rsbac_um_hash(): User management configured for crypto API with SHA1, but SHA1 is not available!\n");
+		err = -RSBAC_ENOTFOUND;
+		goto out;
+	}
+
+	tfm = crypto_alloc_hash("sha1", 0, 0);
+	if (!tfm) {
+		rsbac_printk(KERN_WARNING "pid %u(%s): rsbac_um_hash(): Could not allocate tfm for SHA1!\n",
+			current->pid, current->comm);
+		err = -RSBAC_ENOTFOUND;
+		goto out;
+	}
+	memcpy(buffer, &salt, sizeof(salt));
+	memcpy(buffer + sizeof(salt), pass, plen);
+	sg_init_one(sg, buffer, plen + sizeof(salt));
+
+	hd.tfm = tfm;
+	hd.flags = 0;
+	err = crypto_hash_init(&hd);
+	if(err) {
+		rsbac_printk(KERN_WARNING "pid %u(%s): rsbac_um_hash(): crypto_hash_init() failed with error %u!\n",
+			current->pid, current->comm, err);
+		goto out;
+	}
+	err = crypto_hash_update(&hd, sg, sg[0].length);
+	if(err) {
+		rsbac_printk(KERN_WARNING "pid %u(%s): rsbac_um_hash(): crypto_hash_update() failed with error %u!\n",
+			current->pid, current->comm, err);
+		goto out;
+	}
+	err = crypto_hash_final(&hd, pass);
+	if(err) {
+		rsbac_printk(KERN_WARNING "pid %u(%s): rsbac_um_hash(): crypto_hash_final() failed with error %u!\n",
+			current->pid, current->comm, err);
+		goto out;
+	}
+	crypto_free_hash(tfm);
+out:
+	rsbac_kfree(buffer);
+	return err;
+#else
+	/* no crypto: just zero rest of string to allow comparizon */
+	u_int len;
+
+	len = strlen(pass);
+	if (len < RSBAC_UM_PASS_LEN)
+		memset(pass + len, 0, RSBAC_UM_PASS_LEN - len);
+	return 0;
+#endif
+}
+
+int rsbac_um_get_uid(rsbac_list_ta_number_t ta_number,
+			char *name,
+			rsbac_uid_t * uid_p)
+{
+	int err;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	rsbac_um_set_t vset;
+#endif
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	rsbac_time_t ttl;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	struct rsbac_um_name_cache_desc_t cache_desc;
+#endif
+#endif
+
+	if (!name || !uid_p)
+		return -RSBAC_EINVALIDPOINTER;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	vset = RSBAC_UID_SET(*uid_p);
+	if (vset == RSBAC_UM_VIRTUAL_KEEP) {
+		char * p = name;
+
+		while (*p && (*p != '/'))
+			p++;
+		if (*p) {
+			*p = 0;
+			err = rsbac_get_vset_num(name, &vset);
+			if (err)
+				return err;
+			p++;
+			name = p;
+			if (vset == RSBAC_UM_VIRTUAL_KEEP)
+				vset = rsbac_get_vset();
+		} else
+			vset = rsbac_get_vset();
+	}
+	if (!strcmp(name, "ALL")) {
+		*uid_p = RSBAC_GEN_UID(vset, RSBAC_ALL_USERS);
+		return 0;
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	if (!rsbac_um_name_cache_disable) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if (vset != RSBAC_UM_VIRTUAL_ALL)
+			cache_desc.vset = vset;
+		else
+			cache_desc.vset = 0;
+		memcpy(cache_desc.name, name, RSBAC_UM_NAME_LEN);
+		if (!rsbac_ta_list_get_data_ttl(ta_number,
+						uid_cache_handle,
+						&ttl, &cache_desc, uid_p)) {
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u/%u (%s) found in name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_UID_SET(*uid_p), RSBAC_UID_NUM(*uid_p), cache_desc.name, ttl);
+			uid_cache_hits++;
+			return 0;
+		}
+#else
+		if (!rsbac_ta_list_get_data_ttl(ta_number,
+						uid_cache_handle,
+						&ttl, name, uid_p)) {
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u (%s) found in name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_UID_NUM(*uid_p), name, ttl);
+			uid_cache_hits++;
+			return 0;
+		}
+#endif
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if (vset != RSBAC_UM_VIRTUAL_ALL)
+		err = rsbac_ta_list_lol_get_desc_selector_ttl(ta_number,
+					user_handle,
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+					&ttl,
+#else
+					NULL,
+#endif
+					uid_p,
+					name,
+					name_compare,
+					vset_selector,
+					&vset);
+	else
+#endif
+		err = rsbac_ta_list_lol_get_desc_ttl(ta_number,
+					user_handle,
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+					&ttl,
+#else
+					NULL,
+#endif
+					uid_p,
+					name,
+					name_compare);
+
+	if (!err) {
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+		if (!rsbac_um_name_cache_disable) {
+			if (ttl > 0)
+				ttl = rsbac_min(ttl, rsbac_um_name_cache_ttl);
+			else
+				ttl = rsbac_um_name_cache_ttl;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if (vset != RSBAC_UM_VIRTUAL_ALL)
+				cache_desc.vset = vset;
+			else
+				cache_desc.vset = 0;
+			memcpy(cache_desc.name, name, RSBAC_UM_NAME_LEN);
+			rsbac_ta_list_add_ttl(ta_number,
+						uid_cache_handle,
+						ttl,
+						&cache_desc, uid_p);
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u/%u (%s) added to name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_UID_SET(*uid_p), RSBAC_UID_NUM(*uid_p), cache_desc.name, ttl);
+			uid_cache_misses++;
+#else
+			rsbac_ta_list_add_ttl(ta_number,
+						uid_cache_handle,
+						ttl,
+						name, uid_p);
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u (%s) added to name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_UID_NUM(*uid_p), name, ttl);
+			uid_cache_misses++;
+#endif
+		}
+#endif
+
+		return 0;
+	} else
+		return -RSBAC_ENOTFOUND;
+}
+
+int rsbac_um_get_gid(rsbac_list_ta_number_t ta_number,
+		     char *name, rsbac_gid_t * gid_p)
+{
+	int err;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	rsbac_um_set_t vset;
+#endif
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	rsbac_time_t ttl;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	struct rsbac_um_name_cache_desc_t cache_desc;
+#endif
+#endif
+
+	if (!name || !gid_p)
+		return -RSBAC_EINVALIDPOINTER;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	vset = RSBAC_GID_SET(*gid_p);
+	if (vset == RSBAC_UM_VIRTUAL_KEEP) {
+		char * p = name;
+
+		while (*p && (*p != '/'))
+			p++;
+		if (*p) {
+			*p = 0;
+			err = rsbac_get_vset_num(name, &vset);
+			if (err)
+				return err;
+			p++;
+			name = p;
+			if (vset == RSBAC_UM_VIRTUAL_KEEP)
+				vset = rsbac_get_vset();
+		} else
+			vset = rsbac_get_vset();
+	}
+	if (!strcmp(name, "ALL")) {
+		*gid_p = RSBAC_GEN_GID(vset, RSBAC_ALL_GROUPS);
+		return 0;
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	if (!rsbac_um_name_cache_disable) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if (vset != RSBAC_UM_VIRTUAL_ALL)
+			cache_desc.vset = vset;
+		else
+			cache_desc.vset = 0;
+		memcpy(cache_desc.name, name, RSBAC_UM_NAME_LEN);
+		if (!rsbac_ta_list_get_data_ttl(ta_number,
+						gid_cache_handle,
+						&ttl, &cache_desc, gid_p)) {
+			rsbac_pr_debug(aef_um, "pid %u(%s): group %u/%u (%s) found in name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_GID_SET(*gid_p), RSBAC_GID_NUM(*gid_p), cache_desc.name, ttl);
+			gid_cache_hits++;
+			return 0;
+		}
+#else
+		if (!rsbac_ta_list_get_data_ttl(ta_number,
+						gid_cache_handle,
+						&ttl, name, gid_p)) {
+			rsbac_pr_debug(aef_um, "pid %u(%s): group %u (%s) found in name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_GID_NUM(*gid_p), name, ttl);
+			gid_cache_hits++;
+			return 0;
+		}
+#endif
+	}
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if (vset != RSBAC_UM_VIRTUAL_ALL)
+		err = rsbac_ta_list_get_desc_selector_ttl(ta_number,
+					group_handle,
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+					&ttl,
+#else
+					NULL,
+#endif
+					gid_p,
+					name,
+					group_name_compare,
+					vset_selector,
+					&vset);
+	else
+#endif
+		err = rsbac_ta_list_get_desc_ttl(ta_number,
+					group_handle,
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+					&ttl,
+#else
+					NULL,
+#endif
+					gid_p,
+					name, group_name_compare);
+
+	if (!err) {
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+		if (!rsbac_um_name_cache_disable) {
+			if (ttl > 0)
+				ttl = rsbac_min(ttl, rsbac_um_name_cache_ttl);
+			else
+				ttl = rsbac_um_name_cache_ttl;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if (vset != RSBAC_UM_VIRTUAL_ALL)
+				cache_desc.vset = vset;
+			else
+				cache_desc.vset = 0;
+			memcpy(cache_desc.name, name, RSBAC_UM_NAME_LEN);
+			rsbac_ta_list_add_ttl(ta_number,
+						gid_cache_handle,
+						ttl,
+						&cache_desc, gid_p);
+			rsbac_pr_debug(aef_um, "pid %u(%s): group %u/%u (%s) added to name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_GID_SET(*gid_p), RSBAC_GID_NUM(*gid_p), cache_desc.name, ttl);
+			gid_cache_misses++;
+#else
+			rsbac_ta_list_add_ttl(ta_number,
+						gid_cache_handle,
+						ttl,
+						name, gid_p);
+			rsbac_pr_debug(aef_um, "pid %u(%s): group %u (%s) added to name cache with ttl %u\n",
+					current->pid, current->comm, RSBAC_GID_NUM(*gid_p), name, ttl);
+			gid_cache_misses++;
+#endif
+		}
+#endif
+
+		return 0;
+	} else
+		return -RSBAC_ENOTFOUND;
+}
+
+int rsbac_um_add_user(rsbac_list_ta_number_t ta_number,
+		      rsbac_uid_t * user_p,
+		      struct rsbac_um_user_entry_t *entry_p,
+		      char *pass, rsbac_time_t ttl)
+{
+	int err;
+	rsbac_uid_t user;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_add_user(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (!entry_p || !user_p)
+		return -RSBAC_EINVALIDPOINTER;
+	user = *user_p;
+#ifdef CONFIG_RSBAC_UM_EXCL
+	if (!rsbac_um_no_excl) {
+	    rsbac_gid_t gid = RSBAC_GEN_GID(RSBAC_UID_SET(user),
+					entry_p->group);
+	    if (!rsbac_ta_list_exist(ta_number,
+				    group_handle,
+				    &gid)) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if (RSBAC_GID_SET(gid))
+			rsbac_printk(KERN_INFO "rsbac_um_add_user(): gid %u/%u not known to RSBAC User Management!\n",
+			     RSBAC_GID_SET(gid), entry_p->group);
+		else
+#endif
+			rsbac_printk(KERN_INFO "rsbac_um_add_user(): gid %u not known to RSBAC User Management!\n",
+			     entry_p->group);
+		return -RSBAC_EINVALIDVALUE;
+	    }
+	}
+#endif
+	if (RSBAC_UID_NUM(user) == RSBAC_NO_USER) {
+		user = RSBAC_GEN_UID(RSBAC_UID_SET(user),
+				CONFIG_RSBAC_UM_USER_MIN);
+		while (rsbac_ta_list_lol_exist
+		       (ta_number, user_handle, &user))
+			user++;
+	} else
+	    if (rsbac_ta_list_lol_exist
+		(ta_number, user_handle, &user))
+		return -RSBAC_EEXISTS;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if (RSBAC_UID_SET(user))
+		rsbac_pr_debug(aef_um, "pid %u(%s): adding user %u/%u\n",
+			current->pid, current->comm,
+			RSBAC_UID_SET(user), RSBAC_UID_NUM(user));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): adding user %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(user));
+	if (pass) {
+		__u32 salt;
+
+		new_salt(&salt);
+		err = rsbac_um_hash(pass, salt);
+		if (err)
+			return err;
+		memcpy(entry_p->pass, &salt, sizeof(salt));
+		memcpy(entry_p->pass + sizeof(salt), pass,
+		       RSBAC_UM_PASS_LEN - sizeof(salt));
+	} else
+		memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
+	err =
+	    rsbac_ta_list_lol_add_ttl(ta_number,
+				      user_handle, ttl,
+				      &user, entry_p);
+	if (!err)
+		*user_p = user;
+	return err;
+}
+
+int rsbac_um_add_group(rsbac_list_ta_number_t ta_number,
+		       rsbac_gid_t * group_p,
+		       struct rsbac_um_group_entry_t *entry_p,
+		       char *pass, rsbac_time_t ttl)
+{
+	int err;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_add_group(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (!entry_p || !group_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (RSBAC_GID_NUM(*group_p) == RSBAC_NO_USER) {
+		*group_p = RSBAC_GEN_GID(RSBAC_GID_SET(*group_p), CONFIG_RSBAC_UM_GROUP_MIN);
+		while (rsbac_ta_list_exist
+		       (ta_number, group_handle,
+			group_p))
+			(*group_p)++;
+	} else
+	    if (rsbac_ta_list_exist
+		(ta_number, group_handle, group_p))
+		return -RSBAC_EEXISTS;
+	if (RSBAC_GID_SET(*group_p))
+		rsbac_pr_debug(aef_um, "pid %u(%s): adding group %u/%u\n",
+			current->pid, current->comm,
+			RSBAC_GID_SET(*group_p), RSBAC_GID_NUM(*group_p));
+	else
+		rsbac_pr_debug(aef_um, "pid %u(%s): adding group %u\n",
+			current->pid, current->comm, RSBAC_GID_NUM(*group_p));
+	if (pass) {
+		__u32 salt;
+
+		new_salt(&salt);
+		err = rsbac_um_hash(pass, salt);
+		if (err)
+			return err;
+		memcpy(entry_p->pass, &salt, sizeof(salt));
+		memcpy(entry_p->pass + sizeof(salt), pass,
+		       RSBAC_UM_PASS_LEN - sizeof(salt));
+	} else
+		memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
+	return rsbac_ta_list_add_ttl(ta_number,
+				     group_handle,
+				     ttl, group_p, entry_p);
+}
+
+int rsbac_um_add_gm(rsbac_list_ta_number_t ta_number,
+		    rsbac_uid_t user, rsbac_gid_num_t group, rsbac_time_t ttl)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_add_gm(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+#ifdef CONFIG_RSBAC_UM_EXCL
+	if (!rsbac_um_no_excl) {
+        	rsbac_gid_t gid = RSBAC_GEN_GID(RSBAC_UID_SET(user),
+					group);
+
+		if (!rsbac_ta_list_exist
+		    (ta_number, user_handle, &user)) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if (RSBAC_UID_SET(user))
+				rsbac_printk(KERN_INFO "rsbac_um_add_gm(): uid %u/%u not known to RSBAC User Management!\n",
+				     RSBAC_UID_SET(user), RSBAC_UID_NUM(user));
+		else
+#endif
+			rsbac_printk(KERN_INFO "rsbac_um_add_gm(): uid %u not known to RSBAC User Management!\n",
+				     RSBAC_UID_SET(user));
+			return -RSBAC_ENOTFOUND;
+		}
+		if (!rsbac_ta_list_exist
+		    (ta_number, group_handle, &gid)) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if (RSBAC_GID_SET(gid))
+				rsbac_printk(KERN_INFO "rsbac_um_add_gm(): gid %u/%u not known to RSBAC User Management!\n",
+				     RSBAC_GID_SET(gid), group);
+		else
+#endif
+			rsbac_printk(KERN_INFO "rsbac_um_add_gm(): gid %u not known to RSBAC User Management!\n",
+				     group);
+			return -RSBAC_ENOTFOUND;
+		}
+	}
+#endif
+	rsbac_pr_debug(aef_um, "pid %u(%s): adding user %u group %u\n",
+		current->pid, current->comm, user, group);
+	return rsbac_ta_list_lol_subadd_ttl(ta_number,
+					    user_handle,
+					    ttl, &user, &group, NULL);
+}
+
+int rsbac_um_mod_user(rsbac_list_ta_number_t ta_number,
+		      rsbac_uid_t user,
+		      enum rsbac_um_mod_t mod,
+		      union rsbac_um_mod_data_t *data_p)
+{
+	int err;
+	struct rsbac_um_user_entry_t *entry_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_mod_user(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (!data_p && (mod != UM_pass)
+	    )
+		return -RSBAC_EINVALIDPOINTER;
+	if (!rsbac_ta_list_lol_exist
+	    (ta_number, user_handle, &user))
+		return -RSBAC_ENOTFOUND;
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err =
+	    rsbac_ta_list_lol_get_data_ttl(ta_number,
+					   user_handle,
+					   NULL, &user, entry_p);
+	if (err) {
+		rsbac_kfree(entry_p);
+		return err;
+	}
+	rsbac_pr_debug(aef_um, "pid %u(%s): modifying user %u\n",
+		current->pid, current->comm, user);
+	switch (mod) {
+	case UM_name:
+		{
+			rsbac_uid_t tmp_user = user;
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			struct rsbac_um_name_cache_desc_t cache_desc;
+#endif
+#endif
+
+			if (!rsbac_um_get_uid
+			    (ta_number, data_p->string, &tmp_user)
+			    && (tmp_user != user)
+			    )
+				return -RSBAC_EEXISTS;
+			strncpy(entry_p->name, data_p->string,
+				RSBAC_UM_NAME_LEN);
+			entry_p->name[RSBAC_UM_NAME_LEN - 1] = 0;
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			cache_desc.vset = RSBAC_UID_SET(user);
+			memcpy(cache_desc.name, entry_p->name, RSBAC_UM_NAME_LEN);
+			rsbac_ta_list_remove(ta_number,
+					    uid_cache_handle,
+					    &cache_desc);
+#else
+			rsbac_ta_list_remove(ta_number,
+					    uid_cache_handle,
+					    entry_p->name);
+#endif
+#endif
+		}
+		break;
+
+	case UM_pass:
+		if (data_p) {
+			__u32 salt;
+
+			new_salt(&salt);
+			err = rsbac_um_hash(data_p->string, salt);
+			if (err) {
+				rsbac_kfree(entry_p);
+				return err;
+			}
+			memcpy(entry_p->pass, &salt, sizeof(salt));
+			memcpy(entry_p->pass + sizeof(salt),
+			       data_p->string,
+			       RSBAC_UM_PASS_LEN - sizeof(salt));
+		} else
+			memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
+		entry_p->lastchange = RSBAC_CURRENT_TIME / 86400;
+		break;
+
+	case UM_cryptpass:
+		memcpy(entry_p->pass, data_p->string, RSBAC_UM_PASS_LEN);
+		break;
+
+	case UM_fullname:
+		strncpy(entry_p->fullname, data_p->string,
+			RSBAC_UM_FULLNAME_LEN);
+		entry_p->fullname[RSBAC_UM_FULLNAME_LEN - 1] = 0;
+		break;
+
+	case UM_homedir:
+		strncpy(entry_p->homedir, data_p->string,
+			RSBAC_UM_HOMEDIR_LEN);
+		entry_p->homedir[RSBAC_UM_HOMEDIR_LEN - 1] = 0;
+		break;
+
+	case UM_shell:
+		strncpy(entry_p->shell, data_p->string,
+			RSBAC_UM_SHELL_LEN);
+		entry_p->shell[RSBAC_UM_SHELL_LEN - 1] = 0;
+		break;
+
+	case UM_group:
+#ifdef CONFIG_RSBAC_UM_EXCL
+		{
+			rsbac_gid_t gid = RSBAC_GEN_GID(RSBAC_UID_SET(user),
+							data_p->group);
+			if (!rsbac_um_no_excl
+			    && !rsbac_ta_list_exist(ta_number,
+						    group_handle,
+						    &gid)) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if (RSBAC_GID_SET(gid))
+					rsbac_printk(KERN_INFO "rsbac_um_mod_user(): gid %u/%u not known to RSBAC User Management!\n",
+					     RSBAC_GID_SET(gid), RSBAC_GID_NUM(gid));
+				else
+#endif
+					rsbac_printk(KERN_INFO "rsbac_um_mod_user(): gid %u not known to RSBAC User Management!\n",
+					     RSBAC_GID_NUM(gid));
+				rsbac_kfree(entry_p);
+				return -RSBAC_EINVALIDVALUE;
+			}
+		}
+#endif
+		entry_p->group = data_p->group;
+		break;
+
+	case UM_lastchange:
+		entry_p->lastchange = data_p->days;
+		break;
+
+	case UM_minchange:
+		entry_p->minchange = data_p->days;
+		break;
+
+	case UM_maxchange:
+		entry_p->maxchange = data_p->days;
+		break;
+
+	case UM_warnchange:
+		entry_p->warnchange = data_p->days;
+		break;
+
+	case UM_inactive:
+		entry_p->inactive = data_p->days;
+		break;
+
+	case UM_expire:
+		entry_p->expire = data_p->days;
+		break;
+
+	case UM_ttl:
+		err =
+		    rsbac_ta_list_lol_add_ttl(ta_number,
+					      user_handle,
+					      data_p->ttl, &user, entry_p);
+		rsbac_kfree(entry_p);
+		return err;
+
+	default:
+		rsbac_kfree(entry_p);
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	err =
+	    rsbac_ta_list_lol_add_ttl(ta_number,
+				      user_handle,
+				      RSBAC_LIST_TTL_KEEP, &user, entry_p);
+	rsbac_kfree(entry_p);
+	return err;
+}
+
+int rsbac_um_mod_group(rsbac_list_ta_number_t ta_number,
+		       rsbac_uid_t group,
+		       enum rsbac_um_mod_t mod,
+		       union rsbac_um_mod_data_t *data_p)
+{
+	int err;
+	struct rsbac_um_group_entry_t *entry_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_mod_group(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (!data_p && (mod != UM_pass)
+	    )
+		return -RSBAC_EINVALIDPOINTER;
+	if (!rsbac_ta_list_exist
+	    (ta_number, group_handle, &group))
+		return -RSBAC_ENOTFOUND;
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err =
+	    rsbac_ta_list_get_data_ttl(ta_number,
+				       group_handle,
+				       NULL, &group, entry_p);
+	if (err) {
+		rsbac_kfree(entry_p);
+		return err;
+	}
+	rsbac_pr_debug(aef_um, "pid %u(%s): modifying group %u\n",
+		current->pid, current->comm, group);
+	switch (mod) {
+	case UM_name:
+		{
+			rsbac_gid_t tmp_group = group;
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			struct rsbac_um_name_cache_desc_t cache_desc;
+#endif
+#endif
+
+			if (!rsbac_um_get_gid
+			    (ta_number, data_p->string, &tmp_group)
+			    && (tmp_group != group)
+			    )
+				return -RSBAC_EEXISTS;
+			strncpy(entry_p->name, data_p->string,
+				RSBAC_UM_NAME_LEN);
+			entry_p->name[RSBAC_UM_NAME_LEN - 1] = 0;
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			cache_desc.vset = RSBAC_GID_SET(group);
+			memcpy(cache_desc.name, entry_p->name, RSBAC_UM_NAME_LEN);
+			rsbac_ta_list_remove(ta_number,
+					    gid_cache_handle,
+					    &cache_desc);
+#else
+			rsbac_ta_list_remove(ta_number,
+					    gid_cache_handle,
+					    entry_p->name);
+#endif
+#endif
+		}
+		break;
+
+	case UM_pass:
+		if (data_p) {
+			__u32 salt;
+
+			new_salt(&salt);
+			err = rsbac_um_hash(data_p->string, salt);
+			if (err) {
+				rsbac_kfree(entry_p);
+				return err;
+			}
+			memcpy(entry_p->pass, &salt, sizeof(salt));
+			memcpy(entry_p->pass + sizeof(salt),
+			       data_p->string,
+			       RSBAC_UM_PASS_LEN - sizeof(salt));
+		} else
+			memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
+		break;
+
+	case UM_cryptpass:
+		memcpy(entry_p->pass, data_p->string, RSBAC_UM_PASS_LEN);
+		break;
+
+	case UM_ttl:
+		err =
+		    rsbac_ta_list_add_ttl(ta_number,
+					  group_handle,
+					  data_p->ttl, &group, entry_p);
+		rsbac_kfree(entry_p);
+		return err;
+
+	default:
+		rsbac_kfree(entry_p);
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	err =
+	    rsbac_ta_list_add_ttl(ta_number,
+				  group_handle,
+				  RSBAC_LIST_TTL_KEEP, &group, entry_p);
+	rsbac_kfree(entry_p);
+	return err;
+}
+
+int rsbac_um_get_user_item(rsbac_list_ta_number_t ta_number,
+			   rsbac_uid_t user,
+			   enum rsbac_um_mod_t mod,
+			   union rsbac_um_mod_data_t *data_p)
+{
+	int err;
+	struct rsbac_um_user_entry_t *entry_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_get_user_item(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (!data_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!rsbac_ta_list_lol_exist
+	    (ta_number, user_handle, &user))
+		return -RSBAC_ENOTFOUND;
+	if (mod == UM_ttl)
+		return rsbac_ta_list_lol_get_data_ttl(ta_number,
+						      user_handle,
+						      &data_p->ttl, &user,
+						      NULL);
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err =
+	    rsbac_ta_list_lol_get_data_ttl(ta_number,
+					   user_handle,
+					   NULL, &user, entry_p);
+	if (err) {
+		rsbac_kfree(entry_p);
+		return err;
+	}
+	switch (mod) {
+	case UM_name:
+		strcpy(data_p->string, entry_p->name);
+		break;
+
+	case UM_pass:
+		memcpy(data_p->string, entry_p->pass, RSBAC_UM_PASS_LEN);
+		break;
+
+	case UM_fullname:
+		strcpy(data_p->string, entry_p->fullname);
+		break;
+
+	case UM_homedir:
+		strcpy(data_p->string, entry_p->homedir);
+		break;
+
+	case UM_shell:
+		strcpy(data_p->string, entry_p->shell);
+		break;
+
+	case UM_group:
+		data_p->group = entry_p->group;
+		break;
+
+	case UM_lastchange:
+		data_p->days = entry_p->lastchange;
+		break;
+
+	case UM_minchange:
+		data_p->days = entry_p->minchange;
+		break;
+
+	case UM_maxchange:
+		data_p->days = entry_p->maxchange;
+		break;
+
+	case UM_warnchange:
+		data_p->days = entry_p->warnchange;
+		break;
+
+	case UM_inactive:
+		data_p->days = entry_p->inactive;
+		break;
+
+	case UM_expire:
+		data_p->days = entry_p->expire;
+		break;
+
+	default:
+		rsbac_kfree(entry_p);
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rsbac_kfree(entry_p);
+	return 0;
+}
+
+int rsbac_um_get_group_item(rsbac_list_ta_number_t ta_number,
+			    rsbac_gid_t group,
+			    enum rsbac_um_mod_t mod,
+			    union rsbac_um_mod_data_t *data_p)
+{
+	int err;
+	struct rsbac_um_group_entry_t *entry_p;
+
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_get_group_item(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	if (!data_p)
+		return -RSBAC_EINVALIDPOINTER;
+	if (!rsbac_ta_list_exist
+	    (ta_number, group_handle, &group))
+		return -RSBAC_ENOTFOUND;
+	if (mod == UM_ttl)
+		return rsbac_ta_list_get_data_ttl(ta_number,
+						  group_handle,
+						  &data_p->ttl, &group,
+						  NULL);
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err =
+	    rsbac_ta_list_get_data_ttl(ta_number,
+				       group_handle,
+				       NULL, &group, entry_p);
+	if (err) {
+		rsbac_kfree(entry_p);
+		return err;
+	}
+	switch (mod) {
+	case UM_name:
+		strcpy(data_p->string, entry_p->name);
+		break;
+
+	case UM_pass:
+		memcpy(data_p->string, entry_p->pass, RSBAC_UM_PASS_LEN);
+		break;
+
+	default:
+		rsbac_kfree(entry_p);
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	rsbac_kfree(entry_p);
+	return 0;
+}
+
+int rsbac_um_user_exists(rsbac_list_ta_number_t ta_number,
+			 rsbac_uid_t user)
+{
+	return rsbac_ta_list_lol_exist(ta_number,
+				       user_handle,
+				       &user);
+}
+
+int rsbac_um_group_exists(rsbac_list_ta_number_t ta_number,
+			  rsbac_gid_t group)
+{
+	return rsbac_ta_list_exist(ta_number,
+				   group_handle,
+				   &group);
+}
+
+int rsbac_um_remove_user(rsbac_list_ta_number_t ta_number,
+			 rsbac_uid_t user)
+{
+	int err;
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	struct rsbac_um_user_entry_t entry;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	struct rsbac_um_name_cache_desc_t cache_desc;
+#else
+	char cache_name[RSBAC_UM_NAME_LEN];
+#endif
+#endif
+
+	if (!rsbac_ta_list_lol_exist
+	    (ta_number, user_handle, &user))
+		return -RSBAC_ENOTFOUND;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(user))
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing user %u/%u\n",
+			current->pid, current->comm, RSBAC_UID_SET(user), RSBAC_UID_NUM(user));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing user %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(user));
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	if (rsbac_ta_list_lol_get_data_ttl(ta_number,
+				    user_handle,
+				    NULL,
+				    &user,
+				    &entry)) {
+		entry.name[0] = 0;
+	}
+#endif
+
+	err = rsbac_ta_list_lol_remove(ta_number,
+					user_handle,
+					&user);
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if (entry.name[0]) {
+		cache_desc.vset = RSBAC_UID_SET(user);
+		strncpy(cache_desc.name, entry.name, RSBAC_UM_NAME_LEN);
+		cache_desc.name[RSBAC_UM_NAME_LEN - 1] = 0;
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing user %u/%u (%s) name cache entry\n",
+				current->pid, current->comm, RSBAC_UID_SET(user), RSBAC_UID_NUM(user), cache_desc.name);
+		rsbac_ta_list_remove(ta_number,
+				    uid_cache_handle,
+				    &cache_desc);
+	}
+#else
+	if (entry.name[0]) {
+		strncpy(cache_name, entry.name, RSBAC_UM_NAME_LEN);
+		cache_name[RSBAC_UM_NAME_LEN - 1] = 0;
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing user %u (%s) name cache entry\n",
+				current->pid, current->comm, RSBAC_UID_NUM(user), cache_name);
+		rsbac_ta_list_remove(ta_number,
+				    uid_cache_handle,
+				    cache_name);
+	}
+#endif
+#endif
+
+	return err;
+}
+
+int rsbac_um_remove_group(rsbac_list_ta_number_t ta_number,
+			  rsbac_gid_t group)
+{
+	int err;
+	rsbac_gid_num_t group_num;
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	struct rsbac_um_group_entry_t entry;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	struct rsbac_um_name_cache_desc_t cache_desc;
+#else
+	char cache_name[RSBAC_UM_NAME_LEN];
+#endif
+#endif
+
+	if (!rsbac_ta_list_exist
+	    (ta_number, group_handle, &group))
+		return -RSBAC_ENOTFOUND;
+	group_num = RSBAC_GID_NUM(group);
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(group))
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing group %u/%u\n",
+			current->pid, current->comm, RSBAC_GID_SET(group), group_num);
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing group %u\n",
+			current->pid, current->comm, group_num);
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+	if (rsbac_ta_list_get_data_ttl(ta_number,
+				    group_handle,
+				    NULL,
+				    &group,
+				    &entry)) {
+		entry.name[0] = 0;
+	}
+#endif
+
+	rsbac_ta_list_lol_subremove_from_all(ta_number,
+					     user_handle,
+					     &group_num);
+	err = rsbac_ta_list_remove(ta_number,
+				    group_handle,
+				    &group);
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if (entry.name[0]) {
+		cache_desc.vset = RSBAC_GID_SET(group);
+		strncpy(cache_desc.name, entry.name, RSBAC_UM_NAME_LEN);
+		cache_desc.name[RSBAC_UM_NAME_LEN - 1] = 0;
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing group %u/%u (%s) name cache entry\n",
+				current->pid, current->comm, RSBAC_GID_SET(group), RSBAC_GID_NUM(group), cache_desc.name);
+		rsbac_ta_list_remove(ta_number,
+				    gid_cache_handle,
+				    &cache_desc);
+	}
+#else
+	if (entry.name[0]) {
+		strncpy(cache_name, entry.name, RSBAC_UM_NAME_LEN);
+		cache_name[RSBAC_UM_NAME_LEN - 1] = 0;
+		rsbac_pr_debug(aef_um, "pid %u(%s): removing group %u (%s) name cache entry\n",
+				current->pid, current->comm, RSBAC_GID_NUM(group), cache_name);
+		rsbac_ta_list_remove(ta_number,
+				    gid_cache_handle,
+				    cache_name);
+	}
+#endif
+#endif
+
+	return err;
+}
+
+int rsbac_um_remove_gm(rsbac_list_ta_number_t ta_number,
+		       rsbac_uid_t user, rsbac_gid_num_t group)
+{
+	if (!rsbac_is_initialized()) {
+		rsbac_printk(KERN_WARNING "rsbac_um_remove_gm(): RSBAC not initialized\n");
+		return (-RSBAC_ENOTINITIALIZED);
+	}
+	rsbac_pr_debug(aef_um, "pid %u(%s): removing user %u group %u\n",
+		current->pid, current->comm, user, group);
+	return rsbac_ta_list_lol_subremove(ta_number,
+					   user_handle,
+					   &user, &group);
+}
+
+int rsbac_um_get_user_entry(rsbac_list_ta_number_t ta_number,
+			    rsbac_uid_t user,
+			    struct rsbac_um_user_entry_t *entry_p,
+			    rsbac_time_t * ttl_p)
+{
+	return rsbac_ta_list_lol_get_data_ttl(ta_number,
+					      user_handle,
+					      ttl_p, &user, entry_p);
+}
+
+int rsbac_um_get_next_user(rsbac_list_ta_number_t ta_number,
+			   rsbac_uid_t old_user, rsbac_uid_t * next_user_p)
+{
+	rsbac_uid_t *old_user_p;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	rsbac_um_set_t vset;
+#endif
+
+	if (old_user == RSBAC_NO_USER)
+		old_user_p = NULL;
+	else
+		old_user_p = &old_user;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	vset = RSBAC_UID_SET(old_user);
+	if (vset != RSBAC_UM_VIRTUAL_ALL)
+		return rsbac_ta_list_lol_get_next_desc_selector(ta_number,
+					    user_handle,
+					    old_user_p,
+					    next_user_p,
+					    vset_selector,
+					    &vset);
+	else
+#endif
+		return rsbac_ta_list_lol_get_next_desc(ta_number,
+					    user_handle,
+					    old_user_p,
+					    next_user_p);
+}
+
+int rsbac_um_get_user_list(rsbac_list_ta_number_t ta_number,
+			rsbac_um_set_t vset,
+			rsbac_uid_t ** list_pp)
+{
+	if(!list_pp)
+		return rsbac_ta_list_lol_count(ta_number, user_handle);
+	else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if (vset != RSBAC_UM_VIRTUAL_ALL)
+			return rsbac_ta_list_lol_get_all_desc_selector(
+					ta_number,
+					user_handle,
+					(void **) list_pp,
+					vset_selector,
+					&vset);
+		else
+#endif
+			return rsbac_ta_list_lol_get_all_desc(ta_number,
+					   user_handle,
+					   (void **) list_pp);
+	}
+}
+
+int rsbac_um_get_gm_list(rsbac_list_ta_number_t ta_number,
+			 rsbac_uid_t user, rsbac_gid_num_t ** list_pp)
+{
+	if (!list_pp)
+		return rsbac_ta_list_lol_subcount(ta_number,
+						  user_handle,
+						  &user);
+	else
+		return rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
+							     user_handle,
+							     &user,
+							     (void **) list_pp,
+							     NULL);
+}
+
+int rsbac_um_get_gm_user_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t group,
+  rsbac_uid_num_t ** list_pp)
+  {
+    int j;
+    long all_count = 0;
+    long copy_count = 0;
+    long tmp_count;
+    rsbac_uid_t * tmp_list_p;
+    rsbac_uid_num_t * collect_list_p;
+    rsbac_uid_num_t * p;
+    rsbac_um_set_t gid_set;
+    rsbac_gid_num_t gid_num;
+
+#ifdef CONFIG_RSBAC_UM_EXCL
+    if(!rsbac_um_no_excl && !rsbac_ta_list_exist(ta_number, group_handle, &group))
+      {
+        return -RSBAC_ENOTFOUND;
+      }
+#endif
+    all_count = rsbac_ta_list_lol_count(ta_number, user_handle);
+    if(!list_pp || (all_count <= 0))
+      return all_count;
+
+    /* provide some extra room in case new groups have been added during this function run */
+    all_count += EXTRA_ROOM;
+    collect_list_p = rsbac_kmalloc_unlocked(all_count * sizeof(rsbac_uid_num_t));
+    if(!collect_list_p)
+      return -RSBAC_ENOMEM;
+    p = collect_list_p;
+    tmp_count = rsbac_ta_list_lol_get_all_desc(ta_number, user_handle, (void *) &tmp_list_p);
+    if(tmp_count > 0)
+      {
+        gid_set = RSBAC_GID_SET(group);
+        gid_num = RSBAC_GID_NUM(group);
+        for(j=0; j<tmp_count; j++)
+          {
+            if(   (RSBAC_UID_SET(tmp_list_p[j]) == gid_set)
+               && rsbac_ta_list_lol_subexist(ta_number, user_handle, &tmp_list_p[j], &gid_num))
+              {
+                *p = RSBAC_UID_NUM(tmp_list_p[j]);
+                p++;
+                copy_count++;
+              }
+          }
+        rsbac_kfree(tmp_list_p);
+      }
+    if(!copy_count)
+      rsbac_kfree(collect_list_p);
+    else
+      *list_pp = collect_list_p;
+    return copy_count;
+  }
+
+int rsbac_um_get_group_list(rsbac_list_ta_number_t ta_number,
+			rsbac_um_set_t vset,
+			rsbac_gid_t ** list_pp)
+{
+	if(!list_pp)
+		return rsbac_ta_list_count(ta_number, group_handle);
+	else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if (vset != RSBAC_UM_VIRTUAL_ALL)
+			return rsbac_ta_list_get_all_desc_selector(
+					ta_number,
+					group_handle,
+					(void **) list_pp,
+					vset_selector,
+					&vset);
+		else
+#endif
+			return rsbac_ta_list_get_all_desc(ta_number,
+					   group_handle,
+					   (void **) list_pp);
+	}
+}
+
+int rsbac_um_check_pass(rsbac_uid_t uid, char *pass)
+{
+	int err;
+	struct rsbac_um_user_entry_t *entry_p;
+	__u32 salt;
+	u_long curdays;
+	char * pass_copy;
+
+	if (!pass)
+		return -RSBAC_EINVALIDPOINTER;
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err = rsbac_ta_list_lol_get_data_ttl(0, user_handle,
+					NULL, &uid, entry_p);
+	if (err)
+		goto out_free;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(uid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): checking password for user %u/%u\n",
+			current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): checking password for user %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(uid));
+	/* check whether account or password has expired */
+	curdays = RSBAC_CURRENT_TIME / 86400;
+	if ((curdays > entry_p->expire) && (entry_p->expire != -1)
+	    && (entry_p->expire != 0) && (entry_p->lastchange != 0)) {
+		err = -RSBAC_EEXPIRED;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if(RSBAC_UID_SET(uid))
+			rsbac_pr_debug(aef_um, "pid %u(%s): account for user %u/%u has expired\n",
+				current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+		else
+#endif
+			rsbac_pr_debug(aef_um, "pid %u(%s): account for user %u has expired\n",
+				current->pid, current->comm, RSBAC_UID_NUM(uid));
+		goto out_free;
+	}
+	if ((curdays >
+	     (entry_p->lastchange + entry_p->maxchange +
+	      entry_p->inactive))
+	    && (entry_p->maxchange != -1)
+	    && (entry_p->maxchange)
+	    && (entry_p->inactive != -1)
+	    && (entry_p->inactive)
+	    && (entry_p->lastchange)
+	    ) {
+		err = -RSBAC_EEXPIRED;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if(RSBAC_UID_SET(uid))
+			rsbac_pr_debug(aef_um, "pid %u(%s): password for user %u/%u has expired\n",
+			       current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+		else
+#endif
+			rsbac_pr_debug(aef_um, "pid %u(%s): password for user %u has expired\n",
+			       current->pid, current->comm, RSBAC_UID_NUM(uid));
+		goto out_free;
+	}
+
+/* rsbac_um_hash destroys old pass, so make a copy */
+	pass_copy = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+	if (!pass_copy) {
+		err = -RSBAC_ENOMEM;
+		goto out_free;
+	}
+	strncpy(pass_copy, pass, RSBAC_MAXNAMELEN);
+	pass_copy[RSBAC_MAXNAMELEN - 1] = 0;
+	salt = *((__u32 *) entry_p->pass);
+	if (   !salt
+	    || rsbac_um_hash(pass_copy, salt)
+	    || memcmp (pass_copy, entry_p->pass + sizeof(salt),
+			RSBAC_UM_PASS_LEN - sizeof(salt))) {
+#ifdef CONFIG_RSBAC_UM_ONETIME
+		rsbac_um_password_t * pw_array;
+		int count;
+
+		count = rsbac_list_lol_get_all_subdesc(onetime_handle,
+			&uid, (void **) &pw_array);
+		if (count > 0) {
+			u_int i;
+
+			rsbac_pr_debug(aef_um, "pid %u(%s): check %u one-time passwords for user %u/%u\n",
+			       current->pid, current->comm, count, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+			err = -EPERM;
+			for (i=0; i<count ;i++) {
+				salt = *((__u32 *) pw_array[i]);
+				strncpy(pass_copy, pass, RSBAC_MAXNAMELEN);
+				pass_copy[RSBAC_MAXNAMELEN - 1] = 0;
+				if (!salt || rsbac_um_hash(pass_copy, salt))
+					continue;
+				if (!memcmp
+				    (pass_copy, pw_array[i] + sizeof(salt),
+				     RSBAC_UM_PASS_LEN - sizeof(salt))) {
+					/* found pw: remove and success */
+					rsbac_pr_debug(aef_um, "pid %u(%s): one-time password %u for user %u/%u matched, removing\n",
+					       current->pid, current->comm, i, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+					rsbac_list_lol_subremove(onetime_handle,
+						&uid, pw_array[i]);
+					err = 0;
+					break;
+				}
+			}
+			rsbac_kfree(pw_array);
+		} else
+#endif
+		err = -EPERM;
+	} else
+		err = 0;
+
+	rsbac_kfree(pass_copy);
+out_free:
+	rsbac_kfree(entry_p);
+	if (err)
+		ssleep(1);
+	return err;
+}
+
+int rsbac_um_good_pass(rsbac_uid_t uid, char *pass)
+{
+#ifdef CONFIG_RSBAC_UM_NON_ALPHA
+	char *p;
+#endif
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+	int i;
+	long count;
+	char *hist_pass;
+	char *tmp;
+	__u8 *pwhistory_array;
+	__u32 salt;
+#endif
+
+	if (!pass)
+		return -RSBAC_EINVALIDPOINTER;
+	if (strlen(pass) < CONFIG_RSBAC_UM_MIN_PASS_LEN)
+		return -RSBAC_EWEAKPASSWORD;
+
+#ifdef CONFIG_RSBAC_UM_NON_ALPHA
+	p = pass;
+	while (*p && (((*p >= 'a')
+		       && (*p <= 'z')
+		      )
+		      || ((*p >= 'A')
+			  && (*p <= 'Z')
+		      )
+	       )
+	    )
+		p++;
+	if (!(*p))
+		return -RSBAC_EWEAKPASSWORD;
+#endif
+
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+	count = rsbac_ta_list_lol_get_all_subdata(0,
+					      user_pwhistory_handle,
+					      &uid,
+					      (void **) &pwhistory_array);
+	if (count > 0) {
+		tmp =
+		    rsbac_kmalloc_unlocked(rsbac_max
+				  (strlen(pass), RSBAC_UM_PASS_LEN));
+		hist_pass = pwhistory_array;
+
+		for (i = 0; i < count; i++) {
+			salt = *((__u32 *) hist_pass);
+			memcpy(tmp, pass,
+			       rsbac_max(strlen(pass), RSBAC_UM_PASS_LEN));
+			rsbac_um_hash(tmp, salt);
+
+			if (memcmp
+			    (tmp, hist_pass + sizeof(salt),
+			     RSBAC_UM_PASS_LEN - sizeof(salt)) == 0) {
+				rsbac_kfree(tmp);
+				rsbac_kfree(pwhistory_array);
+				return -RSBAC_EWEAKPASSWORD;
+			}
+			hist_pass += RSBAC_UM_PASS_LEN;
+		}
+		rsbac_kfree(tmp);
+		rsbac_kfree(pwhistory_array);
+	}
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_RSBAC_UM_ONETIME
+int rsbac_um_add_onetime(rsbac_uid_t uid, char *pass, rsbac_time_t ttl)
+{
+	int err;
+	__u32 salt;
+	char pass_entry[RSBAC_UM_PASS_LEN];
+
+	if (!pass)
+		return -RSBAC_EINVALIDPOINTER;
+
+	if (RSBAC_UID_SET(uid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): add one-time password for user %u/%u with ttl %lu\n",
+			current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid), ttl);
+	else
+		rsbac_pr_debug(aef_um, "pid %u(%s): add one-time password for user %u with ttl %lu\n",
+			current->pid, current->comm, RSBAC_UID_NUM(uid), ttl);
+	new_salt(&salt);
+	err = rsbac_um_hash(pass, salt);
+	if (err)
+		return err;
+	memcpy(pass_entry, &salt, sizeof(salt));
+	memcpy(pass_entry + sizeof(salt), pass,
+	       RSBAC_UM_PASS_LEN - sizeof(salt));
+
+	return rsbac_list_lol_subadd_ttl(onetime_handle, ttl, &uid, pass_entry, NULL);
+}
+
+int rsbac_um_remove_all_onetime(rsbac_uid_t uid)
+{
+	rsbac_pr_debug(aef_um, "pid %u(%s): remove all one-time passwords for user %u/%u\n",
+		current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+	return rsbac_list_lol_subremove_all(onetime_handle, &uid);
+}
+
+int rsbac_um_count_onetime(rsbac_uid_t uid)
+{
+	int err;
+
+	rsbac_pr_debug(aef_um, "pid %u(%s): counting one-time passwords for user %u/%u\n",
+		current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+	err = rsbac_list_lol_subcount(onetime_handle, &uid);
+	if (err == -RSBAC_ENOTFOUND)
+		err = 0;
+	return err;
+}
+#endif
+
+int rsbac_um_set_pass(rsbac_uid_t uid, char *pass)
+{
+	int err;
+	struct rsbac_um_user_entry_t *entry_p;
+	__u32 salt;
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err =
+	    rsbac_ta_list_lol_get_data_ttl(0, user_handle,
+					   NULL, &uid, entry_p);
+	if (err)
+		goto out_free;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(uid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): setting password for user %u/%u\n",
+			current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): setting password for user %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(uid));
+	if (pass) {
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+		__u32 max_index = 0;
+		__u8 max_history = CONFIG_RSBAC_UM_PWHISTORY_MAX;
+		long count;
+#endif
+		new_salt(&salt);
+		err = rsbac_um_hash(pass, salt);
+		if (err)
+			goto out_free;
+		memcpy(entry_p->pass, &salt, sizeof(salt));
+		memcpy(entry_p->pass + sizeof(salt), pass,
+		       RSBAC_UM_PASS_LEN - sizeof(salt));
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+		rsbac_list_lol_get_data(user_pwhistory_handle,
+					&uid,
+					&max_history);
+		if (max_history > 0) {
+			rsbac_ta_list_lol_get_max_subdesc(0,
+						user_pwhistory_handle,
+						&uid,
+						&max_index);
+			max_index++;
+
+			if (max_index != 0)
+				rsbac_list_lol_subadd(user_pwhistory_handle,
+						      &uid, &max_index,
+						      entry_p->pass);
+			else {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+				if(RSBAC_UID_SET(uid))
+					rsbac_printk(KERN_WARNING "rsbac_um_set_pass(): maximum password history index reached for user %u/%u, password will not be stored!\n",
+						RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+				else
+#endif
+					rsbac_printk(KERN_WARNING "rsbac_um_set_pass(): maximum password history index reached for user %u, password will not be stored!\n",
+						RSBAC_UID_NUM(uid));
+			}
+			count =
+			    rsbac_list_lol_subcount(user_pwhistory_handle,
+					    &uid);
+			if (count > max_history)
+				rsbac_ta_list_lol_subremove_count(0,
+								 user_pwhistory_handle,
+								 &uid,
+								 (count - max_history));
+		}
+#endif
+	} else
+		memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
+	entry_p->lastchange = RSBAC_CURRENT_TIME / 86400;
+	err = rsbac_ta_list_lol_add_ttl(0, user_handle,
+					0, &uid, entry_p);
+
+      out_free:
+	rsbac_kfree(entry_p);
+	return err;
+}
+
+int rsbac_um_set_group_pass(rsbac_gid_t gid, char *pass)
+{
+	int err;
+	struct rsbac_um_group_entry_t *entry_p;
+	__u32 salt;
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err = rsbac_ta_list_get_data_ttl(0, group_handle,
+					 NULL, &gid, entry_p);
+	if (err)
+		goto out_free;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_GID_SET(gid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): setting password for group %u/%u\n",
+			current->pid, current->comm, RSBAC_GID_SET(gid), RSBAC_GID_NUM(gid));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): setting password for group %u\n",
+			current->pid, current->comm, RSBAC_GID_NUM(gid));
+	if (pass) {
+		new_salt(&salt);
+		err = rsbac_um_hash(pass, salt);
+		if (err)
+			goto out_free;
+		memcpy(entry_p->pass, &salt, sizeof(salt));
+		memcpy(entry_p->pass + sizeof(salt), pass,
+		       RSBAC_UM_PASS_LEN - sizeof(salt));
+	} else
+		memset(entry_p->pass, 0, RSBAC_UM_PASS_LEN);
+	err =
+	    rsbac_ta_list_add_ttl(0, group_handle, 0,
+				  &gid, entry_p);
+
+      out_free:
+	rsbac_kfree(entry_p);
+	return err;
+}
+
+int rsbac_um_check_account(rsbac_uid_t uid)
+{
+	int err;
+	struct rsbac_um_user_entry_t *entry_p;
+	u_long curdays;
+
+	entry_p = rsbac_kmalloc_unlocked(sizeof(*entry_p));
+	if (!entry_p)
+		return -RSBAC_ENOMEM;
+	err =
+	    rsbac_ta_list_lol_get_data_ttl(0, user_handle,
+					   NULL, &uid, entry_p);
+	if (err)
+		goto out_free;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(uid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): checking account for user %u/%u\n",
+			current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): checking account for user %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(uid));
+	/* check whether account or password has expired */
+	curdays = RSBAC_CURRENT_TIME / 86400;
+	if (*((__u32 *) entry_p->pass)
+	    && !entry_p->lastchange) {
+		err = -RSBAC_EMUSTCHANGE;
+		rsbac_pr_debug(aef_um, "pid %u(%s): user %u must change password, "
+			       "lastchange = 0\n", current->pid, current->comm, uid);
+                               goto out_free;
+	}
+	if ((curdays > entry_p->expire)
+	    && (entry_p->expire != -1)
+	    && (entry_p->expire)
+	    ) {
+		err = -RSBAC_EEXPIRED;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if(RSBAC_UID_SET(uid))
+			rsbac_pr_debug(aef_um, "pid %u(%s): account for user %u/%u has expired\n",
+			       current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+		else
+#endif
+			rsbac_pr_debug(aef_um, "pid %u(%s): account for user %u has expired\n",
+			       current->pid, current->comm, RSBAC_UID_NUM(uid));
+		goto out_free;
+	}
+	if ((curdays >
+	     (entry_p->lastchange + entry_p->maxchange +
+	      entry_p->inactive))
+	    && (entry_p->maxchange != -1)
+	    && (entry_p->maxchange)
+	    && (entry_p->inactive != -1)
+	    && (entry_p->inactive)
+	    ) {
+		err = -RSBAC_EEXPIRED;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if(RSBAC_UID_SET(uid))
+			rsbac_pr_debug(aef_um, "pid %u(%s): password for user %u/%u has expired\n",
+			       current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+		else
+#endif
+			rsbac_pr_debug(aef_um, "pid %u(%s): password for user %u has expired\n",
+			       current->pid, current->comm, RSBAC_UID_NUM(uid));
+		goto out_free;
+	}
+	if (((entry_p->lastchange + entry_p->maxchange) < curdays)
+	    && entry_p->maxchange && (entry_p->maxchange != -1)
+	    ) {
+		err = -RSBAC_EMUSTCHANGE;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if(RSBAC_UID_SET(uid))
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u/%u must change password, "
+			       "lastchange too old\n",
+			       current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+		else
+#endif
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u must change password, "
+			       "lastchange too old\n",
+			       current->pid, current->comm, RSBAC_UID_NUM(uid));
+		goto out_free;
+	}
+	if ((curdays >
+	     (entry_p->lastchange + entry_p->maxchange -
+	      entry_p->warnchange))
+	    && (entry_p->maxchange != -1)
+	    && (entry_p->warnchange != -1)
+	    && entry_p->maxchange && entry_p->warnchange) {
+		err = (entry_p->lastchange + entry_p->maxchange) - curdays;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		if(RSBAC_UID_SET(uid))
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u/%u password will expire in %u days\n",
+			       current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid), err);
+		else
+#endif
+			rsbac_pr_debug(aef_um, "pid %u(%s): user %u password will expire in %u days\n",
+			       current->pid, current->comm, RSBAC_UID_NUM(uid), err);
+	} else
+		err = 0;
+
+      out_free:
+	rsbac_kfree(entry_p);
+	return err;
+}
+
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+int rsbac_um_get_max_history(rsbac_list_ta_number_t ta_number, rsbac_uid_t uid)
+{
+	int err;
+	__u8 max_history;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(uid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): getting max_history for user %u/%u\n",
+			current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): getting max_history for user %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(uid));
+	err = rsbac_ta_list_lol_get_data_ttl(ta_number, user_pwhistory_handle,
+					NULL,
+					&uid,
+					&max_history);
+	if (err)
+		return err;
+	else
+		return max_history;
+}
+
+int rsbac_um_set_max_history(rsbac_list_ta_number_t ta_number, rsbac_uid_t uid, __u8 max_history)
+{
+	int err;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	if(RSBAC_UID_SET(uid))
+		rsbac_pr_debug(aef_um, "pid %u(%s): setting max_history for user %u/%u to %u\n",
+			current->pid, current->comm, RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid), max_history);
+	else
+#endif
+		rsbac_pr_debug(aef_um, "pid %u(%s): setting max_history for user %u to %u\n",
+			current->pid, current->comm, RSBAC_UID_NUM(uid), max_history);
+	err = rsbac_ta_list_lol_add_ttl(ta_number, user_pwhistory_handle,
+					0,
+					&uid,
+					&max_history);
+	if (err)
+		return err;
+	if (max_history > 0) {
+		long count;
+
+		count = rsbac_ta_list_lol_subcount(ta_number,
+						user_pwhistory_handle,
+						&uid);
+		if (count > max_history)
+			rsbac_ta_list_lol_subremove_count(ta_number,
+							user_pwhistory_handle,
+							&uid,
+							(count - max_history));
+	} else {
+		rsbac_ta_list_lol_subremove_all(ta_number,
+						user_pwhistory_handle,
+						&uid);
+	}
+	return 0;
+}
+#endif
diff --git a/rsbac/help/Makefile b/rsbac/help/Makefile
new file mode 100644
index 0000000..265e6a9
--- /dev/null
+++ b/rsbac/help/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Rule Set Based Access Control helpers.
+#
+# Author and (c) 1999-2012 Amon Ott <ao@rsbac.org>
+obj-y := syscalls.o helpers.o getname.o debug.o rkmem.o net_getname.o
+#lsm.o
+
+obj-$(CONFIG_RSBAC_RC) += rc_getname.o
+obj-$(CONFIG_RSBAC_ACL) += acl_getname.o
+obj-$(CONFIG_RSBAC_PAX) += pax_getname.o
+obj-$(CONFIG_RSBAC_CAP_LOG_MISSING) += cap_getname.o
+obj-$(CONFIG_RSBAC_JAIL_LOG_MISSING) += jail_getname.o
+obj-$(CONFIG_RSBAC_NET_OBJ) += net_helpers.o
diff --git a/rsbac/help/acl_getname.c b/rsbac/help/acl_getname.c
new file mode 100644
index 0000000..e1d810e
--- /dev/null
+++ b/rsbac/help/acl_getname.c
@@ -0,0 +1,185 @@
+/************************************ */
+/* Rule Set Based Access Control      */
+/*                                    */
+/* Author and (c) 1999-2013: Amon Ott */
+/*                                    */
+/* Getname functions for ACL module   */
+/* Last modified: 27/Nov/2013         */
+/************************************ */
+
+#include <rsbac/types.h>
+#include <rsbac/getname.h>
+#include <rsbac/acl_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+static char  acl_subject_type_list[ACLS_NONE+1][6] = {
+                          "USER",
+                          "ROLE",
+                          "GROUP",
+                          "NONE" };
+
+static char  acl_group_syscall_list[ACLGS_none+1][18] = {
+                          "add_group",
+                          "change_group",
+                          "remove_group",
+                          "get_group_entry",
+                          "list_groups",
+                          "add_member",
+                          "remove_member",
+                          "get_user_groups",
+                          "get_group_members",
+                          "none" };
+
+static char  acl_scd_type_list[AST_none-32+1][20] = {
+                          "auth_administration",
+                          "udf_administration",
+                          "none" };
+
+static char  acl_special_right_list[ACLR_NONE-32+1][20] = {
+                          "FORWARD",
+                          "ACCESS_CONTROL",
+                          "SUPERVISOR",
+                          "NONE" };
+
+/*****************************************/
+
+char * get_acl_subject_type_name(char * name,
+                                 enum rsbac_acl_subject_type_t value)
+  {
+    if(!name)
+      return(NULL);
+    if(value > ACLS_NONE)
+      strcpy(name, "ERROR!");
+    else
+      strcpy(name, acl_subject_type_list[value]);
+    return(name);
+  };
+
+#ifndef __KERNEL__
+enum rsbac_acl_subject_type_t get_acl_subject_type_nr(const char * name)
+  {
+     enum  rsbac_acl_subject_type_t i;
+
+    if(!name)
+      return(ACLS_NONE);
+    for (i = 0; i < ACLS_NONE; i++)
+      {
+        if (!strcmp(name, acl_subject_type_list[i]))
+          {
+            return(i);
+          }
+      }
+    return(ACLS_NONE);
+  };
+#endif
+
+char * get_acl_group_syscall_name(char * name,
+                                  enum rsbac_acl_group_syscall_type_t value)
+  {
+    if(!name)
+      return(NULL);
+    if(value > ACLGS_none)
+      strcpy(name, "ERROR!");
+    else
+      strcpy(name, acl_group_syscall_list[value]);
+    return(name);
+  };
+
+#ifndef __KERNEL__
+enum rsbac_acl_group_syscall_type_t get_acl_group_syscall_nr(const char * name)
+  {
+    enum  rsbac_acl_group_syscall_type_t i;
+
+    if(!name)
+      return(ACLGS_none);
+    for (i = 0; i < ACLGS_none; i++)
+      {
+        if (!strcmp(name, acl_group_syscall_list[i]))
+          {
+            return(i);
+          }
+      }
+    return(ACLGS_none);
+  };
+#endif
+
+char * get_acl_scd_type_name(char * name,
+                            enum rsbac_acl_scd_type_t value)
+  {
+    if(!name)
+      return(NULL);
+    if(value < AST_min)
+      {
+        return(get_scd_type_name(name, value));
+      }
+    value -= AST_min;
+    if(value > AST_none)
+      {
+        strcpy(name, "ERROR!");
+        return(name);
+      }
+    strcpy(name, acl_scd_type_list[value]);
+    return(name);
+  };
+
+#ifndef __KERNEL__
+enum rsbac_acl_scd_type_t get_acl_scd_type_nr(const char * name)
+  {
+     enum  rsbac_acl_scd_type_t i;
+    
+    if(!name)
+      return(AST_none);
+    for (i = 0; i < AST_none-32; i++)
+      {
+        if (!strcmp(name, acl_scd_type_list[i]))
+          {
+            return(i+32);
+          }
+      }
+    return(get_scd_type_nr(name));
+  };
+#endif
+
+char * get_acl_special_right_name(char * name,
+                            enum rsbac_acl_special_rights_t value)
+  {
+    if(!name)
+      return(NULL);
+    if(value < RSBAC_ACL_SPECIAL_RIGHT_BASE)
+      {
+        return(get_request_name(name, value));
+      }
+    value -= RSBAC_ACL_SPECIAL_RIGHT_BASE;
+    if(value > ACLR_NONE)
+      {
+        strcpy(name, "ERROR!");
+        return(name);
+      }
+    strcpy(name, acl_special_right_list[value]);
+    return(name);
+  };
+
+#ifndef __KERNEL__
+enum rsbac_acl_special_rights_t get_acl_special_right_nr(const char * name)
+  {
+     enum  rsbac_acl_special_rights_t i;
+    
+    if(!name)
+      return(ACLR_NONE);
+    for (i = 0; i < (ACLR_NONE - RSBAC_ACL_SPECIAL_RIGHT_BASE); i++)
+      {
+        if (!strcmp(name, acl_special_right_list[i]))
+          {
+            return(i + RSBAC_ACL_SPECIAL_RIGHT_BASE);
+          }
+      }
+    return(get_request_nr(name));
+  };
+#endif
diff --git a/rsbac/help/cap_getname.c b/rsbac/help/cap_getname.c
new file mode 100644
index 0000000..336ad95
--- /dev/null
+++ b/rsbac/help/cap_getname.c
@@ -0,0 +1,450 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 1999-2014:        */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for CAP module */
+/* Last modified: 05/Feb/2014       */
+/********************************** */
+
+#include <rsbac/getname.h>
+#include <rsbac/cap_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#ifdef __KERNEL__
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/debug.h>
+#include <rsbac/aci.h>
+#include <rsbac/lists.h>
+#else
+#include <string.h>
+#endif
+
+/*****************************************/
+
+#ifdef CONFIG_RSBAC_CAP_LEARN_TA
+rsbac_list_ta_number_t cap_learn_ta = CONFIG_RSBAC_CAP_LEARN_TA;
+#else
+#define cap_learn_ta 0
+#endif
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_CAP_LOG_MISSING) || defined(CONFIG_RSBAC_CAP_LEARN)
+void rsbac_cap_log_missing_cap(int cap)
+  {
+    char * tmp;
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+#ifdef CONFIG_RSBAC_CAP_LEARN_TA
+    if (!rsbac_list_ta_exist(cap_learn_ta))
+	rsbac_list_ta_begin(CONFIG_RSBAC_LIST_TRANS_MAX_TTL,
+                &cap_learn_ta,
+		RSBAC_ALL_USERS,
+		RSBAC_CAP_LEARN_TA_NAME,
+		NULL);
+#endif
+    i_tid.process = task_pid(current);
+    if (rsbac_ta_get_attr(cap_learn_ta,
+                       SW_CAP,
+                       T_PROCESS,
+                       i_tid,
+                       A_max_caps_user,
+                       &i_attr_val1,
+                       FALSE))
+      {
+        rsbac_ds_get_error("rsbac_cap_log_missing_cap()", A_max_caps_user);
+      }
+    else
+      {
+        if(cap < 32)
+          {
+            if(!(i_attr_val1.max_caps_user.cap[0] & (1 << cap)))
+              {
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+                if (rsbac_cap_learn)
+                  {
+                    tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                    if(tmp)
+                      {
+                        get_cap_name(tmp, cap);
+                        rsbac_printk(KERN_INFO
+                             "capable(): pid %u(%s), uid %u: add missing user max_cap %s to transaction %u!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp,
+                             cap_learn_ta);
+                         rsbac_kfree(tmp);
+                      }
+                    i_attr_val1.max_caps_user.cap[0] |= (1 << cap);
+		    if (rsbac_ta_set_attr(cap_learn_ta,
+		                        SW_CAP,
+					T_PROCESS,
+					i_tid,
+					A_max_caps_user,
+					i_attr_val1))
+                      {
+			rsbac_pr_set_error (A_max_caps_user);
+                      }
+                    i_tid.user = __kuid_val(current_uid());
+                    if (rsbac_ta_get_attr(cap_learn_ta,
+                                       SW_CAP,
+                                       T_USER,
+                                       i_tid,
+                                       A_max_caps,
+                                       &i_attr_val1,
+                                       FALSE))
+                      {
+                        rsbac_pr_get_error(A_max_caps);
+                      }
+                    else
+                      {
+                        struct cred *override_cred;
+
+                        i_attr_val1.max_caps.cap[0] |= (1 << cap);
+ 		        if (rsbac_ta_set_attr(cap_learn_ta,
+ 		                        SW_CAP,
+					T_USER,
+					i_tid,
+					A_max_caps,
+					i_attr_val1))
+                          {
+			    rsbac_pr_set_error (A_max_caps);
+                          }
+                        /* set effective cap for process */
+			  override_cred = prepare_creds();
+			  if (override_cred)
+			    {
+			      override_cred->cap_effective.cap[0] |= (1 << cap);
+			      commit_creds(override_cred);
+                            }
+                      }
+                  }
+                else
+#endif
+                  if(rsbac_cap_log_missing)
+                    {
+                      tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                      if(tmp)
+                        {
+                          get_cap_name(tmp, cap);
+                          rsbac_printk(KERN_DEBUG
+                             "capable(): pid %u(%s), uid %u: missing user max_cap %s!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp);
+                          rsbac_kfree(tmp);
+                        }
+                    }
+              }
+          }
+        else
+          {
+            if(!(i_attr_val1.max_caps_user.cap[1] & (1 << (cap - 32))))
+              {
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+                if (rsbac_cap_learn)
+                  {
+                    tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                    if(tmp)
+                      {
+                        get_cap_name(tmp, cap);
+                        rsbac_printk(KERN_INFO
+                             "capable(): pid %u(%s), uid %u: add missing user max_cap %s to transaction %u!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp,
+                             cap_learn_ta);
+                         rsbac_kfree(tmp);
+                      }
+                    i_attr_val1.max_caps_user.cap[1] |= (1 << (cap - 32));
+		    if (rsbac_ta_set_attr(cap_learn_ta,
+		                        SW_CAP,
+					T_PROCESS,
+					i_tid,
+					A_max_caps_user,
+					i_attr_val1)) {
+			rsbac_ds_set_error ("rsbac_adf_set_attr_cap()",
+					 A_max_caps_user);
+                    }
+                    i_tid.user = __kuid_val(current_uid());
+                    if (rsbac_ta_get_attr(cap_learn_ta,
+                                       SW_CAP,
+                                       T_USER,
+                                       i_tid,
+                                       A_max_caps,
+                                       &i_attr_val1,
+                                       FALSE))
+                      {
+                        rsbac_pr_get_error(A_max_caps);
+                      }
+                    else
+                      {
+			struct cred *override_cred;
+
+                        i_attr_val1.max_caps.cap[1] |= (1 << (cap - 32));
+ 		        if (rsbac_ta_set_attr(cap_learn_ta,
+ 		                        SW_CAP,
+					T_USER,
+					i_tid,
+					A_max_caps,
+					i_attr_val1))
+                          {
+			    rsbac_pr_set_error (A_max_caps);
+                          }
+                        /* set effective cap for process */
+			  override_cred = prepare_creds();
+			  if (override_cred)
+			    {
+			      override_cred->cap_effective.cap[1] |= (1 << (cap - 32));
+			      commit_creds(override_cred);
+                            }
+                      }
+                  }
+                else
+#endif
+                  if(rsbac_cap_log_missing)
+                    {
+                      tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                      if(tmp)
+                        {
+                          get_cap_name(tmp, cap);
+                          rsbac_printk(KERN_DEBUG
+                             "capable(): pid %u(%s), uid %u: missing user max_cap %s!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp);
+                          rsbac_kfree(tmp);
+                        }
+                    }
+              }
+          }
+      }
+
+
+    if (rsbac_ta_get_attr(cap_learn_ta,
+                       SW_CAP,
+                       T_PROCESS,
+                       i_tid,
+                       A_max_caps_program,
+                       &i_attr_val1,
+                       FALSE))
+      {
+        rsbac_pr_get_error(A_max_caps_program);
+      }
+    else
+      {
+        if(cap < 32)
+          {
+            if(!(i_attr_val1.max_caps_program.cap[0] & (1 << cap)))
+              {
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+                if (rsbac_cap_learn)
+                  {
+                    i_attr_val1.max_caps_program.cap[0] |= (1 << cap);
+		    if (rsbac_ta_set_attr(cap_learn_ta,
+		                        SW_CAP,
+					T_PROCESS,
+					i_tid,
+					A_max_caps_program,
+					i_attr_val1)) {
+			rsbac_pr_set_error (A_max_caps_program);
+                    }
+                    if (rsbac_get_attr(SW_GEN,
+                                       T_PROCESS,
+                                       i_tid,
+                                       A_program_file,
+                                       &i_attr_val1,
+                                       FALSE))
+                      {
+                        rsbac_pr_get_error(A_program_file);
+                      }
+                    else
+                      {
+                        i_tid.file = i_attr_val1.program_file;
+                        tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                        if(tmp)
+                          {
+			    char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			    target_id_name = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+#else
+			    target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+#endif
+                            if(target_id_name)
+                              {
+                                get_cap_name(tmp, cap);
+                                rsbac_printk(KERN_INFO
+                                     "capable(): pid %u(%s), uid %u: add missing program max_cap %s to FILE %s to transaction %u!\n",
+                                     current->pid, current->comm,
+                                     __kuid_val(current_uid()),
+                                     tmp,
+                                     get_target_name(NULL, T_FILE, target_id_name, i_tid),
+                                     cap_learn_ta);
+                                rsbac_kfree(target_id_name);
+                              }
+                            rsbac_kfree(tmp);
+                          }
+                        if (rsbac_ta_get_attr(cap_learn_ta,
+                                           SW_CAP,
+                                           T_FILE,
+                                           i_tid,
+                                           A_max_caps,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_pr_get_error(A_max_caps);
+                          }
+                        else
+                          {
+			    struct cred *override_cred;
+
+                            i_attr_val1.max_caps.cap[0] |= (1 << cap);
+ 		            if (rsbac_ta_set_attr(cap_learn_ta,
+ 		                        SW_CAP,
+					T_FILE,
+					i_tid,
+					A_max_caps,
+					i_attr_val1))
+                              {
+			        rsbac_pr_set_error (A_max_caps);
+                              }
+                            /* set effective cap for process */
+			    override_cred = prepare_creds();
+			    if (override_cred)
+			      {
+			        override_cred->cap_effective.cap[0] |= (1 << cap);
+			        commit_creds(override_cred);
+                              }
+                          }
+                      }
+                  }
+                else
+#endif
+                  if(rsbac_cap_log_missing)
+                    {
+                      tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                      if(tmp)
+                        {
+                          get_cap_name(tmp, cap);
+                          rsbac_printk(KERN_DEBUG
+                             "capable(): pid %u(%s), uid %u: missing program max_cap %s!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp);
+                          rsbac_kfree(tmp);
+                        }
+                    }
+              }
+          }
+        else
+          {
+            if(!(i_attr_val1.max_caps_program.cap[1] & (1 << (cap - 32))))
+              {
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+                if (rsbac_cap_learn)
+                  {
+                    i_attr_val1.max_caps_program.cap[1] |= (1 << (cap - 32));
+		    if (rsbac_ta_set_attr(cap_learn_ta,
+		                        SW_CAP,
+					T_PROCESS,
+					i_tid,
+					A_max_caps_program,
+					i_attr_val1)) {
+			rsbac_pr_set_error (A_max_caps_program);
+                    }
+                    if (rsbac_get_attr(SW_GEN,
+                                       T_PROCESS,
+                                       i_tid,
+                                       A_program_file,
+                                       &i_attr_val1,
+                                       FALSE))
+                      {
+                        rsbac_pr_get_error(A_program_file);
+                      }
+                    else
+                      {
+                        i_tid.file = i_attr_val1.program_file;
+                        tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                        if(tmp)
+                          {
+			    char * target_id_name;
+
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			    target_id_name = rsbac_kmalloc_unlocked(CONFIG_RSBAC_MAX_PATH_LEN + RSBAC_MAXNAMELEN);
+#else
+			    target_id_name = rsbac_kmalloc_unlocked(2 * RSBAC_MAXNAMELEN);
+#endif
+                            if(target_id_name)
+                              {
+                                get_cap_name(tmp, cap);
+                                rsbac_printk(KERN_INFO
+                                     "capable(): pid %u(%s), uid %u: add missing program max_cap %s to FILE %s to transaction %u!\n",
+                                     current->pid, current->comm,
+                                     __kuid_val(current_uid()),
+                                     tmp,
+                                     get_target_name(NULL, T_FILE, target_id_name, i_tid),
+                                     cap_learn_ta);
+                                rsbac_kfree(target_id_name);
+                              }
+                            rsbac_kfree(tmp);
+                          }
+                        if (rsbac_ta_get_attr(cap_learn_ta,
+                                           SW_CAP,
+                                           T_FILE,
+                                           i_tid,
+                                           A_max_caps,
+                                           &i_attr_val1,
+                                           FALSE))
+                          {
+                            rsbac_pr_get_error(A_max_caps);
+                          }
+                        else
+                          {
+			    struct cred *override_cred;
+
+                            i_attr_val1.max_caps.cap[1] |= (1 << (cap - 32));
+ 		            if (rsbac_ta_set_attr(cap_learn_ta,
+ 		                        SW_CAP,
+					T_FILE,
+					i_tid,
+					A_max_caps,
+					i_attr_val1))
+                              {
+			        rsbac_pr_set_error (A_max_caps);
+                              }
+                        /* set effective cap for process */
+				override_cred = prepare_creds();
+				if (override_cred)
+				    {
+				      override_cred->cap_effective.cap[1] |= (1 << (cap - 32));
+				      commit_creds(override_cred);
+                                    }
+                          }
+                      }
+                  }
+                else
+#endif
+                  if(rsbac_cap_log_missing)
+                    {
+                      tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+                      if(tmp)
+                        {
+                          get_cap_name(tmp, cap);
+                          rsbac_printk(KERN_DEBUG
+                             "capable(): pid %u(%s), uid %u: missing program max_cap %s!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp);
+                          rsbac_kfree(tmp);
+                        }
+                    }
+              }
+          }
+      }
+  }
+#endif
+#endif
diff --git a/rsbac/help/debug.c b/rsbac/help/debug.c
new file mode 100644
index 0000000..a8c7bc3
--- /dev/null
+++ b/rsbac/help/debug.c
@@ -0,0 +1,4900 @@
+/******************************************* */
+/* Rule Set Based Access Control             */
+/*                                           */
+/* Author and (c) 1999-2016:                 */
+/*   Amon Ott <ao@rsbac.org>                 */
+/*                                           */
+/* Debug and logging functions for all parts */
+/*                                           */
+/* Last modified: 27/Mar/2016                */
+/******************************************* */
+ 
+#include <asm/uaccess.h>
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/aci_data_structures.h>
+#include <rsbac/debug.h>
+#include <rsbac/error.h>
+#include <rsbac/proc_fs.h>
+#include <rsbac/getname.h>
+#include <rsbac/net_getname.h>
+#include <rsbac/adf.h>
+#include <rsbac/rkmem.h>
+#if defined(CONFIG_RSBAC_DAZ)
+#include <rsbac/daz.h>
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+#include <rsbac/udf.h>
+#endif
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/net.h>
+#include <linux/in.h>
+#include <linux/moduleparam.h>
+#include <linux/syscalls.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/seq_file.h>
+
+extern u_int rsbac_list_rcu_rate;
+
+unsigned long int rsbac_flags;
+
+/* Boolean debug switch for NO_WRITE (global) */
+int  rsbac_debug_no_write = 0;
+
+static rsbac_boolean_t debug_initialized = FALSE;
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+rsbac_time_t rsbac_fd_cache_ttl = CONFIG_RSBAC_FD_CACHE_TTL;
+u_int rsbac_fd_cache_disable = 0;
+u_int rsbac_fd_cache_fuse = 0;
+u_int rsbac_fd_cache_ceph = 0;
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+rsbac_time_t rsbac_um_name_cache_ttl = CONFIG_RSBAC_UM_NAME_CACHE_TTL;
+u_int rsbac_um_name_cache_disable = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+rsbac_time_t rsbac_list_check_interval = CONFIG_RSBAC_LIST_CHECK_INTERVAL;
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+/* Boolean debug switch for data structures */
+int  rsbac_debug_ds = 0;
+
+/* Boolean debug switch for writing of data structures */
+int  rsbac_debug_write = 0;
+
+/* Boolean debug switch for AEF */
+EXPORT_SYMBOL(rsbac_debug_aef);
+int  rsbac_debug_aef = 0;
+
+/* Boolean debug switch for stack debugging */
+int  rsbac_debug_stack = 0;
+
+/* Boolean debug switch for generic lists */
+int  rsbac_debug_lists = 0;
+
+#ifdef CONFIG_RSBAC_NET
+int rsbac_debug_ds_net = 0;
+int rsbac_debug_adf_net = 0;
+int rsbac_debug_aef_net = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_MAC)
+/* Boolean debug switch for MAC data structures */
+int  rsbac_debug_ds_mac = 0;
+/* Boolean debug switch for MAC syscalls / AEF */
+int  rsbac_debug_aef_mac = 0;
+/* Boolean debug switch for MAC decisions / ADF */
+int  rsbac_debug_adf_mac = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+/* Boolean debug switch for DAZ decisions / ADF */
+int  rsbac_debug_adf_daz = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+/* Boolean debug switch for RC data structures */
+int  rsbac_debug_ds_rc = 0;
+/* Boolean debug switch for RC syscalls / AEF */
+int  rsbac_debug_aef_rc = 0;
+/* Boolean debug switch for RC decisions / ADF */
+int  rsbac_debug_adf_rc = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+/* Boolean debug switch for AUTH data structures */
+int  rsbac_debug_ds_auth = 0;
+/* Boolean debug switch for AUTH syscalls / AEF */
+int  rsbac_debug_aef_auth = 0;
+/* Boolean debug switch for AUTH decisions / ADF */
+int  rsbac_debug_adf_auth = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_REG)
+/* Boolean debug switch for REG */
+int  rsbac_debug_reg = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_ACL)
+/* Boolean debug switch for ACL data structures */
+int  rsbac_debug_ds_acl = 0;
+/* Boolean debug switch for ACL syscalls / AEF */
+int  rsbac_debug_aef_acl = 0;
+/* Boolean debug switch for ACL decisions / ADF */
+int  rsbac_debug_adf_acl = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+/* Boolean debug switch for JAIL syscalls / AEF */
+int  rsbac_debug_aef_jail = 0;
+/* Boolean debug switch for JAIL decisions / ADF */
+int  rsbac_debug_adf_jail = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+/* Boolean debug switch for PAX decisions / ADF */
+int  rsbac_debug_adf_pax = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+/* Boolean debug switch for UDF decisions / ADF */
+int  rsbac_debug_adf_udf = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_UM)
+/* Boolean debug switch for UM data structures */
+int  rsbac_debug_ds_um = 0;
+/* Boolean debug switch for UM syscalls / AEF */
+int  rsbac_debug_aef_um = 0;
+/* Boolean debug switch for UM decisions / ADF */
+int  rsbac_debug_adf_um = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+int  rsbac_debug_auto = 0;
+#endif
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+int rsbac_debug_fdcache = 0;
+#endif
+
+
+#endif /* DEBUG */
+
+#if defined(CONFIG_RSBAC_UM_EXCL)
+int  rsbac_um_no_excl = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+int  rsbac_rc_learn = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+/* Boolean switch for AUTH init: set may_setuid for /bin/login */
+int  rsbac_auth_enable_login = 0;
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+int  rsbac_auth_learn = 0;
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+int  rsbac_cap_learn = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_LEARN)
+int  rsbac_acl_learn_fd = 0;
+#endif
+
+/* Suppress default list creation for complete restore */
+int  rsbac_no_defaults = 0;
+
+static rsbac_list_handle_t log_levels_handle = NULL;
+
+#ifdef CONFIG_RSBAC_SOFTMODE
+/* Boolean switch for RSBAC soft mode */
+int  rsbac_softmode = 0;
+int  rsbac_softmode_prohibit = 0;
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+int  rsbac_ind_softmode[SW_NONE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#endif
+#endif
+
+int rsbac_list_recover = 0;
+int rsbac_list_noread = 0;
+/* If number of items per hashed list is bigger than this and flag
+   RSBAC_LIST_AUTO_HASH_RESIZE is set for the list, rehash */
+u_int rsbac_list_auto_rehash_trigger = CONFIG_RSBAC_LIST_AUTO_REHASH_TRIGGER;
+
+#ifdef CONFIG_RSBAC_FREEZE
+int rsbac_freeze = 0;
+#endif
+
+#if defined(CONFIG_RSBAC_CAP_PROC_HIDE)
+int rsbac_cap_process_hiding = 0;
+#endif
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+int rsbac_cap_log_missing = 0;
+#endif
+#ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+int rsbac_jail_log_missing = 0;
+#endif
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+/* Boolean switch for disabling Linux DAC */
+int  rsbac_dac_disable = 0;
+
+#if defined(CONFIG_RSBAC_REG)
+EXPORT_SYMBOL(rsbac_dac_is_disabled);
+#endif
+int rsbac_dac_is_disabled(void)
+  {
+    return rsbac_dac_disable;
+  }
+#endif
+
+static u_int log_seq = 0;
+
+/* Boolean switch for no syslog option*/
+#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+int  rsbac_nosyslog = 0;
+#endif
+
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+static u_int rsbac_syslog_rate = CONFIG_RSBAC_SYSLOG_RATE_DEF;
+static u_int syslog_count = 0;
+#endif
+
+/* Boolean switch for delayed init option*/
+#ifdef CONFIG_RSBAC_INIT_DELAY
+int  rsbac_no_delay_init = 0;
+kdev_t rsbac_delayed_root = RSBAC_MKDEV(0,0);
+#endif
+
+/* Array of Boolean debug switches for ADF */
+int  rsbac_debug_adf_default = 1;
+rsbac_log_entry_t  rsbac_log_levels[R_NONE+1];
+
+rsbac_boolean_t rsbac_debug_adf_dirty = FALSE;
+
+/* variables for rsbac_logging */
+#if defined(CONFIG_RSBAC_RMSG)
+#include <linux/poll.h>
+#include <linux/smp.h>
+DECLARE_WAIT_QUEUE_HEAD(rlog_wait);
+struct rsbac_log_list_head_t log_list_head = {NULL, NULL, 0, 0};
+static u_int rsbac_rmsg_maxentries = CONFIG_RSBAC_RMSG_MAXENTRIES;
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+struct rsbac_log_list_head_t remote_log_list_head = {NULL, NULL, 0, 0};
+static DECLARE_WAIT_QUEUE_HEAD(rsbaclogd_wait);
+static u_int rsbac_log_remote_maxentries = CONFIG_RSBAC_LOG_REMOTE_MAXENTRIES;
+#ifndef CONFIG_RSBAC_LOG_REMOTE_SYNC
+u_int rsbac_log_remote_interval = CONFIG_RSBAC_LOG_INTERVAL;
+#endif
+rsbac_pid_t rsbaclogd_pid = NULL;
+static __u16 rsbac_log_remote_port = 0;
+static __u32 rsbac_log_remote_addr = 0;
+static char rsbac_log_remote_addr_string[RSBAC_MAXNAMELEN] = CONFIG_RSBAC_LOG_REMOTE_ADDR;
+#endif
+
+#endif /* RMSG */
+
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+static struct timer_list rsbac_syslog_rate_timer;
+#endif
+
+void  rsbac_adf_log_switch(rsbac_adf_request_int_t request,
+                           enum rsbac_target_t target,
+                           rsbac_enum_t value)
+  {
+    if(   (request < R_NONE)
+       && (target <= T_NONE)
+       && (value <= LL_full)
+      )
+      {
+        rsbac_log_levels[request][target] = value;
+        if(log_levels_handle)
+          rsbac_list_add(log_levels_handle, &request, rsbac_log_levels[request]);
+      }
+  };
+
+int rsbac_get_adf_log(rsbac_adf_request_int_t request,
+                      enum rsbac_target_t target,
+                      u_int * value_p)
+  {
+    if(   (request < R_NONE)
+       && (target <= T_NONE)
+      )
+      {
+        *value_p = rsbac_log_levels[request][target];
+        return 0;
+      }
+    else
+      return -RSBAC_EINVALIDVALUE;
+  }
+
+static int R_INIT rsbac_flags_setup(char * line)
+{
+	rsbac_flags = simple_strtoul(line, NULL, 0);
+	rsbac_flags_set(rsbac_flags);
+	return 1;
+}
+__setup("rsbac_flags=", rsbac_flags_setup);
+
+//  module_param(rsbac_no_defaults, bool, S_IRUGO);
+  static int R_INIT no_defaults_setup(char *line)
+    {
+      rsbac_no_defaults = 1;
+      return 1;
+    }
+__setup("rsbac_no_defaults", no_defaults_setup);
+
+  #if defined(CONFIG_RSBAC_UM_EXCL)
+  static int R_INIT um_no_excl_setup(char *line)
+    {
+      rsbac_um_no_excl = 1;
+      return 1;
+    }
+  __setup("rsbac_um_no_excl", um_no_excl_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_DAZ_CACHE)
+  /* RSBAC: DAZ - set cache ttl */
+//    module_param(rsbac_daz_ttl,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT daz_ttl_setup(char *line)
+    {
+      rsbac_daz_set_ttl(simple_strtoul(line, NULL, 0));
+      return 1;
+    }
+  __setup("rsbac_daz_ttl=", daz_ttl_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_UDF_CACHE)
+  /* RSBAC: UDF - set cache ttl */
+//    module_param(rsbac_udf_ttl,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT udf_ttl_setup(char *line)
+    {
+      rsbac_udf_set_ttl(simple_strtoul(line, NULL, 0));
+      return 1;
+    }
+  __setup("rsbac_udf_ttl=", udf_ttl_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_RC_LEARN)
+  static int R_INIT rc_learn_setup(char *line)
+    {
+      rsbac_rc_learn = 1;
+      rsbac_debug_adf_rc = 1;
+      return 1;
+    }
+  __setup("rsbac_rc_learn", rc_learn_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_AUTH)
+  /* RSBAC: AUTH - set auth_may_setuid for /bin/login? */
+//    module_param(rsbac_auth_enable_login, int, S_IRUGO);
+  static int R_INIT auth_enable_login_setup(char *line)
+    {
+      rsbac_auth_enable_login = 1;
+      return 1;
+    }
+  __setup("rsbac_auth_enable_login", auth_enable_login_setup);
+    #if defined(CONFIG_RSBAC_AUTH_LEARN)
+  static int R_INIT auth_learn_setup(char *line)
+    {
+      rsbac_auth_learn = 1;
+      return 1;
+    }
+  __setup("rsbac_auth_learn", auth_learn_setup);
+    #endif
+  #endif
+  #if defined(CONFIG_RSBAC_CAP_LEARN)
+  static int R_INIT cap_learn_setup(char *line)
+    {
+      rsbac_cap_learn = 1;
+      return 1;
+    }
+  __setup("rsbac_cap_learn", cap_learn_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_ACL_LEARN)
+  /* learn all target types */
+  static int R_INIT acl_learn_setup(char *line)
+    {
+      rsbac_acl_learn_fd = 1;
+      return 1;
+    }
+  __setup("rsbac_acl_learn", acl_learn_setup);
+  static int R_INIT acl_learn_fd_setup(char *line)
+    {
+      rsbac_acl_learn_fd = 1;
+      return 1;
+    }
+  __setup("rsbac_acl_learn_fd", acl_learn_fd_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_RC_LEARN) || defined(CONFIG_RSBAC_AUTH_LEARN) || defined(CONFIG_RSBAC_ACL_LEARN) || defined(CONFIG_RSBAC_CAP_LEARN)
+  static int R_INIT learn_all_setup(char *line)
+    {
+  #if defined(CONFIG_RSBAC_RC_LEARN)
+      rsbac_rc_learn = 1;
+      rsbac_debug_adf_rc = 1;
+  #endif
+  #if defined(CONFIG_RSBAC_AUTH_LEARN)
+      rsbac_auth_learn = 1;
+  #endif
+  #if defined(CONFIG_RSBAC_ACL_LEARN)
+      rsbac_acl_learn_fd = 1;
+  #endif
+  #if defined(CONFIG_RSBAC_CAP_LEARN)
+      rsbac_cap_learn = 1;
+  #endif
+      return 1;
+    }
+  __setup("rsbac_learn_all", learn_all_setup);
+  #endif
+
+  #if defined(CONFIG_RSBAC_SOFTMODE)
+  /* RSBAC: softmode on? */
+//    module_param(rsbac_softmode_once, bool, S_IRUGO);
+//    module_param(rsbac_softmode, bool, S_IRUGO);
+  static int R_INIT softmode_setup(char *line)
+    {
+      rsbac_softmode = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode", softmode_setup);
+  static int R_INIT softmode_once_setup(char *line)
+    {
+      rsbac_softmode = 1;
+      rsbac_softmode_prohibit = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_once", softmode_once_setup);
+//    module_param(rsbac_softmode_never, bool, S_IRUGO);
+  static int R_INIT softmode_never_setup(char *line)
+    {
+      rsbac_softmode_prohibit = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_never", softmode_never_setup);
+
+    #if defined(CONFIG_RSBAC_SOFTMODE_IND)
+    /* RSBAC: softmode on for a module? */
+//    module_param_named(rsbac_softmode_mac, rsbac_ind_softmode[MAC], bool, S_IRUGO);
+  static int R_INIT softmode_mac_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_MAC] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_mac", softmode_mac_setup);
+//    module_param_named(rsbac_softmode_daz, rsbac_ind_softmode[SW_DAZ], bool, S_IRUGO);
+  static int R_INIT softmode_daz_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_DAZ] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_daz", softmode_daz_setup);
+//    module_param_named(rsbac_softmode_ff, rsbac_ind_softmode[SW_FF], bool, S_IRUGO);
+  static int R_INIT softmode_ff_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_FF] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_ff", softmode_ff_setup);
+//    module_param_named(rsbac_softmode_rc, rsbac_ind_softmode[SW_RC], bool, S_IRUGO);
+  static int R_INIT softmode_rc_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_RC] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_rc", softmode_rc_setup);
+//    module_param_named(rsbac_softmode_auth, rsbac_ind_softmode[SW_AUTH], bool, S_IRUGO);
+  static int R_INIT softmode_auth_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_AUTH] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_auth", softmode_auth_setup);
+//    module_param_named(rsbac_softmode_reg, rsbac_ind_softmode[SW_REG], bool, S_IRUGO);
+  static int R_INIT softmode_reg_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_REG] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_reg", softmode_reg_setup);
+//    module_param_named(rsbac_softmode_acl, rsbac_ind_softmode[SW_ACL], bool, S_IRUGO);
+  static int R_INIT softmode_acl_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_ACL] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_acl", softmode_acl_setup);
+//    module_param_named(rsbac_softmode_cap, rsbac_ind_softmode[SW_CAP], bool, S_IRUGO);
+  static int R_INIT softmode_cap_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_CAP] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_cap", softmode_cap_setup);
+//    module_param_named(rsbac_softmode_jail, rsbac_ind_softmode[SW_JAIL], bool, S_IRUGO);
+  static int R_INIT softmode_jail_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_JAIL] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_jail", softmode_jail_setup);
+//    module_param_named(rsbac_softmode_res, rsbac_ind_softmode[SW_RES], bool, S_IRUGO);
+  static int R_INIT softmode_res_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_RES] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_res", softmode_res_setup);
+//    module_param_named(rsbac_softmode_udf, rsbac_ind_softmode[SW_UDF], bool, S_IRUGO);
+  static int R_INIT softmode_udf_setup(char *line)
+    {
+      rsbac_ind_softmode[SW_UDF] = 1;
+      return 1;
+    }
+  __setup("rsbac_softmode_udf", softmode_udf_setup);
+    #endif
+    #endif
+
+    #if defined(CONFIG_RSBAC_CAP_PROC_HIDE)
+    /* RSBAC: hide processes? */
+//    module_param(rsbac_cap_process_hiding, bool, S_IRUGO);
+  static int R_INIT cap_process_hiding_setup(char *line)
+    {
+      rsbac_cap_process_hiding = 1;
+      return 1;
+    }
+  __setup("rsbac_cap_process_hiding", cap_process_hiding_setup);
+    #endif
+    #ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+    /* RSBAC: log missing caps? */
+//    module_param(rsbac_cap_log_missing, bool, S_IRUGO);
+  static int R_INIT cap_log_missing_setup(char *line)
+    {
+      rsbac_cap_log_missing = 1;
+      return 1;
+    }
+  __setup("rsbac_cap_log_missing", cap_log_missing_setup);
+    #endif
+    #ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+    /* RSBAC: log missing jail caps? */
+//    module_param(rsbac_jail_log_missing, bool, S_IRUGO);
+  static int R_INIT jail_log_missing_setup(char *line)
+    {
+      rsbac_jail_log_missing = 1;
+      return 1;
+    }
+  __setup("rsbac_jail_log_missing", jail_log_missing_setup);
+    #endif
+    #if defined(CONFIG_RSBAC_FREEZE)
+    /* RSBAC: freeze config? */
+//    module_param(rsbac_freeze, bool, S_IRUGO);
+  static int R_INIT freeze_setup(char *line)
+    {
+      rsbac_freeze = 1;
+      return 1;
+    }
+  __setup("rsbac_freeze", freeze_setup);
+    #endif
+    /* RSBAC: recover lists? */
+//    module_param(rsbac_list_recover, bool, S_IRUGO);
+  static int R_INIT list_recover_setup(char *line)
+    {
+      rsbac_list_recover = 1;
+      return 1;
+    }
+  __setup("rsbac_list_recover", list_recover_setup);
+    /* RSBAC: do not load lists? might be needed for correct recover? */
+//    module_param(rsbac_list_noread, bool, S_IRUGO);
+  static int R_INIT list_noread_setup(char *line)
+    {
+      rsbac_list_noread = 1;
+      return 1;
+    }
+  __setup("rsbac_list_noread", list_noread_setup);
+  static int R_INIT list_rcu_rate_setup(char *line)
+    {
+      rsbac_list_rcu_rate = simple_strtoul(line, NULL, 0);
+      if (rsbac_list_rcu_rate > 1000)
+        rsbac_list_rcu_rate = 1000;
+      return 1;
+    }
+  __setup("rsbac_list_rcu_rate=", list_rcu_rate_setup);
+  static int R_INIT list_auto_rehash_trigger_setup(char *line)
+    {
+      rsbac_list_auto_rehash_trigger = simple_strtoul(line, NULL, 0);
+      if (rsbac_list_auto_rehash_trigger < 4)
+        rsbac_list_auto_rehash_trigger = 4;
+      return 1;
+    }
+  __setup("rsbac_list_auto_rehash_trigger=", list_auto_rehash_trigger_setup);
+
+    #ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+    /* RSBAC: disable Linux DAC? */
+//    module_param(rsbac_dac_disable, bool, S_IRUGO);
+  static int R_INIT dac_disable_setup(char *line)
+    {
+      rsbac_dac_disable = 1;
+      return 1;
+    }
+  __setup("rsbac_dac_disable", dac_disable_setup);
+    #endif
+    #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+//    module_param(rsbac_nosyslog, bool, S_IRUGO);
+  static int R_INIT nosyslog_setup(char *line)
+    {
+      rsbac_nosyslog = 1;
+      return 1;
+    }
+  __setup("rsbac_nosyslog", nosyslog_setup);
+//    module_param_named(rsbac_no_syslog, rsbac_nosyslog, bool, S_IRUGO);
+  static int R_INIT no_syslog_setup(char *line)
+    {
+      rsbac_nosyslog = 1;
+      return 1;
+    }
+  __setup("rsbac_no_syslog", no_syslog_setup);
+    #endif
+    #if defined(CONFIG_RSBAC_RMSG)
+  static int R_INIT rmsg_maxentries_setup(char *line)
+    {
+      rsbac_rmsg_maxentries = simple_strtoul(line, NULL, 0);
+      return 1;
+    }
+  __setup("rsbac_rmsg_maxentries=", rmsg_maxentries_setup);
+    #endif
+    #if defined(CONFIG_RSBAC_LOG_REMOTE)
+//    module_param_string(rsbac_log_remote_addr,
+//                        rsbac_log_remote_addr_string,
+//                        sizeof(rsbac_log_remote_addr_string),
+//                        S_IRUGO);
+  static int R_INIT log_remote_addr_setup(char *line)
+    {
+      strncpy(rsbac_log_remote_addr_string, line, RSBAC_MAXNAMELEN - 1);
+      rsbac_log_remote_addr_string[RSBAC_MAXNAMELEN - 1]=0;
+      return 1;
+    }
+  __setup("rsbac_log_remote_addr=", log_remote_addr_setup);
+//    module_param(rsbac_log_remote_port,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT log_remote_port_setup(char *line)
+    {
+      __u16 tmp_port;
+
+      tmp_port = simple_strtoul(line, NULL, 0);
+      rsbac_log_remote_port = htons(tmp_port);
+      return 1;
+    }
+  __setup("rsbac_log_remote_port=", log_remote_port_setup);
+  static int R_INIT log_remote_maxentries_setup(char *line)
+    {
+      rsbac_log_remote_maxentries = simple_strtoul(line, NULL, 0);
+      return 1;
+    }
+  __setup("rsbac_log_remote_maxentries=", log_remote_maxentries_setup);
+    #endif
+    #ifdef CONFIG_RSBAC_INIT_DELAY
+//    module_param(rsbac_no_delay_init, bool, S_IRUGO);
+  static int R_INIT no_delay_init_setup(char *line)
+    {
+      rsbac_no_delay_init = 1;
+      return 1;
+    }
+  __setup("rsbac_no_delay_init", no_delay_init_setup);
+//    module_param_named(rsbac_no_init_delay, rsbac_no_delay_init, bool, S_IRUGO);
+  static int R_INIT no_init_delay_setup(char *line)
+    {
+      rsbac_no_delay_init = 1;
+      return 1;
+    }
+  __setup("rsbac_no_init_delay", no_init_delay_setup);
+    char rsbac_delayed_root_str[20] = "";
+//    module_param_string(rsbac_delayed_root,
+//                        rsbac_delayed_root_str,
+//                        sizeof(rsbac_delayed_root_str),
+//                        S_IRUGO);
+  static int R_INIT delayed_root_setup(char *line)
+    {
+      strncpy(rsbac_delayed_root_str, line, 19);
+      rsbac_delayed_root_str[19]=0;
+      return 1;
+    }
+  __setup("rsbac_delayed_root=", delayed_root_setup);
+    #endif
+    #ifdef CONFIG_RSBAC_SYSLOG_RATE
+//    module_param(rsbac_syslog_rate,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT syslog_rate_setup(char *line)
+    {
+      rsbac_syslog_rate = simple_strtoul(line, NULL, 0);
+      return 1;
+    }
+  __setup("rsbac_syslog_rate=", syslog_rate_setup);
+    #endif
+#ifdef CONFIG_RSBAC_FD_CACHE
+//    module_param(rsbac_fd_cache_ttl,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT fd_cache_ttl_setup(char *line)
+    {
+      rsbac_fd_cache_ttl = simple_strtoul(line, NULL, 0);
+      return 1;
+    }
+  __setup("rsbac_fd_cache_ttl=", fd_cache_ttl_setup);
+//    module_param(rsbac_fd_cache_disable, bool, S_IRUGO);
+  static int R_INIT fd_cache_disable_setup(char *line)
+    {
+      rsbac_fd_cache_disable = 1;
+      return 1;
+    }
+  __setup("rsbac_fd_cache_disable", fd_cache_disable_setup);
+//    module_param(rsbac_fd_cache_fuse, bool, S_IRUGO);
+  static int R_INIT fd_cache_fuse_setup(char *line)
+    {
+      rsbac_fd_cache_fuse = 1;
+      return 1;
+    }
+  __setup("rsbac_fd_cache_fuse", fd_cache_fuse_setup);
+//    module_param(rsbac_fd_cache_ceph, bool, S_IRUGO);
+  static int R_INIT fd_cache_ceph_setup(char *line)
+    {
+      rsbac_fd_cache_ceph = 1;
+      return 1;
+    }
+  __setup("rsbac_fd_cache_ceph", fd_cache_ceph_setup);
+#endif
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+//    module_param(rsbac_um_name_cache_ttl,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT um_name_cache_ttl_setup(char *line)
+    {
+      rsbac_um_name_cache_ttl = simple_strtoul(line, NULL, 0);
+      return 1;
+    }
+  __setup("rsbac_um_name_cache_ttl=", um_name_cache_ttl_setup);
+//    module_param(rsbac_um_name_cache_disable, bool, S_IRUGO);
+  static int R_INIT um_name_cache_disable_setup(char *line)
+    {
+      rsbac_um_name_cache_disable = 1;
+      return 1;
+    }
+  __setup("rsbac_um_name_cache_disable", um_name_cache_disable_setup);
+#endif
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+//    module_param(rsbac_list_check_interval,
+//                 int,
+//                 S_IRUGO);
+  static int R_INIT list_check_interval_setup(char *line)
+    {
+      rsbac_list_check_interval = simple_strtoul(line, NULL, 0);
+      return 1;
+    }
+  __setup("rsbac_list_check_interval=", list_check_interval_setup);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    #ifdef CONFIG_RSBAC_NET
+    /* RSBAC: debug for net data structures? */
+//    module_param(rsbac_debug_ds_net, bool, S_IRUGO);
+  static int R_INIT debug_ds_net_setup(char *line)
+    {
+      rsbac_debug_ds_net = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds_net", debug_ds_net_setup);
+    /* RSBAC: debug for net syscalls/AEF? */
+//    module_param(rsbac_debug_aef_net, bool, S_IRUGO);
+  static int R_INIT debug_aef_net_setup(char *line)
+    {
+      rsbac_debug_aef_net = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_net", debug_aef_net_setup);
+    /* RSBAC: debug for net decisions/ADF? */
+//    module_param(rsbac_debug_adf_net, bool, S_IRUGO);
+  static int R_INIT debug_adf_net_setup(char *line)
+    {
+      rsbac_debug_adf_net = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_net", debug_adf_net_setup);
+    #endif
+
+    #if defined(CONFIG_RSBAC_MAC)
+//    module_param(rsbac_debug_ds_mac, bool, S_IRUGO);
+  static int R_INIT debug_ds_mac_setup(char *line)
+    {
+      rsbac_debug_ds_mac = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds_mac", debug_ds_mac_setup);
+//    module_param(rsbac_debug_aef_mac, bool, S_IRUGO);
+  static int R_INIT debug_aef_mac_setup(char *line)
+    {
+      rsbac_debug_aef_mac = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_mac", debug_aef_mac_setup);
+//    module_param(rsbac_debug_adf_mac, bool, S_IRUGO);
+  static int R_INIT debug_adf_mac_setup(char *line)
+    {
+      rsbac_debug_adf_mac = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_mac", debug_adf_mac_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_MAC) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_mac, bool, S_IRUGO);
+  static int R_INIT switch_off_mac_setup(char *line)
+    {
+      rsbac_switch_mac = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_mac", switch_off_mac_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_DAZ)
+//    module_param(rsbac_debug_adf_daz, bool, S_IRUGO);
+  static int R_INIT debug_adf_daz_setup(char *line)
+    {
+      rsbac_debug_adf_daz = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_daz", debug_adf_daz_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_DAZ) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_mac, bool, S_IRUGO);
+  static int R_INIT switch_off_daz_setup(char *line)
+    {
+      rsbac_switch_daz = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_daz", switch_off_daz_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_RC)
+//    module_param(rsbac_debug_ds_rc, bool, S_IRUGO);
+  static int R_INIT debug_ds_rc_setup(char *line)
+    {
+      rsbac_debug_ds_rc = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds_rc", debug_ds_rc_setup);
+//    module_param(rsbac_debug_aef_rc, bool, S_IRUGO);
+  static int R_INIT debug_aef_rc_setup(char *line)
+    {
+      rsbac_debug_aef_rc = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_rc", debug_aef_rc_setup);
+//    module_param(rsbac_debug_adf_rc, bool, S_IRUGO);
+  static int R_INIT debug_adf_rc_setup(char *line)
+    {
+      rsbac_debug_adf_rc = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_rc", debug_adf_rc_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_RC) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_rc, bool, S_IRUGO);
+  static int R_INIT switch_off_rc_setup(char *line)
+    {
+      rsbac_switch_rc = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_rc", switch_off_rc_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_AUTH)
+//    module_param(rsbac_debug_ds_auth, bool, S_IRUGO);
+  static int R_INIT debug_ds_auth_setup(char *line)
+    {
+      rsbac_debug_ds_auth = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds_auth", debug_ds_auth_setup);
+//    module_param(rsbac_debug_aef_auth, bool, S_IRUGO);
+  static int R_INIT debug_aef_auth_setup(char *line)
+    {
+      rsbac_debug_aef_auth = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_auth", debug_aef_auth_setup);
+//    module_param(rsbac_debug_adf_auth, bool, S_IRUGO);
+  static int R_INIT debug_adf_auth_setup(char *line)
+    {
+      rsbac_debug_adf_auth = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_auth", debug_adf_auth_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_AUTH) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_auth, bool, S_IRUGO);
+  static int R_INIT switch_off_auth_setup(char *line)
+    {
+      rsbac_switch_auth = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_auth", switch_off_auth_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_REG)
+//    module_param(rsbac_debug_reg, bool, S_IRUGO);
+  static int R_INIT debug_reg_setup(char *line)
+    {
+      rsbac_debug_reg = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_reg", debug_reg_setup);
+    #endif
+    #if defined(CONFIG_RSBAC_ACL)
+//    module_param(rsbac_debug_ds_acl, bool, S_IRUGO);
+  static int R_INIT debug_ds_acl_setup(char *line)
+    {
+      rsbac_debug_ds_acl = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds_acl", debug_ds_acl_setup);
+//    module_param(rsbac_debug_aef_acl, bool, S_IRUGO);
+  static int R_INIT debug_aef_acl_setup(char *line)
+    {
+      rsbac_debug_aef_acl = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_acl", debug_aef_acl_setup);
+//    module_param(rsbac_debug_adf_acl, bool, S_IRUGO);
+  static int R_INIT debug_adf_acl_setup(char *line)
+    {
+      rsbac_debug_adf_acl = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_acl", debug_adf_acl_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_ACL) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_acl, bool, S_IRUGO);
+  static int R_INIT switch_off_acl_setup(char *line)
+    {
+      rsbac_switch_acl = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_acl", switch_off_acl_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_JAIL)
+//    module_param(rsbac_debug_aef_jail, bool, S_IRUGO);
+  static int R_INIT debug_aef_jail_setup(char *line)
+    {
+      rsbac_debug_aef_jail = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_jail", debug_aef_jail_setup);
+//    module_param(rsbac_debug_adf_jail, bool, S_IRUGO);
+  static int R_INIT debug_adf_jail_setup(char *line)
+    {
+      rsbac_debug_adf_jail = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_jail", debug_adf_jail_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_JAIL) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_jail, bool, S_IRUGO);
+  static int R_INIT switch_off_jail_setup(char *line)
+    {
+      rsbac_switch_jail = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_jail", switch_off_jail_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_PAX)
+//    module_param(rsbac_debug_adf_pax, bool, S_IRUGO);
+  static int R_INIT debug_adf_pax_setup(char *line)
+    {
+      rsbac_debug_adf_pax = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_pax", debug_adf_pax_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_PAX) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_pax, bool, S_IRUGO);
+  static int R_INIT switch_off_pax_setup(char *line)
+    {
+      rsbac_switch_pax = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_pax", switch_off_pax_setup);
+  #endif
+    #endif
+  #if defined(CONFIG_RSBAC_SWITCH_FF) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_ff, bool, S_IRUGO);
+  static int R_INIT switch_off_ff_setup(char *line)
+    {
+      rsbac_switch_ff = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_ff", switch_off_ff_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_SWITCH_RES) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_res, bool, S_IRUGO);
+  static int R_INIT switch_off_res_setup(char *line)
+    {
+      rsbac_switch_res = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_res", switch_off_res_setup);
+  #endif
+  #if defined(CONFIG_RSBAC_SWITCH_CAP) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_cap, bool, S_IRUGO);
+  static int R_INIT switch_off_cap_setup(char *line)
+    {
+      rsbac_switch_cap = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_cap", switch_off_cap_setup);
+  #endif
+    #if defined(CONFIG_RSBAC_UDF)
+//    module_param(rsbac_debug_adf_udf, bool, S_IRUGO);
+  static int R_INIT debug_adf_udf_setup(char *line)
+    {
+      rsbac_debug_adf_udf = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_udf", debug_adf_udf_setup);
+  #if defined(CONFIG_RSBAC_SWITCH_UDF) && defined(RSBAC_SWITCH_BOOT_OFF)
+//    module_param(rsbac_switch_off_udf, bool, S_IRUGO);
+  static int R_INIT switch_off_udf_setup(char *line)
+    {
+      rsbac_switch_udf = 0;
+      return 1;
+    }
+  __setup("rsbac_switch_off_udf", switch_off_udf_setup);
+  #endif
+    #endif
+    #if defined(CONFIG_RSBAC_UM)
+//    module_param(rsbac_debug_ds_um, bool, S_IRUGO);
+  static int R_INIT debug_ds_um_setup(char *line)
+    {
+      rsbac_debug_ds_um = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds_um", debug_ds_um_setup);
+//    module_param(rsbac_debug_aef_um, bool, S_IRUGO);
+  static int R_INIT debug_aef_um_setup(char *line)
+    {
+      rsbac_debug_aef_um = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef_um", debug_aef_um_setup);
+//    module_param(rsbac_debug_adf_um, bool, S_IRUGO);
+  static int R_INIT debug_adf_um_setup(char *line)
+    {
+      rsbac_debug_adf_um = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_um", debug_adf_um_setup);
+    #endif
+    #if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+//    module_param(rsbac_debug_auto, bool, S_IRUGO);
+  static int R_INIT debug_auto_setup(char *line)
+    {
+      rsbac_debug_auto = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_auto", debug_auto_setup);
+    #endif
+#ifdef CONFIG_RSBAC_FD_CACHE
+//    module_param(rsbac_debug_fdcache, bool, S_IRUGO);
+  static int R_INIT debug_fdcache_setup(char *line)
+    {
+      rsbac_debug_fdcache++;
+      return 1;
+    }
+  __setup("rsbac_debug_fdcache", debug_fdcache_setup);
+    #endif
+    /* RSBAC: debug_lists */
+//    module_param(rsbac_debug_lists, bool, S_IRUGO);
+  static int R_INIT debug_lists_setup(char *line)
+    {
+      rsbac_debug_lists = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_lists", debug_lists_setup);
+    /* RSBAC: debug_stack */
+//    module_param(rsbac_debug_stack, bool, S_IRUGO);
+  static int R_INIT debug_stack_setup(char *line)
+    {
+      rsbac_debug_stack = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_stack", debug_stack_setup);
+    /* RSBAC: debug for data structures? */
+//    module_param(rsbac_debug_ds, bool, S_IRUGO);
+  static int R_INIT debug_ds_setup(char *line)
+    {
+      rsbac_debug_ds = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_ds", debug_ds_setup);
+    /* RSBAC: debug for writing of data structures? */
+//    module_param(rsbac_debug_write, bool, S_IRUGO);
+  static int R_INIT debug_write_setup(char *line)
+    {
+      rsbac_debug_write = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_write", debug_write_setup);
+    /* RSBAC: debug for AEF? */
+//    module_param(rsbac_debug_aef, bool, S_IRUGO);
+  static int R_INIT debug_aef_setup(char *line)
+    {
+      rsbac_debug_aef = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_aef", debug_aef_setup);
+    /* RSBAC: debug_no_write for ds */
+//    module_param(rsbac_debug_no_write, bool, S_IRUGO);
+  static int R_INIT debug_no_write_setup(char *line)
+    {
+      rsbac_debug_no_write = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_no_write", debug_no_write_setup);
+    /* RSBAC: debug default for ADF */
+//    module_param(rsbac_debug_adf_default, int, S_IRUGO);
+  static int R_INIT debug_adf_default_setup(char *line)
+    {
+      rsbac_debug_adf_default = 1;
+      return 1;
+    }
+  __setup("rsbac_debug_adf_default", debug_adf_default_setup);
+#endif /* DEBUG */
+
+#if defined(CONFIG_RSBAC_RMSG)
+static DEFINE_SPINLOCK(rsbac_log_lock);
+
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+static DEFINE_SPINLOCK(rsbac_log_remote_lock);
+#endif
+
+/*
+ * Commands to do_syslog:
+ *
+ * 	0 -- Close the log.  Currently a NOP.
+ * 	1 -- Open the log. Currently a NOP.
+ * 	2 -- Read from the log.
+ * 	3 -- Read all messages remaining in the ring buffer.
+ * 	4 -- Read and clear all messages remaining in the ring buffer
+ * 	5 -- Clear ring buffer.
+ *	9 -- Return number of unread characters in the log buffer
+ */
+int rsbac_log(int type, char * buf, int len)
+{
+	unsigned long count;
+	int do_clear = 0;
+	int error = 0;
+	char * k_buf;
+
+        union rsbac_target_id_t       rsbac_target_id;
+        union rsbac_attribute_value_t rsbac_attribute_value;
+	struct rsbac_log_list_item_t * log_item;
+
+        /* RSBAC */
+        rsbac_target_id.scd = ST_rsbac_log;
+        rsbac_attribute_value.dummy = 0;
+        if ((type == 4) || (type == 5))
+          {
+#ifdef CONFIG_RSBAC_DEBUG
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "rsbac_log(): function %u, calling ADF for MODIFY_SYSTEM_DATA\n", type);
+              }
+#endif
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                error = -EPERM;
+                goto out;
+              }
+          }
+        else
+        if(type >= 1)
+          {
+#ifdef CONFIG_RSBAC_DEBUG
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "rsbac_log(): function %u, calling ADF for GET_STATUS_DATA\n", type);
+              }
+#endif
+            if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                error = -EPERM;
+                goto out;
+              }
+          }
+
+	switch (type) {
+	case 0:		/* Close log */
+		break;
+	case 1:		/* Open log */
+		break;
+	case 2:		/* Read from log */
+		if (!buf || len < 0) {
+			error = -EINVAL;
+			goto out;
+		}
+		if (!len) {
+			error = 0;
+			goto out;
+                }
+		error = access_ok(VERIFY_WRITE,buf,len);
+		if (!error)
+			goto out;
+		error = wait_event_interruptible(rlog_wait, log_list_head.count);
+		if (error)
+			goto out;
+		if (len > RSBAC_LOG_MAXREADBUF)
+			len = RSBAC_LOG_MAXREADBUF;
+		k_buf = rsbac_kmalloc(len);
+		count = 0;
+		spin_lock(&rsbac_log_lock);
+		log_item = log_list_head.head;
+		while (log_item && (count + log_item->size < len)) {
+			memcpy(k_buf + count, log_item->buffer, log_item->size);
+			count += log_item->size;
+			log_item = log_item->next;
+			kfree(log_list_head.head);
+			log_list_head.head = log_item;
+			if(!log_item)
+				log_list_head.tail = NULL;
+			log_list_head.count--;
+		}
+		spin_unlock(&rsbac_log_lock);
+		error = copy_to_user(buf, k_buf, count);
+		if (!error)
+			error = count;
+		rsbac_kfree(k_buf);
+		break;
+	case 4:		/* Read/clear last kernel messages */
+		do_clear = 1; 
+		/* FALL THRU */
+	case 3:		/* Read last kernel messages */
+		error = -EINVAL;
+		if (!buf || len < 0)
+			goto out;
+		error = 0;
+		if (!len)
+			goto out;
+		error = access_ok(VERIFY_WRITE,buf,len);
+		if (!error)
+			goto out;
+		if (len > RSBAC_LOG_MAXREADBUF)
+			len = RSBAC_LOG_MAXREADBUF;
+		k_buf = rsbac_kmalloc(len);
+		count = 0;
+		spin_lock(&rsbac_log_lock);
+		log_item = log_list_head.head;
+		while (log_item && (count + log_item->size < len)) {
+			memcpy(k_buf + count, log_item->buffer, log_item->size);
+			count += log_item->size;
+			log_item = log_item->next;
+			if(do_clear) {
+				kfree(log_list_head.head);
+				log_list_head.head = log_item;
+				if(!log_item)
+					log_list_head.tail = NULL;
+				log_list_head.count--;
+			}
+		}
+		spin_unlock(&rsbac_log_lock);
+		error = copy_to_user(buf, k_buf, count);
+		if (!error)
+			error = count;
+		rsbac_kfree(k_buf);
+		break;
+	case 5:		/* Clear ring buffer */
+		spin_lock(&rsbac_log_lock);
+		log_item = log_list_head.head;
+		while (log_item) {
+			log_item = log_item->next;
+			kfree(log_list_head.head);
+			log_list_head.head = log_item;
+		}
+		log_list_head.tail = NULL;
+		log_list_head.count = 0;
+		spin_unlock(&rsbac_log_lock);
+		error = 0;
+		break;
+	case 9:		/* Number of chars in the log buffer */
+		error = 0;
+		spin_lock(&rsbac_log_lock);
+		log_item = log_list_head.head;
+		while (log_item) {
+			error += log_item->size;
+			log_item = log_item->next;
+		}
+		spin_unlock(&rsbac_log_lock);
+		break;
+	default:
+		error = -EINVAL;
+		break;
+	}
+out:
+	return error;
+}
+#endif /* RMSG */
+
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+static void syslog_rate_reset(u_long dummy)
+  {
+    if(syslog_count > rsbac_syslog_rate)
+      printk(KERN_INFO "syslog_rate_reset: resetting syslog_count at %u, next message is %u\n",
+             syslog_count, log_seq);
+    syslog_count = 0;
+    mod_timer(&rsbac_syslog_rate_timer, jiffies + HZ);
+  }
+#endif
+
+EXPORT_SYMBOL(rsbac_printk);
+int rsbac_printk(const char *fmt, ...)
+{
+	va_list args;
+	int printed_len;
+        char * buf;
+#if defined(CONFIG_RSBAC_RMSG)
+	struct rsbac_log_list_item_t * log_item;
+#endif
+
+	if (rsbac_is_initialized())
+		buf = rsbac_kmalloc(RSBAC_LOG_MAXLINE);
+	else
+		buf = kmalloc(RSBAC_LOG_MAXLINE, GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+	/* Emit the output into the buffer */
+	va_start(args, fmt);
+	printed_len = vsnprintf(buf + 11, RSBAC_LOG_MAXLINE - 13, fmt, args);
+	va_end(args);
+	if(printed_len < 4) {
+		kfree(buf);
+		return printed_len;
+	}
+	buf[0] = buf[11];
+	buf[1] = buf[12];
+	sprintf(buf + 2, "%010u", log_seq++);
+	buf[12] = '|';
+	/* Terminate string */
+	buf[printed_len + 11] = 0;
+
+	/* copy to printk */
+#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+	if (!rsbac_nosyslog)
+#endif
+	{
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+		syslog_count++;
+		if(syslog_count < rsbac_syslog_rate)
+#endif
+			printk("%s", buf);
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+		else
+			if(syslog_count == rsbac_syslog_rate)
+				printk(KERN_INFO "rsbac_printk: Applying syslog rate limit at count %u, message %u!\n",
+					syslog_count, log_seq - 1);
+#endif
+	}
+	/* Buffer is ready, now copy into log list */
+#if defined(CONFIG_RSBAC_RMSG)
+	if (rsbac_is_initialized())
+		log_item = rsbac_kmalloc(sizeof(*log_item) + printed_len + 12);
+	else
+		log_item = kmalloc(sizeof(*log_item) + printed_len + 12, GFP_ATOMIC);
+	if(log_item) {
+		memcpy(log_item->buffer, buf, printed_len + 11);
+		log_item->buffer[printed_len + 11] = 0;
+		log_item->size = printed_len + 11;
+		log_item->next = NULL;
+		spin_lock(&rsbac_log_lock);
+		if (log_list_head.tail) {
+			log_list_head.tail->next = log_item;
+		} else {
+			log_list_head.head = log_item;
+		}
+		log_list_head.tail = log_item;
+		log_list_head.count++;
+		while(log_list_head.count > rsbac_rmsg_maxentries) {
+			log_item = log_list_head.head;
+			log_list_head.head = log_item->next;
+			log_list_head.count--;
+			log_list_head.lost++;
+			kfree(log_item);
+		}
+		spin_unlock(&rsbac_log_lock);
+		wake_up_interruptible(&rlog_wait);
+	}
+#endif
+
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+	/* Copy into remote log list */
+	if (rsbac_is_initialized())
+		log_item = rsbac_kmalloc(sizeof(*log_item) + printed_len + 12);
+	else
+		log_item = kmalloc(sizeof(*log_item) + printed_len + 12, GFP_ATOMIC);
+	if(log_item) {
+		memcpy(log_item->buffer, buf, printed_len + 11);
+		log_item->buffer[printed_len + 11] = 0;
+		log_item->size = printed_len + 11;
+		log_item->next = NULL;
+		spin_lock(&rsbac_log_remote_lock);
+		if (remote_log_list_head.tail) {
+			remote_log_list_head.tail->next = log_item;
+		} else {
+			remote_log_list_head.head = log_item;
+		}
+		remote_log_list_head.tail = log_item;
+		remote_log_list_head.count++;
+		while(remote_log_list_head.count > rsbac_log_remote_maxentries) {
+			log_item = remote_log_list_head.head;
+			remote_log_list_head.head = log_item->next;
+			remote_log_list_head.count--;
+			remote_log_list_head.lost++;
+			kfree(log_item);
+		}
+		spin_unlock(&rsbac_log_remote_lock);
+#ifdef CONFIG_RSBAC_LOG_REMOTE_SYNC
+		wake_up_interruptible(&rsbaclogd_wait);
+#endif
+	}
+#endif
+
+	kfree(buf);
+	return printed_len;
+}
+
+#if defined(CONFIG_RSBAC_RMSG)
+#if defined(CONFIG_RSBAC_PROC)
+static int rmsg_open(struct inode * inode, struct file * file)
+{
+	return rsbac_log(1,NULL,0);
+}
+
+static int rmsg_release(struct inode * inode, struct file * file)
+{
+	(void) rsbac_log(0,NULL,0);
+	return 0;
+}
+
+static ssize_t rmsg_read(struct file * file, char * buf,
+			 size_t count, loff_t *ppos)
+{
+	return rsbac_log(2,buf,count);
+}
+
+static unsigned int rmsg_poll(struct file *file, poll_table * wait)
+{
+	poll_wait(file, &rlog_wait, wait);
+	if (rsbac_log(9, 0, 0))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static struct file_operations rmsg_proc_fops = {
+	.read = rmsg_read,
+	.poll = rmsg_poll,	/* rmsg_poll */
+	.open = rmsg_open,
+	.release = rmsg_release
+};
+
+static struct proc_dir_entry *rmsg;
+
+#endif /* PROC */
+#endif /* RMSG */
+
+#if defined(CONFIG_RSBAC_PROC)
+#ifndef PROC_BLOCK_SIZE
+#define PROC_BLOCK_SIZE	(3*1024)  /* 4K page size but our output routines use some slack for overruns */
+#endif
+
+static int
+log_levels_proc_show(struct seq_file *m, void *v)
+{
+  int i,j;
+  char * name;
+  char * name2;
+
+  union rsbac_target_id_t       rsbac_target_id;
+  union rsbac_attribute_value_t rsbac_attribute_value;
+
+  if (!rsbac_is_initialized())
+    return (-ENOSYS);
+
+#ifdef CONFIG_RSBAC_DEBUG
+  if (rsbac_debug_aef)
+    {
+      rsbac_printk(KERN_DEBUG "log_levels_proc_info(): calling ADF\n");
+    }
+#endif
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                         task_pid(current),
+                         T_SCD,
+                         rsbac_target_id,
+                         A_none,
+                         rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+
+  name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+  if(!name)
+    return -ENOMEM;
+  name2 = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+  if(!name2)
+    {
+      rsbac_kfree(name);
+      return -ENOMEM;
+    }
+    
+  seq_printf(m, "RSBAC Log Levels\n----------------\n");
+  seq_printf(m, "Name\t\t\tFILE\tDIR\tFIFO\tSYMLINK\tDEV\tIPC\tSCD\tUSER\tPROCESS\tNETDEV\tNETTEMP\tNETOBJ\tNETT_NT\tNONE\n");
+
+  for (i = 0; i<R_NONE; i++)
+    {
+      seq_printf(m, "%-23s",
+                     get_request_name(name, i));
+      for(j = 0; j<=T_NONE; j++)
+        {
+          if(j != T_FD)
+            seq_printf(m, "\t%u",
+                           rsbac_log_levels[i][j]);
+        }
+      seq_printf(m, "\n");
+    }
+
+  rsbac_kfree(name);
+  rsbac_kfree(name2);
+
+  return 0;
+}
+
+static ssize_t log_levels_proc_write(struct file * file, const char __user * buf,
+                                     size_t count, loff_t *ppos)
+{
+    ssize_t err;
+    char * k_buf;
+    char * p;
+    unsigned int log_level;
+    char rname[RSBAC_MAXNAMELEN];
+    int i,j;
+
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(count > PROC_BLOCK_SIZE) {
+	return(-EOVERFLOW);
+    }
+
+    if (!(k_buf = (char *) __get_free_page(GFP_KERNEL)))
+      return(-ENOMEM);
+    err = copy_from_user(k_buf, buf, count);
+    if(err < 0)
+      return err;
+
+  err = count;
+  if(count < 15 || strncmp("log_levels", k_buf, 10))
+    {
+      goto out;
+    }
+  if (!rsbac_is_initialized())
+    {
+      err = -ENOSYS;
+      goto out;
+    }
+
+    /*
+     * Usage: echo "log_levels request #N" > /proc/rsbac_info/log_levels
+     *   to set log level for request to given value
+     */
+    for(i=0; i<R_NONE; i++)
+      {
+        get_request_name(rname,i);
+        if(!strncmp(rname, k_buf + 11, strlen(rname))) 
+          {
+#ifdef CONFIG_RSBAC_DEBUG
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "log_levels_proc_write(): calling ADF\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.request = i;
+            if (!rsbac_adf_request(R_SWITCH_LOG,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_request,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+	    p = k_buf + 11 + strlen(rname)+1;
+
+            if( *p == '\0' )
+              goto out;
+
+            log_level = simple_strtoul(p, NULL, 0);
+            /* only accept 0 or 1 */
+            if(   (log_level == LL_none)
+               || (log_level == LL_denied)
+               || (log_level == LL_full)
+              )
+              {
+                rsbac_printk(KERN_INFO
+                       "log_levels_proc_write(): setting %s log level for all target types to %u\n",
+                       rname, log_level);
+                for(j = 0; j<=T_NONE; j++)
+                  {
+                    rsbac_log_levels[i][j] = log_level;
+                  }
+                err = count;
+                goto out;
+              }
+            else
+              {
+                rsbac_printk(KERN_INFO
+                       "log_levels_proc_write(): rejecting invalid log level (should be %u, %u or %u)\n",
+                       LL_none, LL_denied, LL_full);
+                goto out;
+              }
+          }
+      }
+
+out:
+  free_page((ulong) k_buf);
+  return(err);
+  }
+
+static int log_levels_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, log_levels_proc_show, NULL);
+}
+
+static const struct file_operations log_levels_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = log_levels_proc_open,
+       .read           = seq_read,
+       .write          = log_levels_proc_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *log_levels;
+
+static int
+debug_proc_show(struct seq_file *m, void *v)
+{
+  union rsbac_target_id_t       rsbac_target_id;
+  union rsbac_attribute_value_t rsbac_attribute_value;
+
+  if (!rsbac_is_initialized())
+    return (-ENOSYS);
+
+#ifdef CONFIG_RSBAC_DEBUG
+  if (rsbac_debug_aef)
+      rsbac_printk(KERN_DEBUG "debug_proc_info(): calling ADF\n");
+#endif
+  rsbac_target_id.scd = ST_rsbac;
+  rsbac_attribute_value.dummy = 0;
+  if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                         task_pid(current),
+                         T_SCD,
+                         rsbac_target_id,
+                         A_none,
+                         rsbac_attribute_value))
+    {
+      return -EPERM;
+    }
+  seq_printf(m, "RSBAC Debug Settings\n--------------------\n");
+
+#ifdef CONFIG_RSBAC_SOFTMODE
+  seq_printf(m, "rsbac_softmode is %i\n",
+                 rsbac_softmode);
+  seq_printf(m, "rsbac_softmode_prohibit is %i\n",
+                 rsbac_softmode_prohibit);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+#ifdef CONFIG_RSBAC_MAC
+  seq_printf(m, "rsbac_ind_softmode[MAC] is %i\n",
+                 rsbac_ind_softmode[SW_MAC]);
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+  seq_printf(m, "rsbac_ind_softmode[DAZ] is %i\n",
+                 rsbac_ind_softmode[SW_DAZ]);
+#endif
+#ifdef CONFIG_RSBAC_FF
+  seq_printf(m, "rsbac_ind_softmode[FF] is %i\n",
+                 rsbac_ind_softmode[SW_FF]);
+#endif
+#ifdef CONFIG_RSBAC_RC
+  seq_printf(m, "rsbac_ind_softmode[RC] is %i\n",
+                 rsbac_ind_softmode[SW_RC]);
+#endif
+#ifdef CONFIG_RSBAC_AUTH
+  seq_printf(m, "rsbac_ind_softmode[AUTH] is %i\n",
+                 rsbac_ind_softmode[SW_AUTH]);
+#endif
+#ifdef CONFIG_RSBAC_REG
+  seq_printf(m, "rsbac_ind_softmode[REG] is %i\n",
+                 rsbac_ind_softmode[SW_REG]);
+#endif
+#ifdef CONFIG_RSBAC_ACL
+  seq_printf(m, "rsbac_ind_softmode[ACL] is %i\n",
+                 rsbac_ind_softmode[SW_ACL]);
+#endif
+#ifdef CONFIG_RSBAC_CAP
+  seq_printf(m, "rsbac_ind_softmode[CAP] is %i\n",
+                 rsbac_ind_softmode[SW_CAP]);
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+  seq_printf(m, "rsbac_ind_softmode[JAIL] is %i\n",
+                 rsbac_ind_softmode[SW_JAIL]);
+#endif
+#ifdef CONFIG_RSBAC_RES
+  seq_printf(m, "rsbac_ind_softmode[RES] is %i\n",
+                 rsbac_ind_softmode[SW_RES]);
+#endif
+#endif
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+  seq_printf(m, "rsbac_freeze is %i\n",
+                 rsbac_freeze);
+#endif
+  seq_printf(m, "rsbac_list_recover is %i (read-only)\n",
+                 rsbac_list_recover);
+  seq_printf(m, "rsbac_list_noread is %i (read-only)\n",
+                 rsbac_list_noread);
+  seq_printf(m, "rsbac_list_rcu_rate is %u\n",
+                 rsbac_list_rcu_rate);
+  seq_printf(m, "rsbac_list_auto_rehash_trigger is %u\n",
+                 rsbac_list_auto_rehash_trigger);
+#if defined(CONFIG_RSBAC_DAZ_CACHE)
+  /* RSBAC: DAZ - set cache ttl */
+  seq_printf(m, "rsbac_daz_ttl is %u\n",
+                 rsbac_daz_get_ttl());
+#endif
+#if defined(CONFIG_RSBAC_UDF_CACHE)
+  /* RSBAC: UDF - set cache ttl */
+  seq_printf(m, "rsbac_udf_ttl is %u\n",
+                 rsbac_udf_get_ttl());
+#endif
+#ifdef CONFIG_RSBAC_CAP_PROC_HIDE
+  seq_printf(m, "rsbac_cap_process_hiding is %i\n",
+                 rsbac_cap_process_hiding);
+#endif
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+  seq_printf(m, "rsbac_cap_log_missing is %i\n",
+                 rsbac_cap_log_missing);
+#endif
+#ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+  seq_printf(m, "rsbac_jail_log_missing is %i\n",
+                 rsbac_jail_log_missing);
+#endif
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+  seq_printf(m, "rsbac_dac_disable is %i\n",
+                 rsbac_dac_disable);
+#endif
+
+#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+  seq_printf(m, "rsbac_nosyslog is %i\n",
+                 rsbac_nosyslog);
+#endif
+
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+  seq_printf(m, "rsbac_syslog_rate is %u\n",
+                 rsbac_syslog_rate);
+#endif
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+  if (rsbac_fd_cache_disable)
+    seq_printf(m, "rsbac_fd_cache_disable is %u (read-only)\n",
+                   rsbac_fd_cache_disable);
+  else
+    seq_printf(m, "rsbac_fd_cache_ttl is %u\n",
+                   rsbac_fd_cache_ttl);
+  seq_printf(m, "rsbac_fd_cache_fuse is %u (read-only)\n",
+                   rsbac_fd_cache_fuse);
+  seq_printf(m, "rsbac_fd_cache_ceph is %u (read-only)\n",
+                   rsbac_fd_cache_ceph);
+#endif
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+  seq_printf(m, "rsbac_um_name_cache_disable is %u\n",
+             rsbac_um_name_cache_disable);
+  seq_printf(m, "rsbac_um_name_cache_ttl is %u\n",
+             rsbac_um_name_cache_ttl);
+#endif
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+  seq_printf(m, "rsbac_list_check_interval is %u\n",
+                 rsbac_list_check_interval);
+#endif
+
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+#if defined(CONFIG_RSBAC_LOG_REMOTE_TCP)
+  seq_printf(m, "rsbac_log_remote_addr (TCP) is %u.%u.%u.%u\n",
+                 NIPQUAD(rsbac_log_remote_addr));
+#else
+  seq_printf(m, "rsbac_log_remote_addr (UDP) is %u.%u.%u.%u\n",
+                 NIPQUAD(rsbac_log_remote_addr));
+#endif
+  seq_printf(m, "rsbac_log_remote_port is %u\n",
+                 ntohs(rsbac_log_remote_port));
+#endif
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+  seq_printf(m, "rsbac_no_delay_init is %i\n",
+                 rsbac_no_delay_init);
+  seq_printf(m, "rsbac_delayed_root is %02u:%02u\n",
+                 RSBAC_MAJOR(rsbac_delayed_root), RSBAC_MINOR(rsbac_delayed_root));
+#endif
+
+#if defined(CONFIG_RSBAC_UM_EXCL)
+  seq_printf(m, "rsbac_um_no_excl is %i\n",
+                 rsbac_um_no_excl);
+#endif
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+  seq_printf(m, "rsbac_rc_learn is %i\n",
+                 rsbac_rc_learn);
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+  seq_printf(m, "rsbac_auth_enable_login is %i\n",
+                 rsbac_auth_enable_login);
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+  seq_printf(m, "rsbac_auth_learn is %i\n",
+                 rsbac_auth_learn);
+#endif
+#endif
+
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+  seq_printf(m, "rsbac_cap_learn is %i\n",
+                 rsbac_cap_learn);
+#endif
+
+#if defined(CONFIG_RSBAC_ACL_LEARN)
+  seq_printf(m, "rsbac_acl_learn_fd is %i\n",
+                 rsbac_acl_learn_fd);
+#endif
+
+  seq_printf(m, "rsbac_no_defaults is %i\n",
+                 rsbac_no_defaults);
+#ifdef CONFIG_RSBAC_DEBUG
+  seq_printf(m, "rsbac_debug_write is %i\n",
+                 rsbac_debug_write);
+  seq_printf(m, "rsbac_debug_stack is %i\n",
+                 rsbac_debug_stack);
+  seq_printf(m, "rsbac_debug_lists is %i\n",
+                 rsbac_debug_lists);
+  seq_printf(m, "rsbac_debug_ds is %i\n",
+                 rsbac_debug_ds);
+  seq_printf(m, "rsbac_debug_aef is %i\n",
+                 rsbac_debug_aef);
+  seq_printf(m, "rsbac_debug_no_write is %i\n",
+                 rsbac_debug_no_write);
+
+#if defined(CONFIG_RSBAC_REG)
+/* Boolean debug switch for REG */
+  seq_printf(m, "rsbac_debug_reg is %i\n",
+                 rsbac_debug_reg);
+#endif
+
+#if defined(CONFIG_RSBAC_NET)
+/* Boolean debug switch for NET data structures */
+  seq_printf(m, "rsbac_debug_ds_net is %i\n",
+                 rsbac_debug_ds_net);
+/* Boolean debug switch for NET syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_net is %i\n",
+                 rsbac_debug_aef_net);
+/* Boolean debug switch for NET decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_net is %i\n",
+                 rsbac_debug_adf_net);
+#endif
+
+#if defined(CONFIG_RSBAC_MAC)
+/* Boolean debug switch for MAC data structures */
+  seq_printf(m, "rsbac_debug_ds_mac is %i\n",
+                 rsbac_debug_ds_mac);
+/* Boolean debug switch for MAC syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_mac is %i\n",
+                 rsbac_debug_aef_mac);
+/* Boolean debug switch for MAC decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_mac is %i\n",
+                 rsbac_debug_adf_mac);
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+/* Boolean debug switch for DAZ decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_daz is %i\n",
+                 rsbac_debug_adf_daz);
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+/* Boolean debug switch for RC data structures */
+  seq_printf(m, "rsbac_debug_ds_rc is %i\n",
+                 rsbac_debug_ds_rc);
+/* Boolean debug switch for RC syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_rc is %i\n",
+                 rsbac_debug_aef_rc);
+/* Boolean debug switch for RC decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_rc is %i\n",
+                 rsbac_debug_adf_rc);
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+/* Boolean debug switch for AUTH data structures */
+  seq_printf(m, "rsbac_debug_ds_auth is %i\n",
+                 rsbac_debug_ds_auth);
+
+/* Boolean debug switch for AUTH syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_auth is %i\n",
+                 rsbac_debug_aef_auth);
+
+/* Boolean debug switch for AUTH decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_auth is %i\n",
+                 rsbac_debug_adf_auth);
+#endif
+
+#if defined(CONFIG_RSBAC_ACL)
+/* Boolean debug switch for ACL data structures */
+  seq_printf(m, "rsbac_debug_ds_acl is %i\n",
+                 rsbac_debug_ds_acl);
+
+/* Boolean debug switch for ACL syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_acl is %i\n",
+                 rsbac_debug_aef_acl);
+
+/* Boolean debug switch for ACL decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_acl is %i\n",
+                 rsbac_debug_adf_acl);
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+/* Boolean debug switch for JAIL syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_jail is %i\n",
+                 rsbac_debug_aef_jail);
+/* Boolean debug switch for JAIL decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_jail is %i\n",
+                 rsbac_debug_adf_jail);
+#endif
+#if defined(CONFIG_RSBAC_PAX)
+/* Boolean debug switch for PAX decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_pax is %i\n",
+                 rsbac_debug_adf_pax);
+#endif
+#if defined(CONFIG_RSBAC_UM)
+/* Boolean debug switch for UM data structures */
+  seq_printf(m, "rsbac_debug_ds_um is %i\n",
+                 rsbac_debug_ds_um);
+/* Boolean debug switch for UM syscalls / AEF */
+  seq_printf(m, "rsbac_debug_aef_um is %i\n",
+                 rsbac_debug_aef_um);
+/* Boolean debug switch for UM decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_um is %i\n",
+                 rsbac_debug_adf_um);
+#endif
+#if defined(CONFIG_RSBAC_UDF)
+/* Boolean debug switch for UDF decisions / ADF */
+  seq_printf(m, "rsbac_debug_adf_udf is %i\n",
+                 rsbac_debug_adf_udf);
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+  seq_printf(m, "rsbac_debug_auto is %i\n",
+                 rsbac_debug_auto);
+#endif /* CONFIG_RSBAC_AUTO_WRITE > 0 */
+#ifdef CONFIG_RSBAC_FD_CACHE
+  seq_printf(m, "rsbac_debug_fdcache is %i\n",
+                 rsbac_debug_fdcache);
+#endif
+#endif /* DEBUG */
+
+#if defined(CONFIG_RSBAC_RMSG)
+  seq_printf(m, "rsbac_rmsg_maxentries is %u\n",
+                 rsbac_rmsg_maxentries);
+  seq_printf(m, "%u messages in log buffer, %lu messages lost, sequence is %u\n",
+                 log_list_head.count, log_list_head.lost, log_seq);
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+  seq_printf(m, "rsbac_log_remote_maxentries is %u\n",
+                 rsbac_log_remote_maxentries);
+  seq_printf(m, "%u messages in remote log buffer, %lu messages lost\n",
+                 remote_log_list_head.count, remote_log_list_head.lost);
+#endif
+#endif
+
+  return 0;
+}
+
+static ssize_t debug_proc_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos)
+{
+    ssize_t err;
+    char * k_buf;
+    char * p;
+    unsigned int debug_level;
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+    enum rsbac_switch_target_t sw_target;
+#endif
+
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(count > PROC_BLOCK_SIZE) {
+	return(-EOVERFLOW);
+    }
+    if(count < 10)
+      return -EINVAL;
+
+    if (!(k_buf = (char *) __get_free_page(GFP_KERNEL)))
+      return(-ENOMEM);
+    err = copy_from_user(k_buf, buf, count);
+    if(err < 0)
+      return err;
+
+  err = count;
+
+  if(!strncmp("debug", k_buf, 5) || !strncmp("rsbac", k_buf, 5))
+    {
+      p = k_buf + 6;
+    }
+  else
+  if(!strncmp("rsbac_debug", k_buf, 11))
+    {
+      p = k_buf + 12;
+    }
+  else
+    goto out;
+
+  if (!rsbac_is_initialized())
+    {
+      err = -ENOSYS;
+      goto out;
+    }
+    if(count < 10)
+      return -EINVAL;
+
+
+#ifdef CONFIG_RSBAC_SOFTMODE
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+/* Boolean switch for RSBAC individual soft mode */
+    /*
+     * Usage: echo "debug ind_softmode modname #N" > /proc/rsbac_info/debug
+     *   to set rsbac_ind_softmode[module] to given value
+     */
+    if(!strncmp("ind_softmode", k_buf + 6, 12)) 
+      {
+        char tmp[20];
+
+	p += 13;
+
+        if( *p == '\0' )
+          goto out;
+
+        sw_target = get_switch_target_nr(p);
+        if(sw_target == SW_NONE)
+          goto out;
+        get_switch_target_name(tmp, sw_target);
+        p += strlen(tmp)+1;
+        if( *p == '\0' )
+          goto out;
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            if(debug_level && rsbac_softmode_prohibit)
+              {
+                rsbac_printk(KERN_WARNING
+                             "debug_proc_write(): setting of softmode prohibited!\n");
+                err = -EPERM;
+                goto out;
+              }
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for switching\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.switch_target = sw_target;
+            if (!rsbac_adf_request(R_SWITCH_MODULE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_switch_target,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_ind_softmode[%s] to %u\n",
+                   tmp,
+                   debug_level);
+            rsbac_ind_softmode[sw_target] = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): rejecting invalid ind_softmode value (should be 0 or 1)\n");
+            err = -EINVAL;
+            goto out;
+          }
+      }
+#endif
+
+/* Boolean switch for RSBAC soft mode prohibit */
+    /*
+     * Usage: echo "debug softmode_prohibit #N" > /proc/rsbac_info/debug
+     *   to set rsbac_softmode to given value
+     */
+    if(!strncmp("softmode_prohibit", k_buf + 6, 17)) 
+      {
+	p += 18;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            if(!debug_level && rsbac_softmode_prohibit)
+              {
+                rsbac_printk(KERN_WARNING
+                             "debug_proc_write(): setting of softmode prohibited!\n");
+                err = -EPERM;
+                goto out;
+              }
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for softmode\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.switch_target = SW_SOFTMODE;
+            if (!rsbac_adf_request(R_SWITCH_MODULE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_switch_target,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_softmode_prohibit to %u\n",
+                   debug_level);
+            rsbac_softmode_prohibit = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): rejecting invalid softmode_prohibit value (should be 0 or 1)\n");
+            err = -EINVAL;
+            goto out;
+          }
+      }
+/* Boolean switch for RSBAC soft mode */
+    /*
+     * Usage: echo "debug softmode #N" > /proc/rsbac_info/debug
+     *   to set rsbac_softmode to given value
+     */
+    if(!strncmp("softmode", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            if(debug_level && rsbac_softmode_prohibit)
+              {
+                rsbac_printk(KERN_WARNING
+                             "debug_proc_write(): setting of softmode prohibited!\n");
+                err = -EPERM;
+                goto out;
+              }
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for softmode\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.switch_target = SW_SOFTMODE;
+            if (!rsbac_adf_request(R_SWITCH_MODULE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_switch_target,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_softmode to %u\n",
+                   debug_level);
+            rsbac_softmode = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): rejecting invalid softmode value (should be 0 or 1)\n");
+            err = -EINVAL;
+            goto out;
+          }
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+/* Boolean switch for disabling Linux DAC */
+    /*
+     * Usage: echo "debug dac_disable #N" > /proc/rsbac_info/debug
+     *   to set dac_disable to given value
+     */
+    if(!strncmp("dac_disable", k_buf + 6, 11)) 
+      {
+	p += 12;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for dac_disable\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_dac_disable to %u\n",
+                   debug_level);
+            rsbac_dac_disable = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): rejecting invalid dac_disabled value (should be 0 or 1)\n");
+            err = -EINVAL;
+            goto out;
+          }
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_FREEZE
+/* Boolean switch to enable freezing */
+    /*
+     * Usage: echo "debug freeze #N" > /proc/rsbac_info/debug
+     *   to set freeze to given value
+     */
+    if(!strncmp("freeze", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            if(!debug_level && rsbac_freeze)
+              {
+                rsbac_printk(KERN_WARNING
+                             "debug_proc_write(): RSBAC configuration frozen, no administration allowed!\n");
+                err = -EPERM;
+                goto out;
+              }
+
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for freeze\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.switch_target = SW_FREEZE;
+            if (!rsbac_adf_request(R_SWITCH_MODULE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_switch_target,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_freeze to %u\n",
+                   debug_level);
+            rsbac_freeze = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): rejecting invalid freeze value (should be 0 or 1)\n");
+            err = -EINVAL;
+            goto out;
+          }
+      }
+#endif
+
+/* Set list rcu rate limit */
+    /*
+     * Usage: echo "debug list_rcu_rate #n" > /proc/rsbac_info/debug
+     *   to set rate limit to given value
+     */
+    if(!strncmp("list_rcu_rate", k_buf + 6, 13)) 
+      {
+        u_int tmp_rate;
+
+	p += 14;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_rate = simple_strtoul(p, NULL, 0);
+        if (tmp_rate > 1000)
+          tmp_rate = 1000;
+
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for list_rcu_rate\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_list_rcu_rate to %u\n",
+                   tmp_rate);
+            rsbac_list_rcu_rate = tmp_rate;
+            err = count;
+            goto out;
+      }
+
+/* Set list rehash trigger */
+    /*
+     * Usage: echo "debug list_auto_rehash_trigger #n" > /proc/rsbac_info/debug
+     *   to set rehash trigger to given value
+     */
+    if(!strncmp("list_auto_rehash_trigger", k_buf + 6, 24))
+      {
+        u_int tmp_trigger;
+
+	p += 25;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_trigger = simple_strtoul(p, NULL, 0);
+        if (tmp_trigger < 4)
+          tmp_trigger = 4;
+
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for list_auto_rehash_trigger\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_list_auto_rehash_trigger to %u\n",
+                   tmp_trigger);
+            rsbac_list_auto_rehash_trigger = tmp_trigger;
+            err = count;
+            goto out;
+      }
+
+#ifdef CONFIG_RSBAC_DAZ_CACHE
+/* Set DAZ cache ttl */
+    /*
+     * Usage: echo "debug daz_ttl #n" > /proc/rsbac_info/debug
+     *   to set daz cache ttl to given value
+     */
+    if(!strncmp("daz_ttl", k_buf + 6, 7)) 
+      {
+        rsbac_time_t tmp_ttl;
+        union rsbac_target_id_t       i_tid;
+        union rsbac_attribute_value_t i_attr_val1;
+
+	p += 8;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_ttl = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for daz_ttl\n");
+              }
+#endif
+        /* Security Officer? */
+        i_tid.user = __kuid_val(current_uid());
+        if (rsbac_get_attr(SW_DAZ,
+                           T_USER,
+                           i_tid,
+                           A_daz_role,
+                           &i_attr_val1,
+                           TRUE))
+          {
+            rsbac_printk(KERN_WARNING
+                         "debug_proc_write(): rsbac_get_attr() returned error!\n");
+            return -EPERM;
+          }
+        /* if not sec_officer or admin, deny */
+        if (i_attr_val1.system_role != SR_security_officer)
+          #ifdef CONFIG_RSBAC_SOFTMODE
+          if(   !rsbac_softmode
+          #ifdef CONFIG_RSBAC_SOFTMODE_IND
+             && !rsbac_ind_softmode[SW_DAZ]
+          #endif
+            )
+          #endif
+          return -EPERM;
+        rsbac_printk(KERN_INFO
+                     "debug_proc_write(): setting rsbac_daz_ttl to %u\n",
+                     tmp_ttl);
+        rsbac_daz_set_ttl(tmp_ttl);
+        err = count;
+        goto out;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UDF_CACHE
+/* Set UDF cache ttl */
+    /*
+     * Usage: echo "debug udf_ttl #n" > /proc/rsbac_info/debug
+     *   to set udf cache ttl to given value
+     */
+    if(!strncmp("udf_ttl", k_buf + 6, 7))
+      {
+        rsbac_time_t tmp_ttl;
+        union rsbac_target_id_t       i_tid;
+        union rsbac_attribute_value_t i_attr_val1;
+
+	p += 8;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_ttl = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for udf_ttl\n");
+              }
+#endif
+        /* Security Officer? */
+        i_tid.user = __kuid_val(current_uid());
+        if (rsbac_get_attr(SW_UDF,
+                           T_USER,
+                           i_tid,
+                           A_udf_role,
+                           &i_attr_val1,
+                           TRUE))
+          {
+            rsbac_printk(KERN_WARNING
+                         "debug_proc_write(): rsbac_get_attr() returned error!\n");
+            return -EPERM;
+          }
+        /* if not sec_officer or admin, deny */
+        if (i_attr_val1.system_role != SR_security_officer)
+          #ifdef CONFIG_RSBAC_SOFTMODE
+          if(   !rsbac_softmode
+          #ifdef CONFIG_RSBAC_SOFTMODE_IND
+             && !rsbac_ind_softmode[SW_UDF]
+          #endif
+            )
+          #endif
+          return -EPERM;
+        rsbac_printk(KERN_INFO
+                     "debug_proc_write(): setting rsbac_udf_ttl to %u\n",
+                     tmp_ttl);
+        rsbac_udf_set_ttl(tmp_ttl);
+        err = count;
+        goto out;
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+/* Set remote address for remote logging */
+    /*
+     * Usage: echo "debug log_remote_addr a.b.c.d" > /proc/rsbac_info/debug
+     *   to set log_remote_addr to given value
+     */
+    if(!strncmp("log_remote_addr", k_buf + 6, 15)) 
+      {
+        __u32 tmp_addr;
+        char * tmp;
+
+	p += 16;
+        if( *p == '\0' )
+          goto out;
+
+        tmp=p;
+        while(*tmp)
+          {
+            if(   (*tmp != '.')
+               && (   (*tmp < '0')
+                   || (*tmp > '9')
+                  )
+              )
+              {
+                *tmp = 0;
+                break;
+              }
+            tmp++;
+          }
+        err = rsbac_net_str_to_inet(p, &tmp_addr);
+        if(!err)
+          {
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for remote_log_addr\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac_remote_log;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_log_remote_addr to %u.%u.%u.%u\n",
+                   NIPQUAD(tmp_addr));
+            rsbac_log_remote_addr = tmp_addr;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                get_error_name(tmp, err);
+                rsbac_printk(KERN_INFO
+                             "debug_proc_write(): converting remote socket address %s failed with error %s, exiting!\n",
+                             p,
+                             tmp);
+                rsbac_kfree(tmp);
+              }
+            err = -EINVAL;
+            goto out;
+          }
+      }
+/* Set remote port for remote logging */
+    /*
+     * Usage: echo "debug log_remote_port #n" > /proc/rsbac_info/debug
+     *   to set log_remote_port to given value
+     */
+    if(!strncmp("log_remote_port", k_buf + 6, 15)) 
+      {
+        __u16 tmp_port;
+
+	p += 16;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_port = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for remote_log_port\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac_remote_log;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_log_remote_port to %u\n",
+                   tmp_port);
+            rsbac_log_remote_port = htons(tmp_port);
+            err = count;
+            goto out;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_SYSLOG_RATE
+/* Set syslog rate limit */
+    /*
+     * Usage: echo "debug syslog_rate #n" > /proc/rsbac_info/debug
+     *   to set rate limit to given value
+     */
+    if(!strncmp("syslog_rate", k_buf + 6, 11)) 
+      {
+        u_int tmp_rate;
+
+	p += 12;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_rate = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for syslog_rate\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_syslog_rate to %u\n",
+                   tmp_rate);
+            rsbac_syslog_rate = tmp_rate;
+            err = count;
+            goto out;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+/* Set fd_cache_ttl */
+    /*
+     * Usage: echo "debug fd_cache_ttl #n" > /proc/rsbac_info/debug
+     *   to set ttl to given value
+     */
+    if(!strncmp("fd_cache_ttl", k_buf + 6, 12)) 
+      {
+        u_int tmp_ttl;
+
+	p += 13;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_ttl = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for fd_cache_ttl\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_fd_cache_ttl to %u\n",
+                   tmp_ttl);
+            rsbac_fd_cache_ttl = tmp_ttl;
+            err = count;
+            goto out;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+/* Set um_name_cache_ttl */
+    /*
+     * Usage: echo "debug um_name_cache_ttl #n" > /proc/rsbac_info/debug
+     *   to set ttl to given value
+     */
+    if(!strncmp("um_name_cache_ttl", k_buf + 6, 17))
+      {
+        u_int tmp_ttl;
+
+	p += 18;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_ttl = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for um_name_cache_ttl\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_um_name_cache_ttl to %u\n",
+                   tmp_ttl);
+            rsbac_um_name_cache_ttl = tmp_ttl;
+            err = count;
+            goto out;
+      }
+
+/* Set um_name_cache_disable */
+    /*
+     * Usage: echo "debug um_name_cache_disable #n" > /proc/rsbac_info/debug
+     *   to set ttl to given value
+     */
+    if(!strncmp("um_name_cache_disable", k_buf + 6, 21))
+      {
+        u_int tmp_disable;
+
+	p += 22;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_disable = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for um_name_cache_disable\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_um_name_cache_disable to %u\n",
+                   tmp_disable);
+            rsbac_um_name_cache_disable = tmp_disable;
+            err = count;
+            goto out;
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+/* Set rsbac_list_check_interval */
+    /*
+     * Usage: echo "debug list_check_interval #n" > /proc/rsbac_info/debug
+     *   to set ttl to given value
+     */
+    if(!strncmp("list_check_interval", k_buf + 6, 19)) 
+      {
+        u_int tmp_ttl;
+
+	p += 20;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_ttl = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for list_check_interval\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_list_check_interval to %u\n",
+                   tmp_ttl);
+            rsbac_list_check_interval = tmp_ttl;
+            err = count;
+            goto out;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+/* Boolean switch for disabling logging to syslog */
+    /*
+     * Usage: echo "debug nosyslog #N" > /proc/rsbac_info/debug
+     *   to set rsbac_nosyslog to given value
+     */
+    if(!strncmp("nosyslog", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for nosyslog\n");
+              }
+#endif
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_SWITCH_LOG,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_nosyslog to %u\n",
+                   debug_level);
+            rsbac_nosyslog = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): rejecting invalid nosyslog value (should be 0 or 1)\n");
+            err = -EINVAL;
+            goto out;
+          }
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_RMSG
+/* Set rsbac log messages limit */
+    /*
+     * Usage: echo "debug rmsg_maxentries #n" > /proc/rsbac_info/debug
+     *   to set limit to given value
+     */
+    if(!strncmp("rmsg_maxentries", k_buf + 6, 15)) 
+      {
+        u_int tmp_rate;
+
+	p += 16;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_rate = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for rmsg_maxentries\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rmsg_maxentries to %u\n",
+                   tmp_rate);
+            rsbac_rmsg_maxentries = tmp_rate;
+            err = count;
+            goto out;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_LOG_REMOTE
+/* Set rsbac remote log messages limit */
+    /*
+     * Usage: echo "debug log_remote_maxentries #n" > /proc/rsbac_info/debug
+     *   to set limit to given value
+     */
+    if(!strncmp("log_remote_maxentries", k_buf + 6, 21)) 
+      {
+        u_int tmp_rate;
+
+	p += 22;
+        if( *p == '\0' )
+          goto out;
+
+        tmp_rate = simple_strtoul(p, NULL, 0);
+#if defined(CONFIG_RSBAC_DEBUG)
+            if (rsbac_debug_aef)
+              {
+                rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF for log_remote_maxentries\n");
+              }
+#endif
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting log_remote_maxentries to %u\n",
+                   tmp_rate);
+            rsbac_log_remote_maxentries = tmp_rate;
+            err = count;
+            goto out;
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_RC_LEARN)
+/* Boolean switch for RC learning mode */
+    /*
+     * Usage: echo "debug rc_learn #N" > /proc/rsbac_info/debug
+     *   to set rsbac_rc_learn to given value
+     */
+    if(!strncmp("rc_learn", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.rc_learn = debug_level;
+            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_rc_learn,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_rc_learn to %u\n",
+                   debug_level);
+            rsbac_rc_learn = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH_LEARN)
+/* Boolean switch for AUTH learning mode */
+    /*
+     * Usage: echo "debug auth_learn #N" > /proc/rsbac_info/debug
+     *   to set rsbac_auth_learn to given value
+     */
+    if(!strncmp("auth_learn", k_buf + 6, 10)) 
+      {
+	p += 11;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.auth_learn = debug_level;
+            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_auth_learn,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_auth_learn to %u\n",
+                   debug_level);
+            rsbac_auth_learn = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_CAP_LEARN)
+/* Boolean switch for CAP learning mode */
+    /*
+     * Usage: echo "debug cap_learn #N" > /proc/rsbac_info/debug
+     *   to set rsbac_cap_learn to given value
+     */
+    if(!strncmp("cap_learn", k_buf + 6, 9)) 
+      {
+	p += 10;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_target_id.dummy = 0;
+            rsbac_attribute_value.cap_learn = debug_level;
+            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                                   task_pid(current),
+                                   T_NONE,
+                                   rsbac_target_id,
+                                   A_cap_learn,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_cap_learn to %u\n",
+                   debug_level);
+            rsbac_cap_learn = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+/* Boolean switch for CAP logging of missing caps */
+    /*
+     * Usage: echo "debug cap_log_missing #N" > /proc/rsbac_info/debug
+     *   to set rsbac_cap_log_missing to given value
+     */
+    if(!strncmp("cap_log_missing", k_buf + 6, 15)) 
+      {
+	p += 16;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_cap_log_missing to %u\n",
+                   debug_level);
+            rsbac_cap_log_missing = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+/* Boolean switch for JAIL logging of missing caps */
+    /*
+     * Usage: echo "debug jail_log_missing #N" > /proc/rsbac_info/debug
+     *   to set rsbac_jail_log_missing to given value
+     */
+    if(!strncmp("jail_log_missing", k_buf + 6, 16)) 
+      {
+	p += 17;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_target_id.scd = ST_rsbac;
+            rsbac_attribute_value.dummy = 0;
+            if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                                   task_pid(current),
+                                   T_SCD,
+                                   rsbac_target_id,
+                                   A_none,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_jail_log_missing to %u\n",
+                   debug_level);
+            rsbac_jail_log_missing = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+
+#if defined(CONFIG_RSBAC_ACL_LEARN)
+/* Boolean switch for ACL FD learning mode */
+    /*
+     * Usage: echo "debug acl_learn_fd #N" > /proc/rsbac_info/debug
+     *   to set rsbac_acl_learn_fd to given value
+     */
+    if(!strncmp("acl_learn_fd", k_buf + 6, 12)) 
+      {
+	p += 13;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            /* use default acls */
+            rsbac_target_id.file.device = RSBAC_ZERO_DEV;
+            rsbac_target_id.file.inode = 0;
+            rsbac_target_id.file.dentry_p = NULL;
+            rsbac_attribute_value.acl_learn = debug_level;
+
+            if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                                   task_pid(current),
+                                   T_FILE,
+                                   rsbac_target_id,
+                                   A_acl_learn,
+                                   rsbac_attribute_value))
+              {
+                err = -EPERM;
+                goto out;
+              }
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_acl_learn_fd to %u\n",
+                   debug_level);
+            rsbac_acl_learn_fd = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_DEBUG)
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "debug_proc_write(): calling ADF\n");
+      }
+    rsbac_target_id.scd = ST_rsbac;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_MODIFY_SYSTEM_DATA,
+                           task_pid(current),
+                           T_SCD,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        err = -EPERM;
+        goto out;
+      }
+
+#if defined(CONFIG_RSBAC_NET)
+/* Boolean debug switch for NET data structures */
+    /*
+     * Usage: echo "debug ds_net #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds_net to given value
+     */
+    if(!strncmp("ds_net", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds_net to %u\n",
+                   debug_level);
+            rsbac_debug_ds_net = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+/* Boolean debug switch for NET syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_net #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_net to given value
+     */
+    if(!strncmp("aef_net", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_net to %u\n",
+                   debug_level);
+            rsbac_debug_aef_net = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for NET decisions / ADF */
+    /*
+     * Usage: echo "debug adf_net #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_net to given value
+     */
+    if(!strncmp("adf_net", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_net to %u\n",
+                   debug_level);
+            rsbac_debug_adf_net = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_MAC)
+/* Boolean debug switch for MAC data structures */
+    /*
+     * Usage: echo "debug ds_mac #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds_mac to given value
+     */
+    if(!strncmp("ds_mac", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds_mac to %u\n",
+                   debug_level);
+            rsbac_debug_ds_mac = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+/* Boolean debug switch for MAC syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_mac #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_mac to given value
+     */
+    if(!strncmp("aef_mac", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_mac to %u\n",
+                   debug_level);
+            rsbac_debug_aef_mac = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for MAC decisions / ADF */
+    /*
+     * Usage: echo "debug adf_mac #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_mac to given value
+     */
+    if(!strncmp("adf_mac", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_mac to %u\n",
+                   debug_level);
+            rsbac_debug_adf_mac = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_DAZ)
+/* Boolean debug switch for DAZ decisions / ADF */
+    /*
+     * Usage: echo "debug adf_daz #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_daz to given value
+     */
+    if(!strncmp("adf_daz", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_daz to %u\n",
+                   debug_level);
+            rsbac_debug_adf_daz = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_RC)
+/* Boolean debug switch for RC data structures */
+    /*
+     * Usage: echo "debug ds_rc #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds_rc to given value
+     */
+    if(!strncmp("ds_rc", k_buf + 6, 5)) 
+      {
+	p += 6;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds_rc to %u\n",
+                   debug_level);
+            rsbac_debug_ds_rc = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+/* Boolean debug switch for RC syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_rc #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_rc to given value
+     */
+    if(!strncmp("aef_rc", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_rc to %u\n",
+                   debug_level);
+            rsbac_debug_aef_rc = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for RC decisions / ADF */
+    /*
+     * Usage: echo "debug adf_rc #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_rc to given value
+     */
+    if(!strncmp("adf_rc", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_rc to %u\n",
+                   debug_level);
+            rsbac_debug_adf_rc = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_AUTH)
+/* Boolean debug switch for AUTH data structures */
+    /*
+     * Usage: echo "debug ds_auth #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds_auth to given value
+     */
+    if(!strncmp("ds_auth", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds_auth to %u\n",
+                   debug_level);
+            rsbac_debug_ds_auth = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+/* Boolean debug switch for AUTH syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_auth #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_auth to given value
+     */
+    if(!strncmp("aef_auth", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_auth to %u\n",
+                   debug_level);
+            rsbac_debug_aef_auth = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for AUTH decisions / ADF */
+    /*
+     * Usage: echo "debug adf_auth #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_auth to given value
+     */
+    if(!strncmp("adf_auth", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_auth to %u\n",
+                   debug_level);
+            rsbac_debug_adf_auth = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+#endif
+
+#if defined(CONFIG_RSBAC_REG)
+/* Boolean debug switch for REG */
+    /*
+     * Usage: echo "debug reg #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_reg to given value
+     */
+    if(!strncmp("reg", k_buf + 6, 3)) 
+      {
+	p += 3;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_reg to %u\n",
+                   debug_level);
+            rsbac_debug_reg = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_ACL)
+/* Boolean debug switch for ACL data structures */
+    /*
+     * Usage: echo "debug ds_acl #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds_acl to given value
+     */
+    if(!strncmp("ds_acl", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds_acl to %u\n",
+                   debug_level);
+            rsbac_debug_ds_acl = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+/* Boolean debug switch for ACL syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_acl #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_acl to given value
+     */
+    if(!strncmp("aef_acl", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_acl to %u\n",
+                   debug_level);
+            rsbac_debug_aef_acl = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for ACL decisions / ADF */
+    /*
+     * Usage: echo "debug adf_acl #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_acl to given value
+     */
+    if(!strncmp("adf_acl", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_acl to %u\n",
+                   debug_level);
+            rsbac_debug_adf_acl = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_JAIL)
+/* Boolean debug switch for JAIL syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_jail #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_jail to given value
+     */
+    if(!strncmp("aef_jail", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_jail to %u\n",
+                   debug_level);
+            rsbac_debug_aef_jail = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for JAIL decisions / ADF */
+    /*
+     * Usage: echo "debug adf_jail #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_jail to given value
+     */
+    if(!strncmp("adf_jail", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_jail to %u\n",
+                   debug_level);
+            rsbac_debug_adf_jail = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_PAX)
+/* Boolean debug switch for PAX decisions / ADF */
+    /*
+     * Usage: echo "debug adf_pax #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_pax to given value
+     */
+    if(!strncmp("adf_pax", k_buf + 6, 7)) 
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_pax to %u\n",
+                   debug_level);
+            rsbac_debug_adf_pax = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_UDF)
+/* Boolean debug switch for UDF decisions / ADF */
+    /*
+     * Usage: echo "debug adf_udf #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_udf to given value
+     */
+    if(!strncmp("adf_udf", k_buf + 6, 7))
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_udf to %u\n",
+                   debug_level);
+            rsbac_debug_adf_udf = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#if defined(CONFIG_RSBAC_UM)
+/* Boolean debug switch for UM data structures */
+    /*
+     * Usage: echo "debug ds_um #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds_um to given value
+     */
+    if(!strncmp("ds_um", k_buf + 6, 5)) 
+      {
+	p += 6;
+
+        if( *p == '\0' )
+          goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds_um to %u\n",
+                   debug_level);
+            rsbac_debug_ds_um = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+/* Boolean debug switch for UM syscalls / AEF */
+    /*
+     * Usage: echo "debug aef_um #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef_um to given value
+     */
+    if(!strncmp("aef_um", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef_um to %u\n",
+                   debug_level);
+            rsbac_debug_aef_um = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for UM decisions / ADF */
+    /*
+     * Usage: echo "debug adf_um #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_adf_um to given value
+     */
+    if(!strncmp("adf_um", k_buf + 6, 6)) 
+      {
+	p += 7;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_adf_um to %u\n",
+                   debug_level);
+            rsbac_debug_adf_um = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+    /*
+     * Usage: echo "debug ds #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_ds to given value
+     */
+    if(!strncmp("ds", k_buf + 6, 2)) 
+      {
+	p += 3;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_ds to %u\n",
+                   debug_level);
+            rsbac_debug_ds = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+    /*
+     * Usage: echo "debug write #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_write to given value
+     */
+    if(!strncmp("write", k_buf + 6, 5)) 
+      {
+	p += 6;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_write to %u\n",
+                   debug_level);
+            rsbac_debug_write = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+    /*
+     * Usage: echo "debug stack #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_stack to given value
+     */
+    if(!strncmp("stack", k_buf + 6, 5)) 
+      {
+	p += 6;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_stack to %u\n",
+                   debug_level);
+            rsbac_debug_stack = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+    /*
+     * Usage: echo "debug lists #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_lists to given value
+     */
+    if(!strncmp("lists", k_buf + 6, 5)) 
+      {
+	p += 6;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_lists to %u\n",
+                   debug_level);
+            rsbac_debug_lists = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+    /* Boolean debug switch for AEF */
+    /*
+     * Usage: echo "debug aef #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_aef to given value
+     */
+    if(!strncmp("aef", k_buf + 6, 3)) 
+      {
+	p += 4;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_aef to %u\n",
+                   debug_level);
+            rsbac_debug_aef = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+/* Boolean debug switch for NO_WRITE */
+    /*
+     * Usage: echo "debug no_write #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_no_write to given value
+     */
+    if(!strncmp("no_write", k_buf + 6, 8)) 
+      {
+	p += 9;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_no_write to %u\n",
+                   debug_level);
+            rsbac_debug_no_write = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+    /*
+     * Usage: echo "debug auto #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_auto to given value
+     */
+    if(!strncmp("auto", k_buf + 6, 4)) 
+      {
+	p += 5;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0 or 1 */
+        if(!debug_level || (debug_level == 1))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_auto to %u\n",
+                   debug_level);
+            rsbac_debug_auto = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif /* CONFIG_RSBAC_AUTO_WRITE > 0 */
+
+#ifdef CONFIG_RSBAC_FD_CACHE
+    /*
+     * Usage: echo "debug fdcache #N" > /proc/rsbac_info/debug
+     *   to set rsbac_debug_fdcache to given value
+     */
+    if(!strncmp("fdcache", k_buf + 6, 7))
+      {
+	p += 8;
+
+        if( *p == '\0' )
+            goto out;
+
+        debug_level = simple_strtoul(p, NULL, 0);
+        /* only accept 0, 1 or 2 */
+        if(!debug_level || (debug_level == 1) || (debug_level == 2))
+          {
+            rsbac_printk(KERN_INFO
+                   "debug_proc_write(): setting rsbac_debug_fdcache to %u\n",
+                   debug_level);
+            rsbac_debug_fdcache = debug_level;
+            err = count;
+            goto out;
+          }
+        else
+          {
+            goto out_inv;
+          }
+      }
+#endif
+
+#endif /* DEBUG */
+
+out:
+  free_page((ulong) k_buf);
+  return err;
+
+out_inv:
+    rsbac_printk(KERN_INFO
+                 "debug_proc_write(): rejecting invalid debug level (should be 0 or 1)\n");
+    err = -EINVAL;
+    goto out;
+  }
+
+static int debug_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, debug_proc_show, NULL);
+}
+
+static const struct file_operations debug_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = debug_proc_open,
+       .read           = seq_read,
+       .write          = debug_proc_write,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static struct proc_dir_entry *debug;
+#endif /* defined(CONFIG_RSBAC_PROC) */
+
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+
+/* rsbac kernel daemon for remote logging */
+static int rsbaclogd(void * dummy)
+  {
+    struct task_struct *tsk = current;
+    int err;
+    int sock_fd;
+    struct rsbac_log_list_item_t * log_item;
+    struct sockaddr_in addr;
+    char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+    mm_segment_t oldfs;
+
+    rsbac_printk(KERN_INFO "rsbaclogd(): Initializing.\n");
+    wait_event_interruptible_timeout(rsbaclogd_wait, remote_log_list_head.count, rsbac_log_remote_interval);
+
+    /* create a socket */
+#ifndef CONFIG_RSBAC_LOG_REMOTE_TCP
+    sock_fd = sys_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    if(sock_fd < 0)
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbaclogd(): creating local log socket failed with error %s, exiting!\n",
+               get_error_name(tmp, sock_fd));
+        rsbaclogd_pid = NULL;
+        kfree(tmp);
+        return -RSBAC_EWRITEFAILED;
+      }
+    /* bind local address */
+    addr.sin_family = PF_INET;
+    addr.sin_port = htons(CONFIG_RSBAC_LOG_LOCAL_PORT);
+    err = rsbac_net_str_to_inet(CONFIG_RSBAC_LOG_LOCAL_ADDR,
+                                &addr.sin_addr.s_addr);
+    if(err < 0)
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbaclogd(): converting local socket address %s failed with error %s, exiting!\n",
+               CONFIG_RSBAC_LOG_LOCAL_ADDR,
+               get_error_name(tmp, err));
+        sys_close(sock_fd);
+        rsbaclogd_pid = NULL;
+        kfree(tmp);
+        return -RSBAC_EINVALIDVALUE;
+      }
+    /* change data segment - sys_bind reads address from user space */
+    oldfs = get_fs();
+    set_fs(KERNEL_DS);
+    err = sys_bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr));
+    set_fs(oldfs);
+    if(err < 0)
+      {
+        rsbac_printk(KERN_WARNING
+               "rsbaclogd(): binding local socket address %u.%u.%u.%u:%u failed with error %s, exiting!\n",
+               NIPQUAD(addr.sin_addr.s_addr),
+               CONFIG_RSBAC_LOG_LOCAL_PORT,
+               get_error_name(tmp, err));
+        sys_close(sock_fd);
+        rsbaclogd_pid = NULL;
+        kfree(tmp);
+        return -RSBAC_EWRITEFAILED;
+      }
+#endif /* ifndef CONFIG_RSBAC_LOG_REMOTE_TCP */
+#ifdef CONFIG_RSBAC_DEBUG
+    if(rsbac_debug_stack)
+      {
+        unsigned long * n = (unsigned long *) (current+1);
+
+        while (!*n)
+          n++;
+	rsbac_printk(KERN_DEBUG "rsbaclogd: free stack: %lu\n",
+	       (unsigned long) n - (unsigned long)(current+1));
+      }
+#endif
+    ignore_signals(tsk);
+    for(;;)
+      {
+        /* wait */
+        if (!wait_event_interruptible_timeout(rsbaclogd_wait, remote_log_list_head.count, rsbac_log_remote_interval))
+            continue;
+#ifdef CONFIG_PM
+	if (try_to_freeze())
+	    continue;
+#endif
+
+        /* Do nothing without remote address */
+        if(!rsbac_log_remote_addr || !rsbac_log_remote_port || !remote_log_list_head.head)
+          continue;
+
+
+#ifdef CONFIG_RSBAC_LOG_REMOTE_TCP
+        sock_fd = sys_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+        if(sock_fd < 0)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbaclogd(): creating local log socket failed with error %s, exiting!\n",
+                   get_error_name(tmp, sock_fd));
+            continue;
+          }
+        /* bind local address */
+        addr.sin_family = PF_INET;
+        addr.sin_port = htons(CONFIG_RSBAC_LOG_LOCAL_PORT);
+        err = rsbac_net_str_to_inet(CONFIG_RSBAC_LOG_LOCAL_ADDR,
+                                    &addr.sin_addr.s_addr);
+        if(err < 0)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbaclogd(): converting local socket address %s failed with error %s, exiting!\n",
+                   CONFIG_RSBAC_LOG_LOCAL_ADDR,
+                   get_error_name(tmp, err));
+            sys_close(sock_fd);
+            continue;
+          }
+        /* change data segment - sys_bind reads address from user space */
+        oldfs = get_fs();
+        set_fs(KERNEL_DS);
+        err = sys_bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr));
+        set_fs(oldfs);
+        if(err < 0)
+          {
+            rsbac_printk(KERN_WARNING
+                   "rsbaclogd(): binding local socket address %u.%u.%u.%u:%u failed with error %s, exiting!\n",
+                   NIPQUAD(addr.sin_addr.s_addr),
+                   CONFIG_RSBAC_LOG_LOCAL_PORT,
+                   get_error_name(tmp, err));
+            sys_close(sock_fd);
+            continue;
+          }
+        /* Target address might have changed */
+        addr.sin_family = PF_INET;
+        addr.sin_port = rsbac_log_remote_port;
+        addr.sin_addr.s_addr = rsbac_log_remote_addr;
+        /* connect to remote socket */
+        oldfs = get_fs();
+        set_fs(KERNEL_DS);
+        err = sys_connect(sock_fd,
+                         (struct sockaddr *)&addr,
+                         sizeof(addr));
+        set_fs(oldfs);
+        if(err < 0)
+          {
+            printk(KERN_WARNING
+                   "rsbaclogd(): connecting to remote TCP address %u.%u.%u.%u:%u failed with error %s, exiting!\n",
+                   NIPQUAD(addr.sin_addr.s_addr),
+                   ntohs(addr.sin_port),
+                   get_error_name(tmp, err));
+            sys_close(sock_fd);
+            continue;
+          }
+#else
+        /* Target address might have changed */
+        addr.sin_family = PF_INET;
+        addr.sin_port = rsbac_log_remote_port;
+        addr.sin_addr.s_addr = rsbac_log_remote_addr;
+#endif
+	while(remote_log_list_head.head)
+	  {
+            spin_lock(&rsbac_log_remote_lock);
+	    log_item = remote_log_list_head.head;
+	    /* Just to be sure */
+	    if (!log_item) {
+	      spin_unlock(&rsbac_log_remote_lock);
+	      break;
+	    }
+	    remote_log_list_head.head = log_item->next;
+	    if(!remote_log_list_head.head)
+		remote_log_list_head.tail = NULL;
+	    remote_log_list_head.count--;
+            spin_unlock(&rsbac_log_remote_lock);
+
+#ifdef CONFIG_RSBAC_LOG_REMOTE_TCP
+            /* change data segment - sys_send reads data and address from user space */
+            oldfs = get_fs();
+            set_fs(KERNEL_DS);
+            err = sys_send(sock_fd,
+                           log_item->buffer,
+                           log_item->size,
+                           0);
+            set_fs(oldfs);
+#else
+            /* change data segment - sys_sendto reads data and address from user space */
+            oldfs = get_fs();
+            set_fs(KERNEL_DS);
+            err = sys_sendto(sock_fd,
+                             log_item->buffer,
+                             log_item->size,
+                             MSG_DONTWAIT,
+                             (struct sockaddr *)&addr,
+                             sizeof(addr));
+            set_fs(oldfs);
+#endif
+            if(err < log_item->size)
+              {
+                if((err < 0) && (err != -EAGAIN))
+                  printk(KERN_WARNING
+                       "rsbaclogd(): sending to remote socket address %u.%u.%u.%u:%u failed with error %i!\n",
+                       NIPQUAD(addr.sin_addr.s_addr),
+                       ntohs(addr.sin_port),
+                       err);
+		/* Restore log item to beginning of the list */
+                spin_lock(&rsbac_log_remote_lock);
+		log_item->next = remote_log_list_head.head;
+	        remote_log_list_head.head = log_item;
+	        if(!remote_log_list_head.tail)
+		  remote_log_list_head.tail = log_item;
+		remote_log_list_head.count++;
+                spin_unlock(&rsbac_log_remote_lock);
+                break;
+              }
+	    else {
+		kfree(log_item);
+	    }
+          }
+#ifdef CONFIG_RSBAC_LOG_REMOTE_TCP
+        sys_close(sock_fd);
+#endif
+      }
+    return 0;
+  }
+#endif
+
+static int ll_conv(
+	void * old_desc,
+	void * old_data,
+	void * new_desc,
+	void * new_data)
+  {
+    rsbac_log_entry_t     * new_aci = new_data;
+    rsbac_old_log_entry_t * old_aci = old_data;
+    int i;
+
+    memcpy(new_desc, old_desc, sizeof(rsbac_adf_request_int_t));
+    for(i=0; i < T_NONE - 1; i++)
+      (*new_aci)[i] = (*old_aci)[i];
+    (*new_aci)[T_NONE - 1] = LL_denied;
+    (*new_aci)[T_NONE] = (*old_aci)[T_NONE - 1];
+    return 0;
+  }
+
+static int ll_old_conv(
+	void * old_desc,
+	void * old_data,
+	void * new_desc,
+	void * new_data)
+  {
+    rsbac_log_entry_t     * new_aci = new_data;
+    rsbac_old_log_entry_t * old_aci = old_data;
+    int i;
+
+    memcpy(new_desc, old_desc, sizeof(rsbac_adf_request_int_t));
+    for(i=0; i < T_NONE - 2; i++)
+      (*new_aci)[i] = (*old_aci)[i];
+    (*new_aci)[T_NONE - 1] = LL_denied;
+    (*new_aci)[T_NONE - 2] = LL_denied;
+    (*new_aci)[T_NONE] = (*old_aci)[T_NONE - 1];
+    return 0;
+  }
+
+rsbac_list_conv_function_t * ll_get_conv(rsbac_version_t old_version)
+  {
+    switch(old_version)
+      {
+        case RSBAC_LOG_LEVEL_OLD_VERSION:
+          return ll_conv;
+        case RSBAC_LOG_LEVEL_OLD_OLD_VERSION:
+          return ll_old_conv;
+        default:
+          return NULL;
+      }
+  }
+
+
+/********************************/
+/*             Init             */
+/********************************/
+
+#ifdef CONFIG_RSBAC_INIT_DELAY
+inline void rsbac_init_debug(void)
+#else
+inline void __init rsbac_init_debug(void)
+#endif
+  {
+    int i;
+#if defined(CONFIG_RSBAC_LOG_REMOTE)
+    struct task_struct * rsbaclogd_thread;
+#endif
+
+    if (!debug_initialized)
+      {
+        struct rsbac_list_info_t * info_p;
+        int tmperr;
+        rsbac_enum_t * def_data_p;
+
+        rsbac_printk(KERN_INFO "rsbac_init_debug(): Initializing\n");
+        info_p = rsbac_kmalloc(sizeof(*info_p));
+        if(!info_p)
+          {
+            memset(rsbac_log_levels, LL_denied, sizeof(rsbac_log_levels));
+            return;
+          }
+        def_data_p = rsbac_kmalloc(sizeof(rsbac_log_entry_t));
+        if(!def_data_p)
+          {
+            memset(rsbac_log_levels, LL_denied, sizeof(rsbac_log_levels));
+            rsbac_kfree(info_p);
+            return;
+          }
+        /* register log_levels list */
+        for(i=0; i<=T_NONE; i++)
+          def_data_p[i] = LL_denied;
+        info_p->version = RSBAC_LOG_LEVEL_VERSION;
+        info_p->key = RSBAC_LOG_LEVEL_KEY;
+        info_p->desc_size = sizeof(rsbac_adf_request_int_t);
+        info_p->data_size = sizeof(rsbac_log_entry_t);
+        info_p->max_age = 0;
+        tmperr = rsbac_list_register(RSBAC_LIST_VERSION,
+                                     &log_levels_handle,
+                                     info_p,
+                                     RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
+                                     NULL,
+                                     ll_get_conv,
+                                     def_data_p,
+                                     RSBAC_LOG_LEVEL_LIST_NAME,
+                                     RSBAC_AUTO_DEV);
+        rsbac_kfree(info_p);
+        rsbac_kfree(def_data_p);
+        if(tmperr)
+          {
+            char * tmp;
+
+            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+            if(tmp)
+              {
+                rsbac_printk(KERN_WARNING
+                       "rsbac_init_debug(): registering log levels list ll failed with error %s!\n",
+                       get_error_name(tmp, tmperr));
+                rsbac_kfree(tmp);
+              }
+            memset(rsbac_log_levels, LL_denied, sizeof(rsbac_log_levels));
+          }
+        else
+          {
+            rsbac_adf_request_int_t req;
+
+            for(req = 0; req < R_NONE; req++)
+              rsbac_list_get_data(log_levels_handle, &req, rsbac_log_levels[req]);
+          }
+
+        #if defined(CONFIG_RSBAC_PROC)
+	log_levels = proc_create("log_levels", S_IFREG | S_IRUGO | S_IWUGO, proc_rsbac_root_p, &log_levels_proc_fops);
+
+	debug = proc_create("debug", S_IFREG | S_IRUGO | S_IWUGO, proc_rsbac_root_p, &debug_proc_fops);
+
+        #if defined(CONFIG_RSBAC_RMSG)
+	rmsg = proc_create("rmsg", S_IFREG | S_IRUGO, proc_rsbac_root_p, &rmsg_proc_fops);
+        #endif
+        #endif
+
+        #if defined(CONFIG_RSBAC_LOG_REMOTE)
+        /* Start rsbac logging thread for auto write */
+        if(!rsbac_log_remote_port)
+          rsbac_log_remote_port = htons(CONFIG_RSBAC_LOG_REMOTE_PORT);
+        tmperr = rsbac_net_str_to_inet(rsbac_log_remote_addr_string,
+                                    &rsbac_log_remote_addr);
+        if(tmperr < 0)
+          {
+            char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+            if(tmp)
+              {
+                get_error_name(tmp, tmperr);
+                rsbac_printk(KERN_WARNING
+                             "rsbac_init_debug(): converting remote socket address %s failed with error %s, exiting!\n",
+                             rsbac_log_remote_addr_string,
+                             tmp);
+                rsbac_log_remote_addr = 0;
+                rsbac_kfree(tmp);
+              }
+          }
+	rsbaclogd_thread = kthread_create(rsbaclogd, NULL, "rsbaclogd");
+	wake_up_process(rsbaclogd_thread);
+	rsbaclogd_pid = task_pid(rsbaclogd_thread);
+        rsbac_printk(KERN_INFO "rsbac_init_debug(): Started rsbaclogd thread with pid %u\n",
+               pid_nr(rsbaclogd_pid));
+        #endif
+
+        #ifdef CONFIG_RSBAC_SYSLOG_RATE
+        init_timer(&rsbac_syslog_rate_timer);
+        rsbac_syslog_rate_timer.function = syslog_rate_reset;
+        rsbac_syslog_rate_timer.data = 0;
+        rsbac_syslog_rate_timer.expires = jiffies + HZ;
+        add_timer(&rsbac_syslog_rate_timer);
+        #endif
+
+        debug_initialized = TRUE;
+      }
+
+    #ifdef CONFIG_RSBAC_SOFTMODE
+    if(rsbac_softmode)
+      rsbac_printk(KERN_DEBUG "rsbac_softmode is set\n");
+    if(rsbac_softmode_prohibit)
+      rsbac_printk(KERN_DEBUG "rsbac_softmode_prohibit is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      rsbac_printk(KERN_DEBUG "rsbac_freeze is set\n");
+    #endif
+    if(rsbac_list_recover)
+      rsbac_printk(KERN_DEBUG "rsbac_list_recover is set\n");
+    if(rsbac_list_noread)
+      rsbac_printk(KERN_DEBUG "rsbac_list_noread is set\n");
+    #if defined(CONFIG_RSBAC_UM_EXCL)
+    if(rsbac_um_no_excl)
+      rsbac_printk(KERN_DEBUG "rsbac_um_no_excl is set\n");
+    #endif
+    #if defined(CONFIG_RSBAC_DAZ_CACHE)
+    rsbac_printk(KERN_DEBUG "rsbac_daz_ttl is %u\n",
+                 rsbac_daz_get_ttl());
+    #endif
+    #if defined(CONFIG_RSBAC_UDF_CACHE)
+    rsbac_printk(KERN_DEBUG "rsbac_udf_ttl is %u\n",
+                 rsbac_udf_get_ttl());
+    #endif
+    #if defined(CONFIG_RSBAC_RC_LEARN)
+    if(rsbac_rc_learn)
+      rsbac_printk(KERN_DEBUG "rsbac_rc_learn is set\n");
+    #endif
+    #if defined(CONFIG_RSBAC_AUTH_LEARN)
+    if(rsbac_auth_learn)
+      rsbac_printk(KERN_DEBUG "rsbac_auth_learn is set\n");
+    #endif
+    #if defined(CONFIG_RSBAC_CAP_LEARN)
+    if(rsbac_cap_learn)
+      rsbac_printk(KERN_DEBUG "rsbac_cap_learn is set\n");
+    #endif
+    #if defined(CONFIG_RSBAC_ACL_LEARN)
+    if(rsbac_acl_learn_fd)
+      rsbac_printk(KERN_DEBUG "rsbac_acl_learn_fd is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_CAP_PROC_HIDE
+    if(rsbac_cap_process_hiding)
+      rsbac_printk(KERN_DEBUG "rsbac_cap_process_hiding is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_CAP_LOG_MISSING
+    if(rsbac_cap_log_missing)
+      rsbac_printk(KERN_DEBUG "rsbac_cap_log_missing is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+    if(rsbac_jail_log_missing)
+      rsbac_printk(KERN_DEBUG "rsbac_jail_log_missing is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+    if(rsbac_dac_disable)
+      rsbac_printk(KERN_DEBUG "rsbac_dac_disable is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_RMSG_NOSYSLOG
+    if(rsbac_nosyslog)
+      rsbac_printk(KERN_DEBUG "rsbac_nosyslog is set\n");
+    #endif
+    #ifdef CONFIG_RSBAC_SYSLOG_RATE
+    if(rsbac_syslog_rate != CONFIG_RSBAC_SYSLOG_RATE_DEF)
+      rsbac_printk(KERN_DEBUG "rsbac_syslog_rate is %u\n",
+                   rsbac_syslog_rate);
+    #endif
+#ifdef CONFIG_RSBAC_FD_CACHE
+    if(rsbac_fd_cache_disable) {
+      rsbac_printk(KERN_DEBUG "rsbac_fd_cache_disable is %u\n",
+                   rsbac_fd_cache_disable);
+    } else {
+      if(rsbac_fd_cache_ttl != CONFIG_RSBAC_FD_CACHE_TTL)
+        rsbac_printk(KERN_DEBUG "rsbac_fd_cache_ttl is %u\n",
+                     rsbac_fd_cache_ttl);
+    }
+    if(rsbac_fd_cache_fuse) {
+      rsbac_printk(KERN_DEBUG "rsbac_fd_cache_fuse is %u\n",
+                   rsbac_fd_cache_fuse);
+    }
+    if(rsbac_fd_cache_ceph) {
+      rsbac_printk(KERN_DEBUG "rsbac_fd_cache_ceph is %u\n",
+                   rsbac_fd_cache_ceph);
+    }
+#endif
+#ifdef CONFIG_RSBAC_UM_NAME_CACHE
+    if(rsbac_um_name_cache_disable) {
+      rsbac_printk(KERN_DEBUG "rsbac_um_name_cache_disable is %u\n",
+                   rsbac_um_name_cache_disable);
+    } else {
+      if(rsbac_um_name_cache_ttl != CONFIG_RSBAC_UM_NAME_CACHE_TTL)
+        rsbac_printk(KERN_DEBUG "rsbac_um_name_cache_ttl is %u\n",
+                     rsbac_um_name_cache_ttl);
+    }
+#endif
+#if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+    if(rsbac_list_check_interval != CONFIG_RSBAC_LIST_CHECK_INTERVAL)
+      rsbac_printk(KERN_DEBUG "rsbac_list_check_interval is %u\n",
+                   rsbac_list_check_interval);
+#endif
+    #ifdef CONFIG_RSBAC_INIT_DELAY
+    if(rsbac_no_delay_init)
+      rsbac_printk(KERN_DEBUG "rsbac_no_delay_init is set\n");
+    if(rsbac_delayed_root_str[0])
+      rsbac_printk(KERN_DEBUG "rsbac_delayed_root is %s\n",
+             rsbac_delayed_root_str);
+    #endif
+    if(rsbac_no_defaults)
+      rsbac_printk(KERN_DEBUG "rsbac_no_defaults is set\n");
+
+#if defined(CONFIG_RSBAC_DEBUG)
+    if(rsbac_debug_ds)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds is set\n");
+    if(rsbac_debug_write)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_write is set\n");
+    if(rsbac_debug_no_write)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_no_write is set\n");
+    if(rsbac_debug_stack)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_stack is set\n");
+    if(rsbac_debug_lists)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_lists is set\n");
+    if(rsbac_debug_aef)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef is set\n");
+    if(rsbac_debug_adf_default != 1)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_default is set to %i\n",
+             rsbac_debug_adf_default);
+
+    #if defined(CONFIG_RSBAC_REG)
+    if(rsbac_debug_reg)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_reg is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_NET)
+    if(rsbac_debug_ds_net)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds_net is set\n");
+    if(rsbac_debug_aef_net)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_net is set\n");
+    if(rsbac_debug_adf_net)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_net is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_MAC)
+    if(rsbac_debug_ds_mac)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds_mac is set\n");
+    if(rsbac_debug_aef_mac)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_mac is set\n");
+    if(rsbac_debug_adf_mac)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_mac is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_DAZ)
+    if(rsbac_debug_adf_daz)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_daz is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_RC)
+    if(rsbac_debug_ds_rc)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds_rc is set\n");
+    if(rsbac_debug_aef_rc)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_rc is set\n");
+    if(rsbac_debug_adf_rc)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_rc is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_AUTH)
+    if(rsbac_debug_ds_auth)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds_auth is set\n");
+    if(rsbac_debug_aef_auth)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_auth is set\n");
+    if(rsbac_debug_adf_auth)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_auth is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_ACL)
+    if(rsbac_debug_ds_acl)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds_acl is set\n");
+    if(rsbac_debug_aef_acl)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_acl is set\n");
+    if(rsbac_debug_adf_acl)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_acl is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_JAIL)
+    if(rsbac_debug_aef_jail)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_jail is set\n");
+    if(rsbac_debug_adf_jail)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_jail is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_PAX)
+    if(rsbac_debug_adf_pax)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_pax is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_UDF)
+    if(rsbac_debug_adf_udf)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_udf is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_UM)
+    if(rsbac_debug_ds_um)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_ds_um is set\n");
+    if(rsbac_debug_aef_um)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_aef_um is set\n");
+    if(rsbac_debug_adf_um)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_adf_um is set\n");
+    #endif
+
+    #if defined(CONFIG_RSBAC_AUTO_WRITE) && (CONFIG_RSBAC_AUTO_WRITE > 0)
+    if(rsbac_debug_auto)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_auto is set\n");
+    #endif
+#ifdef CONFIG_RSBAC_FD_CACHE
+    if(rsbac_debug_fdcache)
+      rsbac_printk(KERN_DEBUG "rsbac_debug_fdcache is %u\n", rsbac_debug_fdcache);
+#endif
+#endif /* DEBUG */
+
+  }
+
diff --git a/rsbac/help/getname.c b/rsbac/help/getname.c
new file mode 100644
index 0000000..a16c3c1
--- /dev/null
+++ b/rsbac/help/getname.c
@@ -0,0 +1,1874 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2016:           */
+/*   Amon Ott <ao@rsbac.org>           */
+/* Helper functions for all parts      */
+/* Last modified: 05/Apr/2016          */
+/************************************* */
+
+#include <rsbac/types.h>
+#include <rsbac/getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+#include <rsbac/pax_getname.h>
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/network.h>
+#include <rsbac/net_getname.h>
+#else
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#endif
+
+static char request_list[R_NONE + 1][24] = {
+	"ADD_TO_KERNEL",
+	"ALTER",
+	"APPEND_OPEN",
+	"CHANGE_GROUP",
+	"CHANGE_OWNER",
+	"CHDIR",
+	"CLONE",
+	"CLOSE",
+	"CREATE",
+	"DELETE",
+	"EXECUTE",
+	"GET_PERMISSIONS_DATA",
+	"GET_STATUS_DATA",
+	"LINK_HARD",
+	"MODIFY_ACCESS_DATA",
+	"MODIFY_ATTRIBUTE",
+	"MODIFY_PERMISSIONS_DATA",
+	"MODIFY_SYSTEM_DATA",
+	"MOUNT",
+	"READ",
+	"READ_ATTRIBUTE",
+	"READ_WRITE_OPEN",
+	"READ_OPEN",
+	"REMOVE_FROM_KERNEL",
+	"RENAME",
+	"SEARCH",
+	"SEND_SIGNAL",
+	"SHUTDOWN",
+	"SWITCH_LOG",
+	"SWITCH_MODULE",
+	"TERMINATE",
+	"TRACE",
+	"TRUNCATE",
+	"UMOUNT",
+	"WRITE",
+	"WRITE_OPEN",
+	"MAP_EXEC",
+	"BIND",
+	"LISTEN",
+	"ACCEPT",
+	"CONNECT",
+	"SEND",
+	"RECEIVE",
+	"NET_SHUTDOWN",
+	"CHANGE_DAC_EFF_OWNER",
+	"CHANGE_DAC_FS_OWNER",
+	"CHANGE_DAC_EFF_GROUP",
+	"CHANGE_DAC_FS_GROUP",
+	"IOCTL",
+	"LOCK",
+	"AUTHENTICATE",
+	"MOVETO",
+	"NONE"
+};
+
+static char result_list[UNDEFINED + 1][12] = {
+	"NOT_GRANTED",
+	"GRANTED",
+	"DO_NOT_CARE",
+	"UNDEFINED"
+};
+
+static rsbac_switch_target_int_t attr_mod_list[A_none + 1] = {
+	SW_GEN,			/* pseudo */
+	SW_MAC,			/* security_level */
+	SW_MAC,			/* initial_security_level */
+	SW_MAC,			/* local_sec_level */
+	SW_MAC,			/* remote_sec_level */
+	SW_MAC,			/* min_security_level */
+	SW_MAC,			/* mac_categories */
+	SW_MAC,			/* mac_initial_categories */
+	SW_MAC,			/* local_mac_categories */
+	SW_MAC,			/* remote_mac_categories */
+	SW_MAC,			/* mac_min_categories */
+	SW_MAC,			/* mac_user_flags */
+	SW_MAC,			/* mac_process_flags */
+	SW_MAC,			/* mac_file_flags */
+	SW_NONE,		/* system_role */
+	SW_MAC,			/* mac_role */
+	SW_DAZ,			/* daz_role */
+	SW_FF,			/* ff_role */
+	SW_AUTH,			/* auth_role */
+	SW_CAP,			/* cap_role */
+	SW_JAIL,			/* jail_role */
+	SW_PAX,			/* pax_role */
+	SW_MAC,			/* current_sec_level */
+	SW_MAC,			/* mac_curr_categories */
+	SW_MAC,			/* min_write_open */
+	SW_MAC,			/* min_write_categories */
+	SW_MAC,			/* max_read_open */
+	SW_MAC,			/* max_read_categories */
+	SW_MAC,			/* mac_auto */
+	SW_MAC,			/* mac_check */
+	SW_MAC,			/* mac_prop_trusted */
+	SW_NONE,		/* pm_role */
+	SW_NONE,		/* pm_process_type */
+	SW_NONE,		/* pm_current_task */
+	SW_NONE,		/* pm_object_class */
+	SW_NONE,		/* local_pm_object_class */
+	SW_NONE,		/* remote_pm_object_class */
+	SW_NONE,		/* pm_ipc_purpose */
+	SW_NONE,		/* local_pm_ipc_purpose */
+	SW_NONE,		/* remote_pm_ipc_purpose */
+	SW_NONE,		/* pm_object_type */
+	SW_NONE,		/* local_pm_object_type */
+	SW_NONE,		/* remote_pm_object_type */
+	SW_NONE,		/* pm_program_type */
+	SW_NONE,		/* pm_tp */
+	SW_NONE,		/* pm_task_set */
+	SW_DAZ,			/* daz_scanned */
+	SW_DAZ,			/* daz_scanner */
+	SW_FF,			/* ff_flags */
+	SW_RC,			/* rc_type */
+        SW_RC,                  /* rc_select_type */
+	SW_RC,			/* local_rc_type */
+	SW_RC,			/* remote_rc_type */
+	SW_RC,			/* rc_type_fd */
+	SW_RC,			/* rc_type_nt */
+	SW_RC,			/* rc_force_role */
+	SW_RC,			/* rc_initial_role */
+	SW_RC,			/* rc_role */
+	SW_RC,			/* rc_def_role */
+	SW_AUTH,			/* auth_may_setuid */
+	SW_AUTH,			/* auth_may_set_cap */
+	SW_AUTH,			/* auth_learn */
+	SW_CAP,			/* min_caps */
+	SW_CAP,			/* max_caps */
+	SW_CAP,			/* max_caps_user */
+	SW_CAP,			/* max_caps_program */
+	SW_JAIL,			/* jail_id */
+	SW_JAIL,			/* jail_parent */
+	SW_JAIL,			/* jail_ip */
+	SW_JAIL,			/* jail_flags */
+	SW_JAIL,			/* jail_max_caps */
+	SW_JAIL,			/* jail_scd_get */
+	SW_JAIL,			/* jail_scd_modify */
+	SW_PAX,			/* pax_flags */
+	SW_RES,			/* res_role */
+	SW_RES,			/* res_min */
+	SW_RES,			/* res_max */
+	SW_GEN,			/* log_array_low */
+	SW_GEN,			/* local_log_array_low */
+	SW_GEN,			/* remote_log_array_low */
+	SW_GEN,			/* log_array_high */
+	SW_GEN,			/* local_log_array_high */
+	SW_GEN,			/* remote_log_array_high */
+	SW_GEN,			/* log_program_based */
+	SW_GEN,			/* log_user_based */
+	SW_GEN,			/* symlink_add_remote_ip */
+	SW_GEN,			/* symlink_add_uid */
+	SW_GEN,			/* symlink_add_mac_level */
+	SW_GEN,			/* symlink_add_rc_role */
+	SW_GEN,			/* linux_dac_disable */
+	SW_CAP,			/* cap_process_hiding */
+	SW_GEN,			/* fake_root_uid */
+	SW_GEN,			/* audit_uid */
+	SW_GEN,			/* auid_exempt */
+	SW_AUTH,			/* auth_last_auth */
+	SW_GEN,			/* remote_ip */
+	SW_CAP,                 /* cap_ld_env */
+	SW_DAZ,                 /* daz_do_scan */
+	SW_GEN,			/* vset */
+	SW_UDF,			/* udf_role */
+	SW_UDF,			/* udf_checked */
+	SW_UDF,			/* udf_checker */
+	SW_UDF,			/* udf_do_check */
+#ifdef __KERNEL__
+	/* adf-request helpers */
+	SW_NONE,		/* group */
+	SW_NONE,		/* signal */
+	SW_NONE,		/* mode */
+	SW_NONE,		/* nlink */
+	SW_NONE,		/* switch_target */
+	SW_NONE,		/* mod_name */
+	SW_NONE,		/* request */
+	SW_NONE,		/* trace_request */
+	SW_NONE,		/* auth_add_f_cap */
+	SW_NONE,		/* auth_remove_f_cap */
+	SW_NONE,		/* auth_get_caplist */
+	SW_NONE,		/* prot_bits */
+	SW_NONE,		/* internal */
+	SW_NONE,		/* create_data */
+	SW_NONE,		/* new_object */
+	SW_NONE,		/* rlimit */
+	SW_NONE,		/* new_dir_dentry_p */
+	SW_NONE,		/* auth_program_file */
+	SW_NONE,		/* auth_start_uid */
+	SW_NONE,		/* auth_start_euid */
+	SW_NONE,		/* auth_start_gid */
+	SW_NONE,		/* auth_start_egid */
+	SW_NONE,		/* acl_learn */
+	SW_NONE,		/* priority */
+	SW_NONE,		/* pgid */
+	SW_NONE,		/* kernel_thread */
+	SW_NONE,		/* open_flag */
+	SW_NONE,		/* reboot_cmd */
+	SW_NONE,		/* setsockopt_level */
+	SW_NONE,		/* ioctl_cmd */
+	SW_NONE,		/* f_mode */
+	SW_NONE,		/* process */
+	SW_NONE,		/* sock_type */
+	SW_NONE,		/* pagenr */
+	SW_NONE,		/* cap_learn */
+	SW_NONE,		/* rc_learn */
+	SW_NONE,		/* old_dir_inode_p */
+#endif
+	SW_NONE /* none */
+};
+
+static char attribute_list[A_none + 1][23] = {
+	"pseudo",
+	"security_level",
+	"initial_security_level",
+	"local_sec_level",
+	"remote_sec_level",
+	"min_security_level",
+	"mac_categories",
+	"mac_initial_categories",
+	"local_mac_categories",
+	"remote_mac_categories",
+	"mac_min_categories",
+	"mac_user_flags",
+	"mac_process_flags",
+	"mac_file_flags",
+	"system_role",
+	"mac_role",
+	"daz_role",
+	"ff_role",
+	"auth_role",
+	"cap_role",
+	"jail_role",
+	"pax_role",
+	"current_sec_level",
+	"mac_curr_categories",
+	"min_write_open",
+	"min_write_categories",
+	"max_read_open",
+	"max_read_categories",
+	"mac_auto",
+	"mac_check",
+	"mac_prop_trusted",
+	"pm_role",
+	"pm_process_type",
+	"pm_current_task",
+	"pm_object_class",
+	"local_pm_object_class",
+	"remote_pm_object_class",
+	"pm_ipc_purpose",
+	"local_pm_ipc_purpose",
+	"remote_pm_ipc_purpose",
+	"pm_object_type",
+	"local_pm_object_type",
+	"remote_pm_object_type",
+	"pm_program_type",
+	"pm_tp",
+	"pm_task_set",
+	"daz_scanned",
+	"daz_scanner",
+	"ff_flags",
+	"rc_type",
+	"rc_select_type",
+	"local_rc_type",
+	"remote_rc_type",
+	"rc_type_fd",
+	"rc_type_nt",
+	"rc_force_role",
+	"rc_initial_role",
+	"rc_role",
+	"rc_def_role",
+	"auth_may_setuid",
+	"auth_may_set_cap",
+	"auth_learn",
+	"min_caps",
+	"max_caps",
+	"max_caps_user",
+	"max_caps_program",
+	"jail_id",
+	"jail_parent",
+	"jail_ip",
+	"jail_flags",
+	"jail_max_caps",
+	"jail_scd_get",
+	"jail_scd_modify",
+	"pax_flags",
+	"res_role",
+	"res_min",
+	"res_max",
+	"log_array_low",
+	"local_log_array_low",
+	"remote_log_array_low",
+	"log_array_high",
+	"local_log_array_high",
+	"remote_log_array_high",
+	"log_program_based",
+	"log_user_based",
+	"symlink_add_remote_ip",
+	"symlink_add_uid",
+	"symlink_add_mac_level",
+	"symlink_add_rc_role",
+	"linux_dac_disable",
+	"cap_process_hiding",
+	"fake_root_uid",
+	"audit_uid",
+	"auid_exempt",
+	"auth_last_auth",
+	"remote_ip",
+	"cap_ld_env",
+	"daz_do_scan",
+	"vset",
+	"udf_role",
+	"udf_checked",
+	"udf_checker",
+	"udf_do_check",
+#ifdef __KERNEL__
+	/* adf-request helpers */
+	"owner",
+	"group",
+	"signal",
+	"mode",
+	"nlink",
+	"switch_target",
+	"mod_name",
+	"request",
+	"trace_request",
+	"auth_add_f_cap",
+	"auth_remove_f_cap",
+	"auth_get_caplist",
+	"prot_bits",
+	"internal",
+	"create_data",
+	"new_object",
+	"rlimit",
+	"new_dir_dentry_p",
+	"program_file",
+	"auth_start_uid",
+	"auth_start_euid",
+	"auth_start_gid",
+	"auth_start_egid",
+	"acl_learn",
+	"priority",
+	"pgid",
+	"kernel_thread",
+	"open_flag",
+	"reboot_cmd",
+	"setsockopt_level",
+	"ioctl_cmd",
+	"f_mode",
+	"process",
+	"sock_type",
+	"pagenr",
+	"cap_learn",
+	"rc_learn",
+	"old_dir_inode_p",
+#endif
+	"none"
+};
+
+static char target_list[T_NONE + 1][11] = {
+	"FILE",
+	"DIR",
+	"FIFO",
+	"SYMLINK",
+	"DEV",
+	"IPC",
+	"SCD",
+	"USER",
+	"PROCESS",
+	"NETDEV",
+	"NETTEMP",
+	"NETOBJ",
+	"NETTEMP_NT",
+	"GROUP",
+	"FD",
+	"UNIXSOCK",
+	"NONE"
+};
+
+static char ipc_target_list[I_none + 1][9] = {
+	"sem",
+	"msg",
+	"shm",
+	"anonpipe",
+	"mqueue",
+	"anonunix",
+	"none"
+};
+
+static char switch_target_list[SW_NONE + 1][12] = {
+	"GEN",
+	"MAC",
+	"UDF",
+	"DAZ",
+	"FF",
+	"RC",
+	"AUTH",
+	"REG",
+	"ACL",
+	"CAP",
+	"JAIL",
+	"RES",
+	"PAX",
+	"SOFTMODE",
+	"DAC_DISABLE",
+	"UM",
+	"FREEZE",
+	"NONE"
+};
+
+static char error_list[RSBAC_EMAX][26] = {
+	"RSBAC_EPERM",
+	"RSBAC_EACCESS",
+	"RSBAC_EREADFAILED",
+	"RSBAC_EWRITEFAILED",
+	"RSBAC_EINVALIDPOINTER",
+	"RSBAC_ENOROOTDIR",
+	"RSBAC_EPATHTOOLONG",
+	"RSBAC_ENOROOTDEV",
+	"RSBAC_ENOTFOUND",
+	"RSBAC_ENOTINITIALIZED",
+	"RSBAC_EREINIT",
+	"RSBAC_ECOULDNOTADDDEVICE",
+	"RSBAC_ECOULDNOTADDITEM",
+	"RSBAC_ECOULDNOTCREATEPATH",
+	"RSBAC_EINVALIDATTR",
+	"RSBAC_EINVALIDDEV",
+	"RSBAC_EINVALIDTARGET",
+	"RSBAC_EINVALIDVALUE",
+	"RSBAC_EEXISTS",
+	"RSBAC_EINTERNONLY",
+	"RSBAC_EINVALIDREQUEST",
+	"RSBAC_ENOTWRITABLE",
+	"RSBAC_EMALWAREDETECTED",
+	"RSBAC_ENOMEM",
+	"RSBAC_EDECISIONMISMATCH",
+	"RSBAC_EINVALIDVERSION",
+	"RSBAC_EINVALIDMODULE",
+	"RSBAC_EEXPIRED",
+	"RSBAC_EMUSTCHANGE",
+	"RSBAC_EBUSY",
+	"RSBAC_EINVALIDTRANSACTION",
+	"RSBAC_EWEAKPASSWORD",
+	"RSBAC_EINVALIDLIST",
+	"RSBAC_EFROMINTERRUPT"
+};
+
+static char scd_type_list[ST_none + 1][17] = {
+	"time_strucs",
+	"clock",
+	"host_id",
+	"net_id",
+	"ioports",
+	"rlimit",
+	"swap",
+	"syslog",
+	"rsbac",
+	"rsbac_log",
+	"other",
+	"kmem",
+	"network",
+	"firewall",
+	"priority",
+	"sysfs",
+	"rsbac_remote_log",
+	"quota",
+	"sysctl",
+	"nfsd",
+	"ksyms",
+	"mlock",
+	"capability",
+	"kexec",
+	"videomem",
+	"none"
+};
+
+/* Attribute types */
+
+#ifndef __KERNEL__
+static char attribute_param_list[A_none + 1][194] = {
+	"user-pseudo (positive long integer)", /* pseudo */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, 254 = inherit, max. level 252", /* security_level */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, 254 = inherit, max. level 252", /* initial_security_level */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, 254 = inherit, max. level 252", /* local_sec_level */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, 254 = inherit, max. level 252", /* remote_sec_level */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, 254 = inherit, max. level 252", /* min_security_level */
+	"Bit Set String of length 64 for all categories", /* mac_categories */
+	"Bit Set String of length 64 for all categories", /* mac_initial_categories */
+	"Bit Set String of length 64 for all categories", /* local_mac_categories */
+	"Bit Set String of length 64 for all categories", /* remote_mac_categories */
+	"Bit Set String of length 64 for all categories", /* mac_min_categories */
+	"1 = override, 4 = trusted, 8 = write_up, 16 = read_up,\n\t32 = write_down, 64 = allow_mac_auto", /* mac_user_flags */
+	"1 = override, 2 = auto, 4 = trusted, 8 = write_up,\n\t16 = read_up, 32 = write_down, 128 = prop_trusted", /* mac_process_flags */
+	"2 = auto, 4 = trusted, 8 = write_up, 16 = read_up,\n\t32 = write_down", /* mac_file_flags */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* system_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* mac_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* daz_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* ff_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* auth_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* cap_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* jail_role */
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* pax_role */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, max. level 252", /* current_sec_level */
+	"Bit Set String of length 64 for all categories", /* mac_curr_categories */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, max. level 252", /* min_write_open */
+	"Bit Set String of length 64 for all categories", /* min_write_categories */
+	"0 = unclassified, 1 = confidential, 2 = secret,\n\t3 = top secret, max. level 252", /* max_read_open */
+	"Bit Set String of length 64 for all categories", /* max_read_categories */
+	"0 = no, 1 = yes, 2 = inherit (default value)", /* mac_auto */
+	"0 = false, 1 = true", /* mac_check */
+	"0 = false, 1 = true", /* mac_prop_trusted */
+	"0 = user, 1 = security officer, 2 = data protection officer,\n\t3 = TP-manager, 4 = system-admin", /* pm_role */
+	"0 = none, 1 = TP", /* pm_process_type */
+	"Task-ID (positive integer)", /* pm_current_task */
+	"Class-ID (positive integer)", /* pm_object_class */
+	"Class-ID (positive integer)", /* local_pm_object_class */
+	"Class-ID (positive integer)", /* remote_pm_object_class */
+	"Purpose-ID (positive integer)", /* pm_ipc_purpose */
+	"Purpose-ID (positive integer)", /* local_pm_ipc_purpose */
+	"Purpose-ID (positive integer)", /* remote_pm_ipc_purpose */
+	"0 = none, 1 = TP, 2 = personal data, 3 = non-personal data,\n\t4 = ipc, 5 = dir", /* pm_object_type */
+	"0 = none, 1 = TP, 2 = personal data, 3 = non-personal data,\n\t4 = ipc, 5 = dir", /* local_pm_object_type */
+	"0 = none, 1 = TP, 2 = personal data, 3 = non-personal data,\n\t4 = ipc, 5 = dir", /* remote_pm_object_type */
+	"0 = none, 1 = TP", /* pm_program_type */
+	"TP-ID (positive integer)", /* pm_tp */
+	"pm-task-list-ID (positive integer)", /* pm_task_set */
+	"0 = unscanned, 1 = infected, 2 = clean", /* daz_scanned */
+	"0 = FALSE, 1 = TRUE", /* daz_scanner */
+	"1 = read_only, 2 = execute_only, 4 = search_only, 8 = write_only,\n\t16 = secure_delete, 32 = no_execute, 64 = no_delete_or_rename,\n\t128 = add_inherited (or'd), 256 = append_only, 512 = no_mount", /* ff_flags */
+	"RC-type-id", /* rc_type */
+        "RC-type-id (-7 = use fd)", /* rc_select_type */
+	"RC-type-id", /* local_rc_type */
+	"RC-type-id", /* remote_rc_type */
+	"RC-type-id (-2 = inherit from parent)", /* rc_type_fd */
+	"RC-type-id", /* rc_type_nt */
+	"RC-role-id (-1 = inherit_user, -2 = inherit_process (keep),\n\t-3 = inherit_parent (def.),\n\t-4 = inherit_user_on_chown_only (root default)", /* rc_force_role */
+	"RC-role-id (-3 = inherit_parent (default),\n\t-5 = use_force_role (root default)", /* rc_initial_role */
+	"RC-role-id", /* rc_role */
+	"RC-role-id", /* rc_def_role */
+	"0 = off, 1 = full, 2 = last_auth_only, 3 = last_auth_and_gid", /* auth_may_setuid */
+	"0 = false, 1 = true", /* auth_may_set_cap */
+	"0 = false, 1 = true", /* auth_learn */
+	"Bit-Vector value or name list of desired caps", /* min_caps */
+	"Bit-Vector value or name list of desired caps", /* max_caps */
+	"Bit-Vector value or name list of desired caps", /* max_caps_user */
+	"Bit-Vector value or name list of desired caps", /* max_caps_program */
+	"JAIL ID (0 = off)", /* jail_id */
+	"JAIL ID (0 = no parent jail)", /* jail_parent */
+	"JAIL IP address a.b.c.d", /* jail_ip */
+	"JAIL flags (or'd, 1 = allow external IPC, 2 = allow all net families,\n\t4 = allow_rlimit, 8 = allow raw IP, 16 = auto adjust IP,\n\t32 = allow localhost, 64 = allow scd clock)", /* jail_flags */
+	"Bit-Vector value or name list of desired caps", /* jail_max_caps */
+	"List of SCD targets", /* jail_scd_get */
+	"List of SCD targets", /* jail_scd_modify */
+	"PAX flags with capital=on, non-capital=off, e.g. PeMRxS", /* pax_flags */
+	"0 = user, 1 = security officer, 2 = administrator", /* res_role */
+	"array of non-negative integer values, all 0 for unset", /* res_min */
+	"array of non-negative integer values, all 0 for unset", /* res_max */
+	"Bit-String for all Requests, low bit", /* log_array_low */
+	"Bit-String for all Requests, low bit", /* local_log_array_low */
+	"Bit-String for all Requests, low bit", /* remote_log_array_low */
+	"Bit-String for all Requests, high bit (l=0,h=0 = none, l=1,h=0 = denied,\n\tl=0,h=1 = full, l=1,h=1 = request based)", /* log_array_high */
+	"Bit-String for all Requests, high bit (l=0,h=0 = none, l=1,h=0 = denied,\n\tl=0,h=1 = full, l=1,h=1 = request based)", /* local_log_array_high */
+	"Bit-String for all Requests, high bit (l=0,h=0 = none, l=1,h=0 = denied,\n\tl=0,h=1 = full, l=1,h=1 = request based)", /* remote_log_array_high */
+	"Bit-String for all Requests", /* log_program_based */
+	"Bit-String for all Requests", /* log_user_based */
+	"Number of bytes to add, 0 to turn off", /* symlink_add_remote_ip */
+	"0 = false, 1 = true", /* symlink_add_uid */
+	"0 = false, 1 = true", /* symlink_add_mac_level */
+	"0 = false, 1 = true", /* symlink_add_rc_role */
+	"0 = false, 1 = true, 2 = inherit (default)", /* linux_dac_disable */
+	"0 = off (default), 1 = from other users, 2 = full", /* cap_process_hiding */
+	"0 = off (default), 1 = uid_only, 2 = euid_only, 3 = both", /* fake_root_uid */
+	"-3 = unset, uid otherwise", /* audit_uid */
+	"-3 = unset, uid otherwise", /* auid_exempt */
+	"-3 = unset, uid otherwise", /* auth_last_auth */
+	"32 Bit value in network byte order", /* remote_ip */
+	"0 = disallow executing of program file with LD_ variables set,\n\t1 = do not care (default)", /* cap_ld_env */
+	"0 = never, 1 = registered, 2 = always, 3 = inherit", /* daz_do_scan */
+	"non-negative virtual set number, 0 = default main set",
+	"0 = user, 1 = security officer, 2 = administrator,\n\t3 = auditor", /* udf_role */
+	"0 = unchecked, 1 = denied, 2 = allowed", /* udf_checked */
+	"0 = FALSE, 1 = TRUE", /* udf_checker */
+	"0 = never, 1 = always, 2 = inherit", /* udf_do_check */
+	"INVALID!"
+};
+#endif
+
+static char log_level_list[LL_invalid + 1][9] = {
+	"none",
+	"denied",
+	"full",
+	"request",
+	"invalid!"
+};
+
+static char cap_list[RSBAC_CAP_MAX + 1][17] = {
+	"CHOWN",
+	"DAC_OVERRIDE",
+	"DAC_READ_SEARCH",
+	"FOWNER",
+	"FSETID",
+	"KILL",
+	"SETGID",
+	"SETUID",
+	"SETPCAP",
+	"LINUX_IMMUTABLE",
+	"NET_BIND_SERVICE",
+	"NET_BROADCAST",
+	"NET_ADMIN",
+	"NET_RAW",
+	"IPC_LOCK",
+	"IPC_OWNER",
+	"SYS_MODULE",
+	"SYS_RAWIO",
+	"SYS_CHROOT",
+	"SYS_PTRACE",
+	"SYS_PACCT",
+	"SYS_ADMIN",
+	"SYS_BOOT",
+	"SYS_NICE",
+	"SYS_RESOURCE",
+	"SYS_TIME",
+	"SYS_TTY_CONFIG",
+	"MKNOD",
+	"LEASE",
+	"AUDIT_WRITE",
+	"AUDIT_CONTROL",
+	"SETFCAP",
+	"MAC_OVERRIDE",
+	"MAC_ADMIN",
+	"NONE"
+};
+
+#ifdef CONFIG_RSBAC_XSTATS
+static char syscall_list[RSYS_none + 1][30] = {
+    "version",
+    "stats",
+    "check",
+    "get_attr",
+    "get_attr_n",
+    "set_attr",
+    "set_attr_n",
+    "remove_target",
+    "remove_target_n",
+    "net_list_all_netdev",
+    "net_template",
+    "net_list_all_template",
+    "switch",
+    "get_switch",
+    "adf_log_switch",
+    "get_adf_log",
+    "write",
+    "log",
+    "mac_set_curr_level",
+    "mac_get_curr_level",
+    "mac_get_max_level",
+    "mac_get_min_level",
+    "mac_add_p_tru",
+    "mac_remove_p_tru",
+    "mac_add_f_tru",
+    "mac_remove_f_tru",
+    "mac_get_f_trulist",
+    "mac_get_p_trulist",
+    "stats_pm",
+    "pm",
+    "pm_change_current_task",
+    "pm_create_file",
+    "daz_flush_cache",
+    "rc_copy_role",
+    "rc_copy_type",
+    "rc_get_item",
+    "rc_set_item",
+    "rc_change_role",
+    "rc_get_eff_rights_n",
+    "rc_get_list",
+    "auth_add_p_cap",
+    "auth_remove_p_cap",
+    "auth_add_f_cap",
+    "auth_remove_f_cap",
+    "auth_get_f_caplist",
+    "auth_get_p_caplist",
+    "acl",
+    "acl_n",
+    "acl_get_rights",
+    "acl_get_rights_n",
+    "acl_get_tlist",
+    "acl_get_tlist_n",
+    "acl_get_mask",
+    "acl_get_mask_n",
+    "acl_group",
+    "reg",
+    "jail",
+    "init",
+    "rc_get_current_role",
+    "um_auth_name",
+    "um_auth_uid",
+    "um_add_user",
+    "um_add_group",
+    "um_add_gm",
+    "um_mod_user",
+    "um_mod_group",
+    "um_get_user_item",
+    "um_get_group_item",
+    "um_remove_user",
+    "um_remove_group",
+    "um_remove_gm",
+    "um_user_exists",
+    "um_group_exists",
+    "um_get_next_user",
+    "um_get_user_list",
+    "um_get_gm_list",
+    "um_get_gm_user_list",
+    "um_get_group_list",
+    "um_get_uid",
+    "um_get_gid",
+    "um_set_pass",
+    "um_set_pass_name",
+    "um_set_group_pass",
+    "um_check_account",
+    "um_check_account_name",
+    "list_ta_begin",
+    "list_ta_refresh",
+    "list_ta_commit",
+    "list_ta_forget",
+    "list_all_dev",
+    "acl_list_all_dev",
+    "list_all_user",
+    "acl_list_all_user",
+    "list_all_group",
+    "acl_list_all_group",
+    "list_all_ipc",
+    "rc_select_fd_create_type",
+    "um_select_vset",
+    "um_add_onetime",
+    "um_add_onetime_name",
+    "um_remove_all_onetime",
+    "um_remove_all_onetime_name",
+    "um_count_onetime",
+    "um_count_onetime_name",
+    "list_ta_begin_name",
+    "um_get_max_history",
+    "um_get_max_history_name",
+    "um_set_max_history",
+    "um_set_max_history_name",
+    "udf_flush_cache",
+    "none"
+};
+
+char *get_syscall_name(char *syscall_name,
+		       enum rsbac_syscall_t syscall)
+{
+	if (!syscall_name)
+		return (NULL);
+	if (syscall >= RSYS_none)
+		strcpy(syscall_name, "ERROR!");
+	else
+		strcpy(syscall_name, syscall_list[syscall]);
+	return (syscall_name);
+}
+#endif
+
+/*****************************************/
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_request_name);
+#endif
+#endif
+
+char *get_request_name(char *request_name,
+		       enum rsbac_adf_request_t request)
+{
+	if (!request_name)
+		return (NULL);
+	if (request >= R_NONE)
+		strcpy(request_name, "ERROR!");
+	else
+		strcpy(request_name, request_list[request]);
+	return (request_name);
+}
+
+enum rsbac_adf_request_t get_request_nr(const char *request_name)
+{
+	enum rsbac_adf_request_t i;
+
+	if (!request_name)
+		return (R_NONE);
+	for (i = 0; i < R_NONE; i++) {
+		if (!strcmp(request_name, request_list[i])) {
+			return (i);
+		}
+	}
+	return (R_NONE);
+}
+
+
+char *get_result_name(char *res_name, enum rsbac_adf_req_ret_t res)
+{
+	if (!res_name)
+		return (NULL);
+	if (res > UNDEFINED)
+		strcpy(res_name, "ERROR!");
+	else
+		strcpy(res_name, result_list[res]);
+	return (res_name);
+}
+
+enum rsbac_adf_req_ret_t get_result_nr(const char *res_name)
+{
+	enum rsbac_adf_req_ret_t i;
+
+	if (!res_name)
+		return (UNDEFINED);
+	for (i = 0; i < UNDEFINED; i++) {
+		if (!strcmp(res_name, result_list[i])) {
+			return (i);
+		}
+	}
+	return (UNDEFINED);
+}
+
+
+enum rsbac_switch_target_t get_attr_module(enum rsbac_attribute_t attr)
+{
+	if (attr > A_none)
+		return SW_NONE;
+	else
+		return attr_mod_list[attr];
+}
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_attribute_name);
+#endif
+#endif
+
+char *get_attribute_name(char *attr_name, enum rsbac_attribute_t attr)
+{
+	if (!attr_name)
+		return (NULL);
+	if (attr > A_none)
+		strcpy(attr_name, "ERROR!");
+	else
+		strcpy(attr_name, attribute_list[attr]);
+	return (attr_name);
+}
+
+enum rsbac_attribute_t get_attribute_nr(const char *attr_name)
+{
+	enum rsbac_attribute_t i;
+
+	if (!attr_name)
+		return (A_none);
+	for (i = 0; i < A_none; i++) {
+		if (!strcmp(attr_name, attribute_list[i])) {
+			return (i);
+		}
+	}
+	return (A_none);
+}
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_attribute_value_name);
+#endif
+#endif
+
+char *get_attribute_value_name(char *attr_val_name,
+			       enum rsbac_attribute_t attr,
+			       union rsbac_attribute_value_t *attr_val_p)
+{
+	if (!attr_val_name)
+		return (NULL);
+	if (attr > A_none)
+		strcpy(attr_val_name, "ERROR!");
+	else
+		switch (attr) {
+		case A_none:
+			strcpy(attr_val_name, "none");
+			break;
+#ifdef __KERNEL__
+		case A_create_data:
+			{
+				char *tmp =
+				    rsbac_kmalloc(RSBAC_MAXNAMELEN);
+
+				if (tmp) {
+					if (attr_val_p->create_data.
+					    dentry_p)
+						snprintf(attr_val_name,
+							 RSBAC_MAXNAMELEN -
+							 1,
+							 "%s %s, mode %o",
+							 get_target_name_only
+							 (tmp,
+							  attr_val_p->
+							  create_data.
+							  target),
+							 attr_val_p->
+							 create_data.
+							 dentry_p->d_name.
+							 name,
+							 attr_val_p->
+							 create_data.
+							 mode & S_IALLUGO);
+					else
+						snprintf(attr_val_name,
+							 RSBAC_MAXNAMELEN -
+							 1, "%s, mode %o",
+							 get_target_name_only
+							 (tmp,
+							  attr_val_p->
+							  create_data.
+							  target),
+							 attr_val_p->
+							 create_data.
+							 mode & S_IALLUGO);
+					rsbac_kfree(tmp);
+				}
+			}
+			break;
+		case A_mode:
+			sprintf(attr_val_name, "%o", attr_val_p->mode);
+			break;
+		case A_rlimit:
+			sprintf(attr_val_name, "%u:%lu:%lu",
+			        attr_val_p->rlimit.resource,
+			        attr_val_p->rlimit.limit.rlim_cur,
+			        attr_val_p->rlimit.limit.rlim_max);
+			break;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+		case A_owner:
+			if(RSBAC_UID_SET(attr_val_p->owner))
+				sprintf(attr_val_name, "%u/%u",
+					RSBAC_UID_SET(attr_val_p->owner),
+					RSBAC_UID_NUM(attr_val_p->owner));
+			else
+				sprintf(attr_val_name, "%u",
+					RSBAC_UID_NUM(attr_val_p->owner));
+			break;
+		case A_group:
+			if(RSBAC_GID_SET(attr_val_p->group))
+				sprintf(attr_val_name, "%u/%u",
+					RSBAC_GID_SET(attr_val_p->group),
+					RSBAC_GID_NUM(attr_val_p->group));
+			else
+				sprintf(attr_val_name, "%u",
+					RSBAC_GID_NUM(attr_val_p->group));
+			break;
+#endif
+		case A_priority:
+			sprintf(attr_val_name, "%i", attr_val_p->priority);
+			break;
+		case A_process:
+		case A_pgid:
+			{
+				struct task_struct *task_p;
+
+				task_p = get_pid_task(attr_val_p->process, PIDTYPE_PID);
+				if (task_p) {
+					if (pid_alive(task_p)) {
+						if(task_p->parent)
+							sprintf(attr_val_name, "%u(%s,parent=%u(%s))", task_p->pid, task_p->comm, task_p->parent->pid, task_p->parent->comm);
+						else
+							sprintf(attr_val_name, "%u(%s)", task_p->pid, task_p->comm);
+					} else {
+						sprintf(attr_val_name, "%u(dead)", pid_nr(attr_val_p->process));
+					}
+					put_task_struct(task_p);
+				} else {
+					sprintf(attr_val_name, "%u", pid_nr(attr_val_p->process));
+				}
+			}
+			break;
+		case A_mod_name:
+			if (attr_val_p->mod_name)
+				strncpy(attr_val_name,
+					attr_val_p->mod_name,
+					RSBAC_MAXNAMELEN - 1);
+			else
+				strcpy(attr_val_name, "unknown");
+			attr_val_name[RSBAC_MAXNAMELEN - 1] = 0;
+			break;
+		case A_auth_add_f_cap:
+		case A_auth_remove_f_cap:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if(   RSBAC_UID_SET(attr_val_p->auth_cap_range.first)
+			   || RSBAC_UID_SET(attr_val_p->auth_cap_range.last)
+			  )
+			  sprintf(attr_val_name, "%u/%u:%u/%u",
+				RSBAC_UID_SET(attr_val_p->auth_cap_range.first),
+				RSBAC_UID_NUM(attr_val_p->auth_cap_range.first),
+				RSBAC_UID_SET(attr_val_p->auth_cap_range.last),
+				RSBAC_UID_NUM(attr_val_p->auth_cap_range.last));
+			else
+#endif
+			sprintf(attr_val_name, "%u:%u",
+				RSBAC_UID_NUM(attr_val_p->auth_cap_range.first),
+				RSBAC_UID_NUM(attr_val_p->auth_cap_range.last));
+			break;
+		case A_switch_target:
+			get_switch_target_name(attr_val_name,
+					       attr_val_p->switch_target);
+			break;
+		case A_request:
+			get_request_name(attr_val_name,
+					 attr_val_p->request);
+			break;
+		case A_sock_type:
+			rsbac_get_net_type_name(attr_val_name,
+					attr_val_p->sock_type);
+			break;
+#endif
+#if defined(CONFIG_RSBAC_PAX) || !defined(__KERNEL__)
+		case A_pax_flags:
+			pax_print_flags(attr_val_name,
+					attr_val_p->pax_flags);
+			break;
+#endif
+#if defined(CONFIG_RSBAC_AUTH) || !defined(__KERNEL__)
+		case A_auth_last_auth:
+#if defined(CONFIG_RSBAC_AUTH_LEARN) && defined(__KERNEL__)
+		case A_auth_start_uid:
+		case A_auth_start_euid:
+#endif
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if(RSBAC_UID_SET(attr_val_p->auth_last_auth))
+			  sprintf(attr_val_name, "%u/%u",
+				RSBAC_UID_SET(attr_val_p->auth_last_auth),
+				RSBAC_UID_NUM(attr_val_p->auth_last_auth));
+			else
+#endif
+			sprintf(attr_val_name, "%u",
+				RSBAC_UID_NUM(attr_val_p->auth_last_auth));
+			break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH_GROUP
+		case A_auth_start_gid:
+#ifdef CONFIG_RSBAC_AUTH_DAC_GROUP
+		case A_auth_start_egid:
+#endif
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if(RSBAC_GID_SET(attr_val_p->auth_last_auth))
+			  sprintf(attr_val_name, "%u/%u",
+				RSBAC_GID_SET(attr_val_p->auth_last_auth),
+				RSBAC_GID_NUM(attr_val_p->auth_last_auth));
+			else
+#endif
+			sprintf(attr_val_name, "%u",
+				RSBAC_GID_NUM(attr_val_p->auth_start_gid));
+			break;
+#endif
+#if defined(CONFIG_RSBAC_FF) || !defined(__KERNEL__)
+		case A_ff_flags:
+			sprintf(attr_val_name, "%u",
+				attr_val_p->ff_flags);
+			break;
+#endif
+#if defined(CONFIG_RSBAC_UDF) || !defined(__KERNEL__)
+		case A_udf_checker:
+			sprintf(attr_val_name, "%u",
+				attr_val_p->udf_checker);
+			break;
+		case A_udf_do_check:
+			sprintf(attr_val_name, "%u",
+				attr_val_p->udf_do_check);
+			break;
+#endif
+		default:
+			snprintf(attr_val_name, RSBAC_MAXNAMELEN - 1, "%u",
+				 attr_val_p->u_dummy);
+		}
+	return (attr_val_name);
+}
+
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_scd_type_name);
+#endif
+#endif
+
+char *get_scd_type_name(char *res_name, enum rsbac_scd_type_t res)
+{
+	if (!res_name)
+		return (NULL);
+	if (res > ST_none)
+		strcpy(res_name, "ERROR!");
+	else
+		strcpy(res_name, scd_type_list[res]);
+	return (res_name);
+}
+
+enum rsbac_scd_type_t get_scd_type_nr(const char *res_name)
+{
+	enum rsbac_scd_type_t i;
+
+	if (!res_name)
+		return (ST_none);
+	for (i = 0; i < ST_none; i++) {
+		if (!strcmp(res_name, scd_type_list[i])) {
+			return (i);
+		}
+	}
+	return (ST_none);
+}
+
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_target_name);
+#endif
+#endif
+
+char *get_target_name(char *target_type_name,
+		      enum rsbac_target_t target,
+		      char *target_id_name, union rsbac_target_id_t tid)
+{
+#ifdef __KERNEL__
+	char *help_name;
+#else
+	char help_name[RSBAC_MAXNAMELEN + 4];
+#endif
+
+#ifdef __KERNEL__
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+	help_name = rsbac_kmalloc(CONFIG_RSBAC_MAX_PATH_LEN + 4);
+#else
+	help_name = rsbac_kmalloc(RSBAC_MAXNAMELEN + 4);
+#endif
+	if (!help_name)
+		return NULL;
+#endif
+
+	switch (target) {
+#ifdef __KERNEL__
+	case T_FD:
+		if(target_type_name)
+			strcpy(target_type_name, "FD");
+		if (!target_id_name)
+			break;
+		sprintf(target_id_name, "Device %02u:%02u Inode %lu",
+			RSBAC_MAJOR(tid.file.device),
+			RSBAC_MINOR(tid.file.device), (u_long) tid.file.inode);
+		if (tid.file.dentry_p && tid.file.dentry_p->d_name.name
+		    && tid.file.dentry_p->d_name.len) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			if (rsbac_get_full_path
+			    (tid.file.dentry_p, help_name,
+			     CONFIG_RSBAC_MAX_PATH_LEN) > 0) {
+				strcat(target_id_name, " Path ");
+				strcat(target_id_name, help_name);
+			}
+#else
+			int namelen =
+			    rsbac_min(tid.file.dentry_p->d_name.len,
+				      RSBAC_MAXNAMELEN);
+
+			strcat(target_id_name, " Name ");
+			strncpy(help_name, tid.file.dentry_p->d_name.name,
+				namelen);
+			help_name[namelen] = 0;
+			strcat(target_id_name, help_name);
+#endif
+		}
+		break;
+	case T_FILE:
+		if(target_type_name)
+			strcpy(target_type_name, "FILE");
+		if (!target_id_name)
+			break;
+		sprintf(target_id_name, "Device %02u:%02u Inode %lu",
+			RSBAC_MAJOR(tid.file.device),
+			RSBAC_MINOR(tid.file.device), (u_long) tid.file.inode);
+		if (tid.file.dentry_p && tid.file.dentry_p->d_name.name
+		    && tid.file.dentry_p->d_name.len) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			if (rsbac_get_full_path
+			    (tid.file.dentry_p, help_name,
+			     CONFIG_RSBAC_MAX_PATH_LEN) > 0) {
+				strcat(target_id_name, " Path ");
+				strcat(target_id_name, help_name);
+			}
+#else
+			int namelen =
+			    rsbac_min(tid.file.dentry_p->d_name.len,
+				      RSBAC_MAXNAMELEN);
+
+			strcat(target_id_name, " Name ");
+			strncpy(help_name, tid.file.dentry_p->d_name.name,
+				namelen);
+			help_name[namelen] = 0;
+			strcat(target_id_name, help_name);
+#endif
+		}
+		break;
+	case T_DIR:
+		if(target_type_name)
+			strcpy(target_type_name, "DIR");
+		if (!target_id_name)
+			break;
+		sprintf(target_id_name, "Device %02u:%02u Inode %lu",
+			RSBAC_MAJOR(tid.file.device),
+			RSBAC_MINOR(tid.file.device), (u_long) tid.dir.inode);
+		if (tid.dir.dentry_p && tid.dir.dentry_p->d_name.name
+		    && tid.dir.dentry_p->d_name.len) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			if (rsbac_get_full_path
+			    (tid.dir.dentry_p, help_name,
+			     CONFIG_RSBAC_MAX_PATH_LEN) > 0) {
+				strcat(target_id_name, " Path ");
+				strcat(target_id_name, help_name);
+			}
+#else
+			int namelen =
+			    rsbac_min(tid.dir.dentry_p->d_name.len,
+				      RSBAC_MAXNAMELEN);
+
+			strcat(target_id_name, " Name ");
+			strncpy(help_name, tid.dir.dentry_p->d_name.name,
+				namelen);
+			help_name[namelen] = 0;
+			strcat(target_id_name, help_name);
+#endif
+		}
+		break;
+	case T_FIFO:
+		if(target_type_name)
+			strcpy(target_type_name, "FIFO");
+		if (!target_id_name)
+			break;
+		sprintf(target_id_name, "Device %02u:%02u Inode %lu",
+			RSBAC_MAJOR(tid.file.device),
+			RSBAC_MINOR(tid.file.device), (u_long) tid.fifo.inode);
+		if (tid.fifo.dentry_p && tid.fifo.dentry_p->d_name.name
+		    && tid.fifo.dentry_p->d_name.len) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			if (rsbac_get_full_path
+			    (tid.fifo.dentry_p, help_name,
+			     CONFIG_RSBAC_MAX_PATH_LEN) > 0) {
+				strcat(target_id_name, " Path ");
+				strcat(target_id_name, help_name);
+			}
+#else
+			int namelen =
+			    rsbac_min(tid.fifo.dentry_p->d_name.len,
+				      RSBAC_MAXNAMELEN);
+
+			strcat(target_id_name, " Name ");
+			strncpy(help_name, tid.fifo.dentry_p->d_name.name,
+				namelen);
+			help_name[namelen] = 0;
+			strcat(target_id_name, help_name);
+#endif
+		}
+		break;
+	case T_SYMLINK:
+		if(target_type_name)
+			strcpy(target_type_name, "SYMLINK");
+		if (!target_id_name)
+			break;
+		sprintf(target_id_name, "Device %02u:%02u Inode %lu",
+			RSBAC_MAJOR(tid.symlink.device),
+			RSBAC_MINOR(tid.symlink.device), (u_long) tid.symlink.inode);
+		if (tid.symlink.dentry_p
+		    && tid.symlink.dentry_p->d_name.name
+		    && tid.symlink.dentry_p->d_name.len) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			if (rsbac_get_full_path
+			    (tid.symlink.dentry_p, help_name,
+			     CONFIG_RSBAC_MAX_PATH_LEN) > 0) {
+				strcat(target_id_name, " Path ");
+				strcat(target_id_name, help_name);
+			}
+#else
+			int namelen =
+			    rsbac_min(tid.symlink.dentry_p->d_name.len,
+				      RSBAC_MAXNAMELEN);
+
+			strcat(target_id_name, " Name ");
+			strncpy(help_name,
+				tid.symlink.dentry_p->d_name.name,
+				namelen);
+			help_name[namelen] = 0;
+			strcat(target_id_name, help_name);
+#endif
+		}
+		break;
+	case T_UNIXSOCK:
+		if(target_type_name)
+			strcpy(target_type_name, "UNIXSOCK");
+		if (!target_id_name)
+			break;
+		sprintf(target_id_name, "Device %02u:%02u Inode %lu",
+			RSBAC_MAJOR(tid.unixsock.device),
+			RSBAC_MINOR(tid.unixsock.device), (u_long) tid.unixsock.inode);
+		if (tid.symlink.dentry_p
+		    && tid.unixsock.dentry_p->d_name.name
+		    && tid.unixsock.dentry_p->d_name.len) {
+#ifdef CONFIG_RSBAC_LOG_FULL_PATH
+			if (rsbac_get_full_path
+			    (tid.unixsock.dentry_p, help_name,
+			     CONFIG_RSBAC_MAX_PATH_LEN) > 0) {
+				strcat(target_id_name, " Path ");
+				strcat(target_id_name, help_name);
+			}
+#else
+			int namelen =
+			    rsbac_min(tid.unixsock.dentry_p->d_name.len,
+				      RSBAC_MAXNAMELEN);
+
+			strcat(target_id_name, " Name ");
+			strncpy(help_name,
+				tid.unixsock.dentry_p->d_name.name,
+				namelen);
+			help_name[namelen] = 0;
+			strcat(target_id_name, help_name);
+#endif
+		}
+		break;
+	case T_DEV:
+		if(target_type_name)
+			strcpy(target_type_name, "DEV");
+		if (!target_id_name)
+			break;
+		switch (tid.dev.type) {
+		case D_block:
+			sprintf(target_id_name, "block %02u:%02u",
+				tid.dev.major, tid.dev.minor);
+			break;
+		case D_char:
+			sprintf(target_id_name, "char %02u:%02u",
+				tid.dev.major, tid.dev.minor);
+			break;
+		case D_block_major:
+			sprintf(target_id_name, "block major %02u",
+				tid.dev.major);
+			break;
+		case D_char_major:
+			sprintf(target_id_name, "char major %02u",
+				tid.dev.major);
+			break;
+		default:
+			sprintf(target_id_name, "*unknown* %02u:%02u",
+				tid.dev.major, tid.dev.minor);
+		}
+		break;
+	case T_NETOBJ:
+		if(target_type_name)
+			strcpy(target_type_name, "NETOBJ");
+		if (!target_id_name)
+			break;
+#ifdef CONFIG_NET
+		if (tid.netobj.sock_p
+		    && tid.netobj.sock_p->ops && tid.netobj.sock_p->sk) {
+			char type_name[RSBAC_MAXNAMELEN];
+
+			switch (tid.netobj.sock_p->ops->family) {
+			case AF_INET:
+				{
+					__u32 saddr;
+					__u16 sport;
+					__u32 daddr;
+					__u16 dport;
+					struct net_device *dev;
+					char ldevname[RSBAC_IFNAMSIZ + 10];
+					char rdevname[RSBAC_IFNAMSIZ + 10];
+
+					if (tid.netobj.local_addr) {
+						struct sockaddr_in *addr =
+						    tid.netobj.local_addr;
+
+						saddr =
+						    addr->sin_addr.s_addr;
+						sport =
+						    ntohs(addr->sin_port);
+					} else {
+						saddr =
+						    inet_sk(tid.netobj.
+							    sock_p->sk)->
+						    inet_saddr;
+						sport =
+						    inet_sk(tid.netobj.
+							    sock_p->sk)->
+						    inet_num;
+					}
+					if (tid.netobj.remote_addr) {
+						struct sockaddr_in *addr =
+						    tid.netobj.remote_addr;
+
+						daddr =
+						    addr->sin_addr.s_addr;
+						dport =
+						    ntohs(addr->sin_port);
+					} else {
+						daddr =
+						    inet_sk(tid.netobj.
+							    sock_p->sk)->
+						    inet_daddr;
+						dport =
+						    ntohs(inet_sk
+							  (tid.netobj.
+							   sock_p->sk)->
+							  inet_dport);
+					}
+					dev = ip_dev_find(&init_net, saddr);
+
+					if (dev) {
+						sprintf(ldevname, "%s:",
+							dev->name);
+						dev_put(dev);
+					} else
+						ldevname[0] = 0;
+					dev = ip_dev_find(&init_net, daddr);
+					if (dev) {
+						sprintf(rdevname, "%s:",
+							dev->name);
+						dev_put(dev);
+					} else
+						rdevname[0] = 0;
+					sprintf(target_id_name,
+						"%p INET %s proto %s local %s%u.%u.%u.%u:%u remote %s%u.%u.%u.%u:%u",
+						tid.netobj.sock_p,
+						rsbac_get_net_type_name
+						(type_name,
+						 tid.netobj.sock_p->type),
+						rsbac_get_net_protocol_name
+						(help_name,
+						 tid.netobj.sock_p->sk->
+						 sk_protocol),
+						ldevname,
+						NIPQUAD(saddr),
+						sport,
+						rdevname,
+						NIPQUAD(daddr), dport);
+				}
+				break;
+			case AF_NETLINK:
+				if (tid.netobj.local_addr || tid.netobj.remote_addr) {
+					struct sockaddr_nl *addr;
+
+					if(tid.netobj.local_addr)
+						addr = tid.netobj.local_addr;
+					else
+						addr = tid.netobj.remote_addr;
+
+					sprintf(target_id_name,
+						"%p NETLINK %s %s %u",
+						tid.netobj.sock_p,
+						rsbac_get_net_type_name
+						(type_name,
+						 tid.netobj.sock_p->type),
+						rsbac_get_net_netlink_family_name(
+							help_name,
+							tid.netobj.sock_p->sk->sk_protocol),
+						addr->nl_pid);
+				} else {
+					sprintf(target_id_name,
+						"%p NETLINK %s %s",
+						tid.netobj.sock_p,
+						rsbac_get_net_type_name
+						(type_name,
+						 tid.netobj.sock_p->type),
+						rsbac_get_net_netlink_family_name(
+							help_name,
+							tid.netobj.sock_p->sk->sk_protocol));
+				}
+				break;
+			default:
+				sprintf(target_id_name, "%p %s %s",
+					tid.netobj.sock_p,
+					rsbac_get_net_family_name
+					(help_name,
+					 tid.netobj.sock_p->ops->family),
+					rsbac_get_net_type_name(type_name,
+								tid.netobj.
+								sock_p->
+								type));
+			}
+		} else
+#endif				/* CONFIG_NET */
+		{
+			sprintf(target_id_name, "%p", tid.netobj.sock_p);
+		}
+		break;
+#endif				/* __KERNEL__ */
+	case T_IPC:
+		if(target_type_name)
+			strcpy(target_type_name, "IPC");
+		if (!target_id_name)
+			break;
+		switch (tid.ipc.type) {
+		case I_sem:
+			strcpy(target_id_name, "Sem-ID ");
+			break;
+		case I_msg:
+			strcpy(target_id_name, "Msg-ID ");
+			break;
+		case I_shm:
+			strcpy(target_id_name, "Shm-ID ");
+			break;
+		case I_anonpipe:
+			strcpy(target_id_name, "AnonPipe-ID ");
+			break;
+		case I_mqueue:
+			strcpy(target_id_name, "Mqueue-ID ");
+			break;
+		case I_anonunix:
+			strcpy(target_id_name, "AnonUnix-ID ");
+			break;
+		default:
+			strcpy(target_id_name, "ID ");
+			break;
+		};
+		sprintf(help_name, "%lu", tid.ipc.id.id_nr);
+		strcat(target_id_name, help_name);
+		break;
+	case T_SCD:
+		if(target_type_name)
+			strcpy(target_type_name, "SCD");
+		if (target_id_name)
+			get_scd_type_name(target_id_name, tid.scd);
+		break;
+	case T_USER:
+		if(target_type_name)
+			strcpy(target_type_name, "USER");
+		if (target_id_name) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if(RSBAC_UID_SET(tid.user))
+			  sprintf(target_id_name, "%u/%u",
+				RSBAC_UID_SET(tid.user),
+				RSBAC_UID_NUM(tid.user));
+			else
+#endif
+			sprintf(target_id_name, "%u", RSBAC_UID_NUM(tid.user));
+		}
+		break;
+	case T_PROCESS:
+		if(target_type_name)
+			strcpy(target_type_name, "PROCESS");
+		if (target_id_name) {
+			struct task_struct *task_p;
+
+			task_p = get_pid_task(tid.process, PIDTYPE_PID);
+			if (task_p) {
+				if (pid_alive(task_p)) {
+					if(task_p->parent)
+						sprintf(target_id_name, "%u(%s,parent=%u(%s))", task_p->pid, task_p->comm, task_p->parent->pid, task_p->parent->comm);
+					else
+						sprintf(target_id_name, "%u(%s)", task_p->pid, task_p->comm);
+				} else {
+					sprintf(target_id_name, "%u(dead)", pid_nr(tid.process));
+				}
+				put_task_struct(task_p);
+			} else {
+				sprintf(target_id_name, "%u", pid_nr(tid.process));
+			}
+		}
+		break;
+	case T_GROUP:
+		if(target_type_name)
+			strcpy(target_type_name, "GROUP");
+		if (target_id_name) {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+			if(RSBAC_GID_SET(tid.group))
+			  sprintf(target_id_name, "%u/%u",
+				RSBAC_GID_SET(tid.group),
+				RSBAC_GID_NUM(tid.group));
+			else
+#endif
+			sprintf(target_id_name, "%u", RSBAC_GID_NUM(tid.group));
+		}
+		break;
+	case T_NETDEV:
+		if(target_type_name)
+			strcpy(target_type_name, "NETDEV");
+		if (!target_id_name)
+			break;
+		strncpy(target_id_name, tid.netdev, RSBAC_IFNAMSIZ);
+		target_id_name[RSBAC_IFNAMSIZ] = 0;
+		break;
+	case T_NETTEMP:
+		if(target_type_name)
+			strcpy(target_type_name, "NETTEMP");
+		if (target_id_name)
+			sprintf(target_id_name, "%u", tid.nettemp);
+		break;
+	case T_NETTEMP_NT:
+		if(target_type_name)
+			strcpy(target_type_name, "NETTEMP_NT");
+		if (target_id_name)
+			sprintf(target_id_name, "%u", tid.nettemp);
+		break;
+	case T_NONE:
+		if(target_type_name)
+			strcpy(target_type_name, "NONE");
+		if (target_id_name)
+			strcpy(target_id_name, "NONE");
+		break;
+	default:
+		if(target_type_name)
+			strcpy(target_type_name, "ERROR!!!");
+		if (target_id_name)
+			sprintf(target_id_name, "%u", target);
+	}
+#ifdef __KERNEL__
+	rsbac_kfree(help_name);
+#endif
+	if(target_type_name)
+		return target_type_name;
+	else
+		return target_id_name;
+}
+
+char *get_target_name_only(char *target_type_name,
+			   enum rsbac_target_t target)
+{
+	if (!target_type_name)
+		return (NULL);
+
+	switch (target) {
+	case T_FILE:
+		strcpy(target_type_name, "FILE");
+		break;
+	case T_DIR:
+		strcpy(target_type_name, "DIR");
+		break;
+	case T_FIFO:
+		strcpy(target_type_name, "FIFO");
+		break;
+	case T_SYMLINK:
+		strcpy(target_type_name, "SYMLINK");
+		break;
+	case T_UNIXSOCK:
+		strcpy(target_type_name, "UNIXSOCK");
+		break;
+	case T_FD:
+		strcpy(target_type_name, "FD");
+		break;
+	case T_DEV:
+		strcpy(target_type_name, "DEV");
+		break;
+	case T_NETOBJ:
+		strcpy(target_type_name, "NETOBJ");
+		break;
+	case T_IPC:
+		strcpy(target_type_name, "IPC");
+		break;
+	case T_SCD:
+		strcpy(target_type_name, "SCD");
+		break;
+	case T_USER:
+		strcpy(target_type_name, "USER");
+		break;
+	case T_PROCESS:
+		strcpy(target_type_name, "PROCESS");
+		break;
+	case T_GROUP:
+		strcpy(target_type_name, "GROUP");
+		break;
+	case T_NETDEV:
+		strcpy(target_type_name, "NETDEV");
+		break;
+	case T_NETTEMP:
+		strcpy(target_type_name, "NETTEMP");
+		break;
+	case T_NETTEMP_NT:
+		strcpy(target_type_name, "NETTEMP_NT");
+		break;
+	case T_NONE:
+		strcpy(target_type_name, "NONE");
+		break;
+	default:
+		strcpy(target_type_name, "ERROR!!!");
+	}
+	return (target_type_name);
+}
+
+enum rsbac_target_t get_target_nr(const char *target_name)
+{
+	enum rsbac_target_t i;
+
+	if (!target_name)
+		return (T_NONE);
+	for (i = 0; i < T_NONE; i++) {
+		if (!strcmp(target_name, target_list[i])) {
+			return (i);
+		}
+	}
+	return (T_NONE);
+}
+
+char *get_ipc_target_name(char *ipc_name, enum rsbac_ipc_type_t target)
+{
+	if (!ipc_name)
+		return (NULL);
+	if (target > I_none)
+		strcpy(ipc_name, "ERROR!");
+	else
+		strcpy(ipc_name, ipc_target_list[target]);
+	return (ipc_name);
+}
+
+enum rsbac_ipc_type_t get_ipc_target_nr(const char *ipc_name)
+{
+	enum rsbac_ipc_type_t i;
+
+	if (!ipc_name)
+		return (I_none);
+	for (i = 0; i < I_none; i++) {
+		if (!strcmp(ipc_name, ipc_target_list[i])) {
+			return (i);
+		}
+	}
+	return (I_none);
+}
+
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_switch_target_name);
+#endif
+#endif
+
+char *get_switch_target_name(char *switch_name,
+			     enum rsbac_switch_target_t target)
+{
+	if (!switch_name)
+		return (NULL);
+	if (target > SW_NONE)
+		strcpy(switch_name, "ERROR!");
+	else
+		strcpy(switch_name, switch_target_list[target]);
+	return (switch_name);
+}
+
+enum rsbac_switch_target_t get_switch_target_nr(const char *switch_name)
+{
+	enum rsbac_switch_target_t i;
+
+	if (!switch_name)
+		return (SW_NONE);
+	for (i = 0; i < SW_NONE; i++) {
+#ifdef __KERNEL__
+		if (!strncmp
+		    (switch_name, switch_target_list[i],
+		     strlen(switch_target_list[i])))
+#else
+		if (!strcmp(switch_name, switch_target_list[i]))
+#endif
+		{
+			return (i);
+		}
+	}
+	return (SW_NONE);
+}
+
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(get_error_name);
+#endif
+#endif
+
+char *get_error_name(char *error_name, int error)
+{
+	if (!error_name)
+		return (NULL);
+#ifndef __KERNEL__
+	if((error == -1) && RSBAC_ERROR(-errno))
+		error = -errno;
+#endif
+	if (RSBAC_ERROR(error))
+		strcpy(error_name, error_list[(-error) - RSBAC_EPERM]);
+	else
+#ifdef __KERNEL__
+		inttostr(error_name, error);
+#else
+		strcpy(error_name, strerror(errno));
+#endif
+	return (error_name);
+}
+
+#ifndef __KERNEL__
+char *get_attribute_param(char *attr_name, enum rsbac_attribute_t attr)
+{
+	if (!attr_name)
+		return (NULL);
+	if (attr > A_none)
+		strcpy(attr_name, "ERROR!");
+	else
+		strcpy(attr_name, attribute_param_list[attr]);
+	return (attr_name);
+}
+#endif
+
+char *get_log_level_name(char *ll_name, enum rsbac_log_level_t target)
+{
+	if (!ll_name)
+		return (NULL);
+	if (target > LL_invalid)
+		strcpy(ll_name, "ERROR!");
+	else
+		strcpy(ll_name, log_level_list[target]);
+	return (ll_name);
+}
+
+enum rsbac_log_level_t get_log_level_nr(const char *ll_name)
+{
+	enum rsbac_log_level_t i;
+
+	if (!ll_name)
+		return (LL_invalid);
+	for (i = 0; i < LL_invalid; i++) {
+		if (!strcmp(ll_name, log_level_list[i])) {
+			return (i);
+		}
+	}
+	return (LL_invalid);
+}
+
+char *get_cap_name(char *name, u_int value)
+{
+	if (!name)
+		return (NULL);
+	if (value > CAP_NONE)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, cap_list[value]);
+	return (name);
+}
+
+int get_cap_nr(const char *name)
+{
+	int i;
+
+	if (!name)
+		return (CAP_NONE);
+	for (i = 0; i < CAP_NONE; i++) {
+		if (!strcasecmp(name, cap_list[i])) {
+			return (i);
+		}
+	}
+	return (CAP_NONE);
+}
diff --git a/rsbac/help/helpers.c b/rsbac/help/helpers.c
new file mode 100644
index 0000000..1939cb3
--- /dev/null
+++ b/rsbac/help/helpers.c
@@ -0,0 +1,1212 @@
+/************************************* */
+/* Rule Set Based Access Control       */
+/* Author and (c) 1999-2015:           */
+/*   Amon Ott <ao@rsbac.org>           */
+/* Helper functions for all parts      */
+/* Last modified: 07/Jul/2015          */
+/************************************* */
+
+#ifndef __KERNEL__
+#include <stdlib.h>
+#endif
+#include <rsbac/types.h>
+#include <rsbac/error.h>
+#include <rsbac/helpers.h>
+#include <rsbac/rc_types.h>
+#include <rsbac/getname.h>
+#include <rsbac/cap_getname.h>
+#include <rsbac/adf.h>
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <uapi/linux/magic.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/binfmts.h>
+#include <net/sock.h>
+#include <net/af_unix.h>
+#include <rsbac/aci.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/debug.h>
+#ifdef CONFIG_RSBAC_RC
+#include <rsbac/rc_getname.h>
+#endif
+#endif
+#ifndef __KERNEL__
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#endif
+
+int rsbac_get_vset_num(char * sourcename, rsbac_um_set_t * vset_p)
+  {
+    if (!sourcename || !vset_p)
+      return -RSBAC_EINVALIDPOINTER;
+    if (!strcmp(sourcename,"all")) {
+      *vset_p = RSBAC_UM_VIRTUAL_ALL;
+      return 0;
+    }
+    if (!strcmp(sourcename,"auto") || !strcmp(sourcename,"keep")) {
+      *vset_p = RSBAC_UM_VIRTUAL_KEEP;
+      return 0;
+    }
+#ifdef __KERNEL__
+    *vset_p = simple_strtoul(sourcename, NULL, 0);
+#else
+    *vset_p = strtoul(sourcename, NULL, 0);
+#endif
+    if(!*vset_p && strcmp(sourcename,"0"))
+      return -RSBAC_EINVALIDVALUE;
+    if (*vset_p > RSBAC_UM_VIRTUAL_MAX)
+      return -RSBAC_EINVALIDVALUE;
+    return 0;
+  }
+
+#ifndef __KERNEL__
+int rsbac_u32_compare(__u32 * a, __u32 * b)
+  {
+    if(*a < *b)
+     return -1;
+    if(*a > *b)
+      return 1;
+    return 0;
+  }
+
+int rsbac_user_compare(const void * a, const void * b)
+  {
+    return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
+  }
+
+int rsbac_group_compare(const void * a, const void * b)
+  {
+    return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
+  }
+
+int rsbac_nettemp_id_compare(const void * a, const void * b)
+  {
+    return rsbac_u32_compare((__u32 *) a, (__u32 *) b);
+  }
+
+int rsbac_dev_compare(const void *desc1, const void *desc2)
+{
+	int result;
+
+	result = memcmp(&((struct rsbac_dev_desc_t *)desc1)->type,
+			&((struct rsbac_dev_desc_t *)desc2)->type,
+			sizeof(((struct rsbac_dev_desc_t *)desc1)->type));
+	if (result)
+		return result;
+	result = memcmp(&((struct rsbac_dev_desc_t *)desc1)->major,
+			&((struct rsbac_dev_desc_t *)desc2)->major,
+			sizeof(((struct rsbac_dev_desc_t *)desc1)->major));
+	if (result)
+		return result;
+	return memcmp(&((struct rsbac_dev_desc_t *)desc1)->minor,
+		&((struct rsbac_dev_desc_t *)desc2)->minor,
+		sizeof(((struct rsbac_dev_desc_t *)desc1)->minor));
+}
+#endif
+
+char * inttostr(char * str, int i)
+  {
+    int j = 0;
+    
+    if(!str)
+      return(NULL);
+      
+    if (i<0)
+      {
+        str[j] = '-';
+        j++;
+        i = -i;
+      }
+    if (i>=10000)
+      {
+        str[j] = '0' + (i / 10000);
+        j++;
+      }
+    if (i>=1000)
+      {
+        str[j] = '0' + ((i % 10000) / 1000);
+        j++;
+      }
+    if (i>=100)
+      {
+        str[j] = '0' + ((i % 1000) / 100);
+        j++;
+      }
+    if (i>=10)
+      {
+        str[j] = '0' + ((i % 100) / 10);
+        j++;
+      }
+    str[j] = '0' + (i % 10);
+    j++;
+    str[j] = 0;
+    return (str);
+  };
+
+char * ulongtostr(char * str, u_long i)
+  {
+    int    j = 0;
+    u_long k = 1000000000;
+    
+    if(!str)
+      return(NULL);
+
+    if (i>=k)
+      {
+        str[j] = '0' + ((i / k) % 100);
+        j++;
+      }
+    k /= 10;
+
+    while (k>1)
+      {
+        if (i>=k)
+          {
+            str[j] = '0' + ((i % (k*10)) / k);
+            j++;
+          }
+        k /= 10;
+      };
+
+    str[j] = '0' + (i % 10);
+    j++;
+    str[j] = 0;
+    return (str);
+  };
+
+char * longtostr(char * str, long i)
+  {
+    int    j = 0;
+    u_long k = 1000000000;
+    
+    if(!str)
+      return(NULL);
+
+    if (i<0)
+      {
+        str[0] = '-';
+        j = 1;
+        i = -i;
+      }
+    if (i>=k)
+      {
+        str[j] = '0' + ((i / k) % 100);
+        j++;
+      }
+    k /= 10;
+
+    while (k>1)
+      {
+        if (i>=k)
+          {
+            str[j] = '0' + ((i % (k*10)) / k);
+            j++;
+          }
+        k /= 10;
+      };
+
+    str[j] = '0' + (i % 10);
+    j++;
+    str[j] = 0;
+    return (str);
+  };
+
+char * u64tostrmac(char * str, __u64 i)
+  {
+    int    j = 0;
+    __u64  k;
+
+    if(!str)
+      return(NULL);
+
+    k = 1;
+    for(j = RSBAC_MAC_MAX_CAT;j >= 0;j--)
+      {
+        if (i & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[RSBAC_MAC_NR_CATS] = 0;
+    return (str);
+  };
+
+#ifndef __KERNEL__
+
+void error_exit(int error)
+  {
+    char tmp1[80];
+
+    if(error<0)
+      {
+        get_error_name(tmp1,error);
+        fprintf(stderr, "Error: %s\n", tmp1);
+        exit(1);
+      }
+  }
+
+void show_error(int error)
+  {
+    char tmp1[80];
+
+    if(error<0)
+      {
+        get_error_name(tmp1,error);
+        fprintf(stderr, "Error: %s\n", tmp1);
+      }
+  }
+
+int rsbac_get_uid_name(rsbac_uid_t * uid, char * name, char * sourcename)
+  {
+    struct passwd * user_info_p;
+    rsbac_uid_t uid_i;
+
+    if(!(user_info_p = getpwnam(sourcename)))
+      {
+        uid_i = strtoul(sourcename,0,10);
+        if(   !uid_i
+           && strcmp("0", sourcename)
+          )
+          {
+            return -RSBAC_EINVALIDVALUE;
+          }
+        if(name)
+          {
+            if((user_info_p = getpwuid(uid_i)))
+              strcpy(name, user_info_p->pw_name);
+            else
+              sprintf(name, "%u", uid_i);
+          }
+      }
+    else
+      {
+        uid_i = user_info_p->pw_uid;
+        if(name)
+          strcpy(name, user_info_p->pw_name);
+      }
+    if(uid)
+      *uid = uid_i;
+    return 0;
+  }
+
+int rsbac_get_fullname(char * fullname, rsbac_uid_t uid)
+  {
+    struct passwd * user_info_p;
+    rsbac_uid_t uid_i;
+
+    if(!fullname)
+      return -RSBAC_EINVALIDPOINTER;
+    if(!(user_info_p = getpwuid(uid)))
+      {
+        sprintf(fullname, "%u", uid);
+      }
+    else
+      {
+        strcpy(fullname, user_info_p->pw_gecos);
+      }
+    return 0;
+  }
+
+char * get_user_name(rsbac_uid_t user, char * name)
+  {
+    struct passwd * user_info_p;
+
+    if((user_info_p = getpwuid(user)))
+      {
+        strcpy(name, user_info_p->pw_name);
+      }
+    else
+      {
+        sprintf(name, "%u", user);
+      }
+    return name;
+  }
+
+char * get_group_name(rsbac_gid_t group, char * name)
+  {
+    struct group * group_info_p;
+
+    if((group_info_p = getgrgid(group)))
+      {
+        strcpy(name, group_info_p->gr_name);
+      }
+    else
+      {
+        sprintf(name, "%u", group);
+      }
+    return name;
+  }
+
+int rsbac_get_gid_name(rsbac_gid_t * gid, char * name, char * sourcename)
+  {
+    struct group * group_info_p;
+    rsbac_gid_t gid_i;
+
+    if(!(group_info_p = getgrnam(sourcename)))
+      {
+        gid_i = strtoul(sourcename,0,10);
+        if(   !gid_i
+           && strcmp("0", sourcename)
+          )
+          {
+            return -RSBAC_EINVALIDVALUE;
+          }
+        if(name)
+          {
+            if((group_info_p = getgrgid(gid_i)))
+              strcpy(name, group_info_p->gr_name);
+            else
+              sprintf(name, "%u", gid_i);
+          }
+      }
+    else
+      {
+        gid_i = group_info_p->gr_gid;
+        if(name)
+          strcpy(name, group_info_p->gr_name);
+      }
+    if(gid)
+      *gid = gid_i;
+    return 0;
+  }
+
+
+char * u64tostrlog(char * str, __u64 i)
+  {
+    int    j = 0;
+    __u64  k;
+
+    if(!str)
+      return(NULL);
+
+    k = 1;
+    for(j = R_NONE - 1;j >= 0;j--)
+      {
+        if (i & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[R_NONE] = 0;
+    return (str);
+  };
+
+__u64 strtou64log(char * str, __u64 * i_p)
+  {
+    int    j;
+    __u64  k = 1, res=0;
+    
+    if(!str)
+      return(0);
+
+    if (strlen(str) < R_NONE)
+      return(-1);
+    for(j=R_NONE-1;j>=0;j--)
+      {
+        if(str[j] != '0')
+          {
+            res |= k;
+          }
+        k <<= 1;
+      }
+    for(j=R_NONE;j<64;j++)
+      {
+        res |= k;
+        k <<= 1;
+      }
+    *i_p = res;
+    return(res);
+  };
+
+char * u64tostrrc(char * str, __u64 i)
+  {
+    int    j = 0;
+    __u64  k;
+
+    if(!str)
+      return(NULL);
+
+    k = 1;
+    for(j = 63;j >= 0;j--)
+      {
+        if (i & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[64] = 0;
+    return (str);
+  };
+
+__u64 strtou64rc(char * str, __u64 * i_p)
+  {
+    int    j;
+    __u64  k = 1, res=0;
+    
+    if(!str)
+      return(0);
+
+    if (strlen(str) < 64)
+      return(-1);
+    for(j=63;j>=0;j--)
+      {
+        if(str[j] != '0')
+          {
+            res |= k;
+          }
+        k <<= 1;
+      }
+    *i_p = res;
+    return(res);
+  };
+
+char * u64tostrrcr(char * str, __u64 i)
+  {
+    int    j = 0;
+    __u64  k;
+
+    if(!str)
+      return(NULL);
+
+    k = 1;
+    for(j = RCR_NONE - 1;j >= 0;j--)
+      {
+        if (i & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[RCR_NONE] = 0;
+    return (str);
+  };
+
+__u64 strtou64rcr(char * str, __u64 * i_p)
+  {
+    int    j;
+    __u64  k = 1, res=0;
+    
+    if(!str)
+      return(0);
+
+    if (strlen(str) < RCR_NONE)
+      return(-1);
+    for(j=RCR_NONE-1;j>=0;j--)
+      {
+        if(str[j] != '0')
+          {
+            res |= k;
+          }
+        k <<= 1;
+      }
+    for(j=RCR_NONE;j<64;j++)
+      {
+        res |= k;
+        k <<= 1;
+      }
+    *i_p = res;
+    return(res);
+  };
+
+__u64 strtou64mac(char * str, __u64 * i_p)
+  {
+    int    j;
+    __u64  k = 1, res=0;
+    
+    if(!str)
+      return(0);
+
+    if (strlen(str) < RSBAC_MAC_NR_CATS)
+      return(-1);
+    for(j=RSBAC_MAC_MAX_CAT;j>=0;j--)
+      {
+        if(str[j] != '0')
+          {
+            res |= k;
+          }
+        k <<= 1;
+      }
+    for(j=RSBAC_MAC_NR_CATS;j<64;j++)
+      {
+        res |= k;
+        k <<= 1;
+      }
+    *i_p = res;
+    return(res);
+  };
+
+__u64 strtou64acl(char * str, __u64 * i_p)
+  {
+    int    j;
+    __u64  k = 1, res=0;
+    
+    if(!str)
+      return(0);
+
+    if (strlen(str) < (ACLR_NONE - 1))
+      return(-1);
+    for(j=ACLR_NONE-1;j>=0;j--)
+      {
+        if(str[j] != '0')
+          {
+            res |= k;
+          }
+        k <<= 1;
+      }
+    for(j=ACLR_NONE-1;j<64;j++)
+      {
+        res |= k;
+        k <<= 1;
+      }
+    *i_p = res;
+    return(res);
+  }
+
+int strtodevdesc(char * str, struct rsbac_dev_desc_t * dev_p)
+  {
+    char * p;
+    char * c;
+
+    if(!str)
+      return -RSBAC_EINVALIDVALUE;
+    if(!strcmp(str, ":DEFAULT:"))
+      {
+        *dev_p = RSBAC_ZERO_DEV_DESC;
+        return 0;
+      }
+    p = str;
+    c = strchr(p,':');
+    switch(*p)
+      {
+        case 'b':
+        case 'B':
+          if(c)
+            dev_p->type = D_block;
+          else
+            dev_p->type = D_block_major;
+          break;
+        case 'c':
+        case 'C':
+          if(c)
+            dev_p->type = D_char;
+          else
+            dev_p->type = D_char_major;
+          break;
+        default:
+          return -RSBAC_EINVALIDTARGET;
+      }
+    p++;
+    dev_p->major = strtoul(p,0,0);
+    if(c)
+      {
+        c++;
+        dev_p->minor = strtoul(c,0,0);
+      }
+    else
+      dev_p->minor = 0;
+    return 0;
+  }
+
+char * devdesctostr(char * str, struct rsbac_dev_desc_t dev)
+  {
+    if(RSBAC_IS_ZERO_DEV_DESC(dev))
+      {
+        sprintf(str, ":DEFAULT:");
+        return str;
+      }
+    switch(dev.type)
+      {
+        case D_block:
+        case D_char:
+          sprintf(str, "%c%u:%u", 'b' + dev.type, dev.major, dev.minor);
+          break;
+        case D_block_major:
+        case D_char_major:
+          sprintf(str, "%c%u",
+                  'b' + dev.type - (D_block_major - D_block),
+                  dev.major);
+          break;
+        default:
+          sprintf(str, "invalid!");
+      }
+    return str;
+  }
+#endif /* ifndef __KERNEL__ */
+
+char * u64tostracl(char * str, __u64 i)
+  {
+    int    j = 0;
+    __u64  k;
+
+    if(!str)
+      return(NULL);
+
+    k = 1;
+    for(j = ACLR_NONE - 1;j >= 0;j--)
+      {
+        if (i & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[ACLR_NONE] = 0;
+    return (str);
+  };
+
+char * u32tostrcap(char * str, __u32 i)
+  {
+    int    j = 0;
+    __u32  k;
+
+    if(!str)
+      return(NULL);
+
+    k = 1;
+    for(j = CAP_NONE - 1;j >= 0;j--)
+      {
+        if (i & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[CAP_NONE] = 0;
+    return (str);
+  };
+int kcaptostrcap(char * str, rsbac_cap_vector_t i)
+  {
+    int    j = 0;
+    int off;
+    __u32  k;
+
+    if(!str)
+      return(-1);
+
+    k = 1;
+    for(j = CAP_NONE - 1;j >= 32;j--)
+      {
+        if (i.cap[1] & k)
+          str[j-32] = '1';
+        else
+          str[j-32] = '0';
+        k<<=1;
+      };
+    k = 1;
+    off = CAP_NONE-32;
+    for(j = 31+off;j >= off;j--)
+      {
+        if (i.cap[0] & k)
+          str[j] = '1';
+        else
+          str[j] = '0';
+        k<<=1;
+      };
+
+    str[CAP_NONE] = 0;
+
+    return 0;
+  };
+
+int strcaptokcap(char * str, rsbac_cap_vector_t * i)
+  {
+    int    j;
+    int    off;
+    __u32  k = 1;
+    
+    if(!str)
+      return -1;
+    if (strlen(str) < CAP_NONE)
+      return -1;
+
+    for(j = CAP_NONE-1; j >= 32; j--)
+      {
+        if(str[j-32] != '0')
+          {
+            i->cap[1] |= k;
+          }
+        k <<= 1;
+      }
+    k = 1;
+    off = CAP_NONE-32;
+	for(j =31+off ;j >= off; j--) {
+		if(str[j] != '0') {
+			i->cap[0] |= k;
+		}
+		k <<= 1;
+	}
+/*    for(j=CAP_NONE;j<32;j++)
+      {
+        res |= k;
+        k <<= 1;
+      }*/
+/*    *i_p = res;*/
+
+    return 0;
+  }
+__u32 strtou32cap(char * str, __u32 * i_p)
+  {
+    int    j;
+    __u32  k = 1, res=0;
+    
+    if(!str)
+      return(0);
+
+    if (strlen(str) < CAP_NONE)
+      return(-1);
+    for(j=CAP_NONE-1;j>=0;j--)
+      {
+        if(str[j] != '0')
+          {
+            res |= k;
+          }
+        k <<= 1;
+      }
+    for(j=CAP_NONE;j<32;j++)
+      {
+        res |= k;
+        k <<= 1;
+      }
+    *i_p = res;
+    return(res);
+  };
+
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+rsbac_um_set_t rsbac_get_vset(void)
+  {
+    union rsbac_target_id_t        i_tid;
+    union rsbac_attribute_value_t  i_attr_val;
+
+    i_tid.process = task_pid(current);
+    if(rsbac_get_attr(SW_GEN,
+                        T_PROCESS,
+                        i_tid,
+                        A_vset,
+                        &i_attr_val,
+                        TRUE))
+	return 0;
+    else
+    	return i_attr_val.vset;
+  }
+#endif
+
+/* find the current owner of this process */
+int rsbac_get_owner(rsbac_uid_t * user_p)
+  {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    *user_p = RSBAC_GEN_UID(rsbac_get_vset(), __kuid_val(current_uid()));
+#else
+    *user_p = __kuid_val(current_uid());
+#endif
+    return 0;
+  }
+
+void rsbac_ds_get_error(const char * function, enum rsbac_attribute_t attr)
+  {
+    if(!function)
+      return;
+    if(attr != A_none)
+      {
+        char tmp[80];
+
+        get_attribute_name(tmp, attr);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_get_attr() for %s returned error!\n",
+                     function, tmp);
+      }
+    else
+      {
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_get_attr() returned error!\n",
+                     function);
+      }
+  }
+
+void rsbac_ds_get_error_num(const char * function, enum rsbac_attribute_t attr, int err)
+  {
+    char tmp2[80];
+
+    if(!function)
+      return;
+    if(attr != A_none)
+      {
+        char tmp[80];
+
+        get_attribute_name(tmp, attr);
+        get_error_name(tmp2, err);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_get_attr() for %s returned error %s!\n",
+                     function, tmp, tmp2);
+      }
+    else
+      {
+        get_error_name(tmp2, err);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_get_attr() returned error %s!\n",
+                     function, tmp2);
+      }
+  }
+
+void rsbac_ds_set_error(const char * function, enum rsbac_attribute_t attr)
+  {
+    if(!function)
+      return;
+    if(attr != A_none)
+      {
+        char tmp[80];
+
+        get_attribute_name(tmp, attr);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_set_attr() for %s returned error!\n",
+                     function, tmp);
+      }
+    else
+      {
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_set_attr() returned error!\n",
+                     function);
+      }
+  }
+
+void rsbac_ds_set_error_num(const char * function, enum rsbac_attribute_t attr, int err)
+  {
+    char tmp2[80];
+
+    if(!function)
+      return;
+    if(attr != A_none)
+      {
+        char tmp[80];
+
+        get_attribute_name(tmp, attr);
+        get_error_name(tmp2, err);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_set_attr() for %s returned error %s!\n",
+                     function, tmp, tmp2);
+      }
+    else
+      {
+        get_error_name(tmp2, err);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_set_attr() returned error %s!\n",
+                     function, tmp2);
+      }
+  }
+
+#ifdef CONFIG_RSBAC_RC
+void rsbac_rc_ds_get_error(const char * function, enum rsbac_rc_item_t item)
+  {
+    if(!function)
+      return;
+    if(item != RI_none)
+      {
+        char tmp[80];
+
+        get_rc_item_name(tmp, item);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_rc_get_item() for %s returned error!\n",
+                     function, tmp);
+      }
+    else
+      {
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_rc_get_item() returned error!\n",
+                     function);
+      }
+  }
+
+void rsbac_rc_ds_set_error(const char * function, enum rsbac_rc_item_t item)
+  {
+    if(!function)
+      return;
+    if(item != RI_none)
+      {
+        char tmp[80];
+
+        get_rc_item_name(tmp, item);
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_rc_set_item() for %s returned error!\n",
+                     function, tmp);
+      }
+    else
+      {
+        rsbac_printk(KERN_WARNING
+                     "%s: rsbac_rc_set_item() returned error!\n",
+                     function);
+      }
+  }
+#endif
+
+int rsbac_handle_filldir(const struct file *file, const char *name, const unsigned int namlen, const ino_t ino)
+{
+	enum   rsbac_target_t	       rsbac_target = T_NONE;
+        union  rsbac_target_id_t       rsbac_target_id;
+        union  rsbac_attribute_value_t rsbac_attribute_value;
+	struct dentry *obj_dentry = NULL;
+	int err = 1;
+
+	if(!rsbac_initialized) {
+		goto old_func;
+	}
+
+	if(!name || !file || !file->f_path.dentry || !file->f_path.dentry->d_sb
+		 || !MAJOR(file->f_path.dentry->d_sb->s_dev))
+		goto old_func;
+
+        if (in_interrupt())
+          {
+            printk(KERN_WARNING "rsbac_handle_filldir(): called from interrupt: pid %u(%s)!\n",
+                         current->pid, current->comm);
+            goto old_func;
+          }
+
+	obj_dentry = rsbac_lookup_one_len(name, file->f_path.dentry, namlen);
+	if (!obj_dentry || IS_ERR(obj_dentry)) {
+		goto old_func;
+	}
+	if (!obj_dentry->d_inode || IS_ERR(obj_dentry->d_inode)) {
+		goto out_dput;
+	}
+	if (!obj_dentry->d_inode->i_mode || !obj_dentry->d_inode->i_sb || !obj_dentry->d_inode->i_sb->s_dev || !ino) {
+		goto out_dput;
+	}
+	if (!obj_dentry->d_sb || !obj_dentry->d_sb->s_magic) {
+		goto out_dput;
+	}
+	rsbac_pr_debug(aef, "[readdir(), sys_getdents()]: calling ADF\n");
+
+	if (S_ISFIFO(obj_dentry->d_inode->i_mode)) {
+		if(obj_dentry->d_sb->s_magic != PIPEFS_MAGIC) {
+			rsbac_target = T_FIFO;
+			rsbac_target_id.fifo.device = obj_dentry->d_inode->i_sb->s_dev;
+			rsbac_target_id.fifo.inode  = ino;
+			rsbac_target_id.fifo.dentry_p = obj_dentry;
+		}
+	} else
+	if (S_ISDIR(obj_dentry->d_inode->i_mode)) {
+		rsbac_target = T_DIR;
+		rsbac_target_id.dir.device = obj_dentry->d_inode->i_sb->s_dev;
+		rsbac_target_id.dir.inode = ino;
+		rsbac_target_id.dir.dentry_p = obj_dentry;
+	} else
+	if (S_ISLNK(obj_dentry->d_inode->i_mode)) {
+		rsbac_target = T_SYMLINK;
+		rsbac_target_id.file.device = obj_dentry->d_inode->i_sb->s_dev;
+		rsbac_target_id.file.inode = ino;
+		rsbac_target_id.file.dentry_p = obj_dentry;
+	} else
+	if (S_ISSOCK(obj_dentry->d_inode->i_mode)) {
+		if (obj_dentry->d_inode->i_sb->s_magic != SOCKFS_MAGIC) {
+			rsbac_target = T_UNIXSOCK;
+			rsbac_target_id.unixsock.device = obj_dentry->d_inode->i_sb->s_dev;
+			rsbac_target_id.unixsock.inode = ino;
+			rsbac_target_id.unixsock.dentry_p = obj_dentry;
+		}
+	} else {
+		rsbac_target = T_FILE;
+		rsbac_target_id.file.device = obj_dentry->d_inode->i_sb->s_dev;
+		rsbac_target_id.file.inode = ino;
+		rsbac_target_id.file.dentry_p = obj_dentry;
+	}
+	rsbac_attribute_value.dummy = 0;
+	if (rsbac_target != T_NONE)
+		if (!rsbac_adf_request(R_SEARCH,
+					task_pid(current),
+					rsbac_target,
+					rsbac_target_id,
+					A_none,
+					rsbac_attribute_value))
+		{
+			err = 0;
+			goto out_dput;
+		}
+
+out_dput:
+	if (obj_dentry)
+		dput(obj_dentry);
+old_func:
+	return err;
+}
+int rsbac_handle_rw_req(const struct file *file, struct rsbac_rw_req *rsbac_rw_req_obj)
+{
+	int err = 1;
+
+	if(!rsbac_initialized) {
+		goto out;
+	}
+
+/*	if (rsbac_rw_req_obj->rsbac_target != T_NONE){printk("i'm here! going out because of target ! =T_NONE\n");
+                goto out;}
+*/
+	if(!file || !file->f_path.dentry || !file->f_path.dentry->d_sb
+		 || !MAJOR(file->f_path.dentry->d_sb->s_dev)
+		 || !file->f_path.dentry->d_sb->s_magic
+		 || !file->f_path.dentry->d_inode
+		 || IS_ERR(file->f_path.dentry->d_inode)
+		 || !file->f_path.dentry->d_inode->i_mode
+		 || !file->f_path.dentry->d_inode->i_ino)
+		goto out;
+
+        if (in_interrupt())
+          {
+            printk(KERN_WARNING "rsbac_handle_rw_req(): called from interrupt: pid %u(%s)!\n",
+                         current->pid, current->comm);
+            goto out;
+          }
+
+	rsbac_pr_debug(aef, "rsbac_handle_rw_req(): calling ADF\n");
+
+	rsbac_rw_req_obj->rsbac_attribute = A_none;
+        rsbac_rw_req_obj->rsbac_attribute_value.dummy = 0;
+
+	if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode)) {
+		if(file->f_path.dentry->d_sb->s_magic != PIPEFS_MAGIC) {
+			rsbac_rw_req_obj->rsbac_target = T_FIFO;
+			rsbac_rw_req_obj->rsbac_target_id.fifo.device = file->f_path.dentry->d_inode->i_sb->s_dev;
+			rsbac_rw_req_obj->rsbac_target_id.fifo.inode  = file->f_path.dentry->d_inode->i_ino;
+			rsbac_rw_req_obj->rsbac_target_id.fifo.dentry_p = file->f_path.dentry;
+		}
+	} else
+	if (S_ISREG(file->f_path.dentry->d_inode->i_mode)) {
+		rsbac_rw_req_obj->rsbac_target = T_FILE;
+		rsbac_rw_req_obj->rsbac_target_id.file.device = file->f_path.dentry->d_inode->i_sb->s_dev;
+		rsbac_rw_req_obj->rsbac_target_id.file.inode  = file->f_path.dentry->d_inode->i_ino;
+		rsbac_rw_req_obj->rsbac_target_id.file.dentry_p = file->f_path.dentry;
+	} else
+	if (S_ISSOCK(file->f_path.dentry->d_inode->i_mode)) {
+		struct socket * sock = SOCKET_I(file->f_path.dentry->d_inode);
+		if (sock->ops && (sock->ops->family == AF_UNIX)) {
+			if (sock->sk) {
+				if (unix_sk(unix_sk(sock->sk)->peer)) {
+					if (unix_sk(unix_sk(sock->sk)->peer)->path.dentry && unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode) {
+						rsbac_rw_req_obj->rsbac_target = T_UNIXSOCK;
+						rsbac_rw_req_obj->rsbac_target_id.unixsock.device = unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_sb->s_dev;
+						rsbac_rw_req_obj->rsbac_target_id.unixsock.inode  = unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode->i_ino;
+						rsbac_rw_req_obj->rsbac_target_id.unixsock.dentry_p = unix_sk(unix_sk(sock->sk)->peer)->path.dentry;
+					} else {
+						rsbac_rw_req_obj->rsbac_target = T_IPC;
+						rsbac_rw_req_obj->rsbac_target_id.ipc.type = I_anonunix;
+						if (unix_sk(unix_sk(sock->sk)->peer)->path.dentry
+								&& unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode
+								&& SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file
+                                                        	&& SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file->f_path.dentry
+                                                        	&& SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file->f_path.dentry->d_inode)
+							rsbac_rw_req_obj->rsbac_target_id.ipc.id.id_nr = SOCKET_I(unix_sk(unix_sk(sock->sk)->peer)->path.dentry->d_inode)->file->f_path.dentry->d_inode->i_ino;
+						else
+							if (sock->file && sock->file->f_path.dentry && sock->file->f_path.dentry->d_inode)
+								rsbac_rw_req_obj->rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+						else
+							rsbac_rw_req_obj->rsbac_target_id.ipc.id.id_nr = 0;
+					}
+				} else {
+					if (unix_sk(sock->sk)->path.dentry && unix_sk(sock->sk)->path.dentry->d_inode) {
+						rsbac_rw_req_obj->rsbac_target = T_UNIXSOCK;
+						rsbac_rw_req_obj->rsbac_target_id.unixsock.device = unix_sk(sock->sk)->path.dentry->d_sb->s_dev;
+						rsbac_rw_req_obj->rsbac_target_id.unixsock.inode  = unix_sk(sock->sk)->path.dentry->d_inode->i_ino;
+						rsbac_rw_req_obj->rsbac_target_id.unixsock.dentry_p = unix_sk(sock->sk)->path.dentry;
+					} else {
+						rsbac_rw_req_obj->rsbac_target = T_IPC;
+						rsbac_rw_req_obj->rsbac_target_id.ipc.type = I_anonunix;
+						if (sock->file && sock->file->f_path.dentry && sock->file->f_path.dentry->d_inode)
+							rsbac_rw_req_obj->rsbac_target_id.ipc.id.id_nr = sock->file->f_path.dentry->d_inode->i_ino;
+						else
+							rsbac_rw_req_obj->rsbac_target_id.ipc.id.id_nr = 0;
+					}
+				}
+				if (sock->sk->sk_peer_pid) {
+					rsbac_rw_req_obj->rsbac_attribute = A_process;
+					rsbac_rw_req_obj->rsbac_attribute_value.process = sock->sk->sk_peer_pid;
+				}
+				else if (unix_sk(sock->sk)->peer && unix_sk(sock->sk)->peer->sk_peer_pid) {
+					rsbac_rw_req_obj->rsbac_attribute = A_process;
+					rsbac_rw_req_obj->rsbac_attribute_value.process = unix_sk(sock->sk)->peer->sk_peer_pid;
+				} else {
+					rsbac_rw_req_obj->rsbac_attribute = A_sock_type;
+					rsbac_rw_req_obj->rsbac_attribute_value.sock_type = sock->type;
+				}
+			}
+		}
+	} else
+	if (S_ISBLK(file->f_path.dentry->d_inode->i_mode)) {
+		rsbac_rw_req_obj->rsbac_target = T_DEV;
+		rsbac_rw_req_obj->rsbac_target_id.dev.type = D_block;
+		rsbac_rw_req_obj->rsbac_target_id.dev.major = RSBAC_MAJOR(file->f_path.dentry->d_inode->i_rdev);
+		rsbac_rw_req_obj->rsbac_target_id.dev.minor = RSBAC_MINOR(file->f_path.dentry->d_inode->i_rdev);
+	} else
+	if (S_ISCHR(file->f_path.dentry->d_inode->i_mode)) {
+		rsbac_rw_req_obj->rsbac_target = T_DEV;
+		rsbac_rw_req_obj->rsbac_target_id.dev.type = D_char;
+                rsbac_rw_req_obj->rsbac_target_id.dev.major = RSBAC_MAJOR(file->f_path.dentry->d_inode->i_rdev);
+                rsbac_rw_req_obj->rsbac_target_id.dev.minor = RSBAC_MINOR(file->f_path.dentry->d_inode->i_rdev);
+	}
+/*
+	printk("i_mode %i\n", file->f_path.dentry->d_inode->i_mode);
+	printk("req %i %i\n", rsbac_rw_req_obj->rsbac_request, rsbac_rw_req_obj->rsbac_target);
+	if (S_ISCHR(file->f_path.dentry->d_inode->i_mode))
+		printk("CHR");
+	if (S_ISBLK(file->f_path.dentry->d_inode->i_mode))
+		printk("BLK");
+	if (S_ISSOCK(file->f_path.dentry->d_inode->i_mode))
+		printk("SOCK");
+	if (S_ISREG(file->f_path.dentry->d_inode->i_mode))
+		printk("REG");
+	if (S_ISFIFO(file->f_path.dentry->d_inode->i_mode))
+		printk("FIFO");
+*/
+	if (rsbac_rw_req_obj->rsbac_target != T_NONE)
+		if (!rsbac_adf_request(rsbac_rw_req_obj->rsbac_request,
+					task_pid(current),
+					rsbac_rw_req_obj->rsbac_target,
+					rsbac_rw_req_obj->rsbac_target_id,
+					A_none,
+					rsbac_rw_req_obj->rsbac_attribute_value))
+		{
+			err = 0;
+			goto out;
+		}
+
+out:
+	return err;
+}
+
+int rsbac_handle_rw_up(struct rsbac_rw_req *rsbac_rw_req_obj)
+{
+	int err = 0;
+
+	if (rsbac_rw_req_obj->rsbac_target != T_NONE) {
+		rsbac_rw_req_obj->rsbac_new_target_id.dummy = 0;
+		err = rsbac_adf_set_attr(rsbac_rw_req_obj->rsbac_request,
+					task_pid(current),
+					rsbac_rw_req_obj->rsbac_target,
+					rsbac_rw_req_obj->rsbac_target_id,
+					T_NONE,
+					rsbac_rw_req_obj->rsbac_new_target_id,
+					rsbac_rw_req_obj->rsbac_attribute,
+					rsbac_rw_req_obj->rsbac_attribute_value);
+		if (err)
+			rsbac_printk(KERN_WARNING "rsbac_handle_rw_up(): rsbac_adf_set_attr() returned error\n");
+	}
+
+	return err;
+}
+#endif
+/* __KERNEL__ */
diff --git a/rsbac/help/jail_getname.c b/rsbac/help/jail_getname.c
new file mode 100644
index 0000000..66f9de7
--- /dev/null
+++ b/rsbac/help/jail_getname.c
@@ -0,0 +1,61 @@
+/*********************************** */
+/* Rule Set Based Access Control     */
+/* Author and (c) 1999-2014:         */
+/*   Amon Ott <ao@rsbac.org>         */
+/* Getname functions for JAIL module */
+/* Last modified: 04/Feb/2014        */
+/*********************************** */
+
+#include <rsbac/getname.h>
+#include <rsbac/jail_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#include <linux/sched.h>
+#include <rsbac/debug.h>
+#include <rsbac/aci.h>
+#include <rsbac/rkmem.h>
+#else
+#include <string.h>
+#endif
+
+#ifdef __KERNEL__
+#ifdef CONFIG_RSBAC_JAIL_LOG_MISSING
+void rsbac_jail_log_missing_cap(int cap)
+  {
+    char * tmp;
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    i_tid.process = task_pid(current);
+    if (rsbac_get_attr(SW_JAIL,
+                       T_PROCESS,
+                       i_tid,
+                       A_jail_max_caps,
+                       &i_attr_val1,
+                       FALSE))
+      {
+        rsbac_ds_get_error("rsbac_jail_log_missing_cap()", A_jail_max_caps);
+      }
+    else
+      {
+        if(!((i_attr_val1.jail_max_caps.cap[0] & (1 << cap)) || (i_attr_val1.jail_max_caps.cap[1] & (1 << cap))))
+          {
+            tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
+            if(tmp)
+              {
+                get_cap_name(tmp, cap);
+                rsbac_printk(KERN_DEBUG
+                             "capable(): pid %u(%s), uid %u: missing jail_max_cap %s!\n",
+                             current->pid, current->comm,
+                             __kuid_val(current_uid()),
+                             tmp);
+                  rsbac_kfree(tmp);
+              }
+          }
+      }
+  }
+#endif
+#endif
diff --git a/rsbac/help/net_getname.c b/rsbac/help/net_getname.c
new file mode 100644
index 0000000..4559e36
--- /dev/null
+++ b/rsbac/help/net_getname.c
@@ -0,0 +1,352 @@
+/*
+ * net_getname.c: Getname functions for the Network
+ *
+ * Author and Copyright (C) 1999-2009 Amon Ott <ao@rsbac.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation, version 2.
+ *
+ * Last modified 03/Feb/2009.
+ */
+
+#include <rsbac/types.h>
+#include <rsbac/getname.h>
+#include <rsbac/net_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#include <linux/module.h>
+#else
+#include <linux/socket.h>
+#include <string.h>
+#include <stdio.h>
+#endif
+
+static char net_temp_syscall_list[NTS_none + 1][19] = {
+	"new_template",
+	"copy_template",
+	"delete_template",
+	"check_id",
+	"get_address",
+	"get_address_family",
+	"get_type",
+	"get_protocol",
+	"get_netdev",
+	"get_ports",
+	"get_name",
+	"set_address",
+	"set_address_family",
+	"set_type",
+	"set_protocol",
+	"set_netdev",
+	"set_ports",
+	"set_name",
+	"none"
+};
+
+static char net_family_list[AF_MAX + 1][19] = {
+	"ANY",			/* 0 */
+	"UNIX",			/* 1 Unix domain sockets */
+	"INET",			/* 2 Internet IP Protocol */
+	"AX25",			/* 3 Amateur Radio AX.25 */
+	"IPX",			/* 4 Novell IPX */
+	"APPLETALK",		/* 5 AppleTalk DDP */
+	"NETROM",		/* 6 Amateur Radio NET/ROM */
+	"BRIDGE",		/* 7 Multiprotocol bridge */
+	"ATMPVC",		/* 8 ATM PVCs */
+	"X25",			/* 9 Reserved for X.25 project */
+	"INET6",		/* 10 IP version 6 */
+	"ROSE",			/* 11 Amateur Radio X.25 PLP */
+	"DECnet",		/* 12 Reserved for DECnet project */
+	"NETBEUI",		/* 13 Reserved for 802.2LLC project */
+	"SECURITY",		/* 14 Security callback pseudo AF */
+	"KEY",			/* 15 PF_KEY key management API */
+	"NETLINK",		/* 16 */
+	"PACKET",		/* 17 Packet family */
+	"ASH",			/* 18 Ash */
+	"ECONET",		/* 19 Acorn Econet  */
+	"ATMSVC",		/* 20 ATM SVCs */
+	"(undefined)",		/* 21 */
+	"SNA",			/* 22 Linux SNA Project (nutters!) */
+	"IRDA",			/* 23 IRDA sockets */
+	"PPPOX",		/* 24 PPPoX sockets */
+	"WANPIPE",		/* 25 Wanpipe API Sockets */
+	"(undefined)",		/* 26 */
+	"(undefined)",		/* 27 */
+	"(undefined)",		/* 28 */
+	"(undefined)",		/* 29 */
+	"(undefined)",		/* 30 */
+	"BLUETOOTH",		/* 31 Bluetooth sockets */
+	"MAX"
+};
+
+#define NETLINK_FAM_MAX 19
+
+static char net_netlink_family_list[NETLINK_FAM_MAX + 1][15] = {
+	"ROUTE",		/* 0 Routing/device hook				*/
+	"UNUSED",		/* 1 Unused number				*/
+	"USERSOCK",		/* 2 Reserved for user mode socket protocols 	*/
+	"FIREWALL",		/* 3 Firewalling hook				*/
+	"INET_DIAG",		/* 4 INET socket monitoring			*/
+	"NFLOG",		/* 5 netfilter/iptables ULOG */
+	"XFRM",			/* 6 ipsec */
+	"SELINUX",		/* 7 SELinux event notifications */
+	"ISCSI",		/* 8 Open-iSCSI */
+	"AUDIT",		/* 9 auditing */
+	"FIB_LOOKUP",		
+	"CONNECTOR",	
+	"NETFILTER",		/* 12 netfilter subsystem */
+	"IP6_FW",		
+	"DNRTMSG",		/* 14 DECnet routing messages */
+	"KOBJECT_UEVENT",	/* 15 Kernel messages to userspace */
+	"GENERIC",		
+	"DM",			/* 17 (DM Events) */
+	"SCSITRANSPORT",	/* 18 SCSI Transports */
+	"ECRYPTFS"
+};
+
+struct proto_desc_t {
+	char name[19];
+	int nr;
+};
+#define NR_PROTO 18
+
+static struct proto_desc_t net_protocol_list[NR_PROTO] = {
+	{"ANY", 0},		/* 0 Dummy protocol for TCP */
+	{"ICMP", 1},		/* Internet Control Message Protocol */
+	{"IGMP", 2},		/* Internet Group Management Protocol   */
+	{"IPIP", 4},		/* IPIP tunnels (older KA9Q tunnels use 94) */
+	{"TCP", 6},		/* Transmission Control Protocol */
+	{"EGP", 8},		/* Exterior Gateway Protocol */
+	{"PUP", 12},		/* PUP protocol */
+	{"UDP", 17},		/* User Datagram Protocol */
+	{"IDP", 22},		/* XNS IDP protocol */
+	{"RSVP", 46},		/* RSVP protocol */
+	{"GRE", 47},		/* Cisco GRE tunnels (rfc 1701,1702) */
+	{"IPV6", 41},		/* IPv6-in-IPv4 tunnelling */
+	{"PIM", 103},		/* Protocol Independent Multicast */
+	{"ESP", 50},		/* Encapsulation Security Payload protocol */
+	{"AH", 51},		/* Authentication Header protocol */
+	{"COMP", 108},		/* Compression Header protocol */
+	{"RAW", 255},		/* Raw IP packets */
+	{"MAX", RSBAC_NET_PROTO_MAX}
+};
+
+static char rsbac_net_type_list[RSBAC_NET_TYPE_MAX + 1][19] = {
+	"ANY",
+	"STREAM",		/* 1 stream (connection) socket */
+	"DGRAM",		/* 2 datagram (conn.less) socket */
+	"RAW",			/* 3 raw socket */
+	"RDM",			/* 4 reliably-delivered message */
+	"SEQPACKET",		/* 5 sequential packet socket */
+	"(undefined)",		/* 6 */
+	"(undefined)",		/* 7 */
+	"(undefined)",		/* 8 */
+	"(undefined)",		/* 9 */
+	"PACKET",		/* 10 linux specific way of */
+	/* getting packets at the dev */
+	/* level.  For writing rarp and */
+	/* other similar things on the */
+	/* user level. */
+	"MAX"
+};
+
+/*****************************************/
+
+char *rsbac_get_net_temp_syscall_name(char *name,
+				      enum rsbac_net_temp_syscall_t value)
+{
+	if (!name)
+		return NULL;
+	if (value > NTS_none)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, net_temp_syscall_list[value]);
+	return name;
+};
+
+#ifndef __KERNEL__
+enum rsbac_net_temp_syscall_t rsbac_get_net_temp_syscall_nr(const char
+							    *name)
+{
+	enum rsbac_net_temp_syscall_t i;
+
+	if (!name)
+		return NTS_none;
+	for (i = 0; i < NTS_none; i++) {
+		if (!strcmp(name, net_temp_syscall_list[i])) {
+			return i;
+		}
+	}
+	return NTS_none;
+};
+#endif
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_get_net_family_name);
+#endif
+#endif
+char *rsbac_get_net_family_name(char *name, u_int value)
+{
+	if (!name)
+		return NULL;
+	if (value > AF_MAX)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, net_family_list[value]);
+	return name;
+};
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_get_net_netlink_family_name);
+#endif
+#endif
+char *rsbac_get_net_netlink_family_name(char *name, u_int value)
+{
+	if (!name)
+		return NULL;
+	if (value == RSBAC_NET_NETLINK_PROTO_ANY)
+		strcpy(name, "ANY");
+	if (value > NETLINK_FAM_MAX)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, net_netlink_family_list[value]);
+	return name;
+};
+
+#ifndef __KERNEL__
+int rsbac_get_net_family_nr(const char *name)
+{
+	int i;
+
+	if (!name)
+		return AF_MAX;
+	if (!strcmp(name, "ANY")
+		return RSBAC_NET_NETLINK_PROTO_ANY;
+	for (i = 0; i < AF_MAX; i++) {
+		if (!strcmp(name, net_family_list[i])) {
+			return i;
+		}
+	}
+	return AF_MAX;
+};
+#endif
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_get_net_protocol_name);
+#endif
+#endif
+char *rsbac_get_net_protocol_name(char *name, u_int value)
+{
+	int i;
+
+	if (!name)
+		return NULL;
+	if (value >= RSBAC_NET_PROTO_MAX)
+		strcpy(name, "ERROR!");
+	else {
+		for (i = 0; i < NR_PROTO; i++) {
+			if (net_protocol_list[i].nr == value) {
+				strcpy(name, net_protocol_list[i].name);
+				return name;
+			}
+		}
+		sprintf(name, "%u", value);
+	}
+	return name;
+};
+
+#ifndef __KERNEL__
+int rsbac_get_net_protocol_nr(const char *name)
+{
+	int i;
+
+	if (!name)
+		return RSBAC_NET_PROTO_MAX;
+	for (i = 0; i < NR_PROTO; i++) {
+		if (!strcmp(name, net_protocol_list[i].name)) {
+			return net_protocol_list[i].nr;
+		}
+	}
+	return RSBAC_NET_PROTO_MAX;
+};
+#endif
+
+#ifdef __KERNEL__
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_get_net_type_name);
+#endif
+#endif
+char *rsbac_get_net_type_name(char *name, u_int value)
+{
+	if (!name)
+		return NULL;
+	if (value > RSBAC_NET_TYPE_MAX)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, rsbac_net_type_list[value]);
+	return name;
+};
+
+#ifndef __KERNEL__
+int rsbac_get_net_type_nr(const char *name)
+{
+	int i;
+
+	if (!name)
+		return RSBAC_NET_TYPE_MAX;
+	for (i = 0; i < RSBAC_NET_TYPE_MAX; i++) {
+		if (!strcmp(name, rsbac_net_type_list[i])) {
+			return i;
+		}
+	}
+	return RSBAC_NET_TYPE_MAX;
+};
+#endif
+
+#ifdef __KERNEL__
+int rsbac_net_str_to_inet(char *str, __u32 * addr)
+{
+	char *end;
+	__u32 s0, s1, s2, s3;
+
+	if (!str || !addr)
+		return -RSBAC_EINVALIDPOINTER;
+	end = str;
+	while (*end) {
+		if ((*end != '.')
+		    && (*end != '\n')
+		    && (*end != ' ')
+		    && ((*end < '0')
+			|| (*end > '9')
+		    )
+		    )
+			return -RSBAC_EINVALIDVALUE;
+		end++;
+	}
+	s0 = simple_strtoul(str, &end, 10);
+	if (!*end || (s0 > 255))
+		return -RSBAC_EINVALIDVALUE;
+	end++;
+	s1 = simple_strtoul(end, &end, 10);
+	if (!*end || (s1 > 255))
+		return -RSBAC_EINVALIDVALUE;
+	end++;
+	s2 = simple_strtoul(end, &end, 10);
+	if (!*end || (s2 > 255))
+		return -RSBAC_EINVALIDVALUE;
+	end++;
+	s3 = simple_strtoul(end, &end, 10);
+	if (*end || (s3 > 255))
+		return -RSBAC_EINVALIDVALUE;
+	*addr = s3 | (s2 << 8) | (s1 << 16) | (s0 << 24);
+	*addr = htonl(*addr);
+	return 0;
+}
+#endif
diff --git a/rsbac/help/net_helpers.c b/rsbac/help/net_helpers.c
new file mode 100644
index 0000000..fbbb308
--- /dev/null
+++ b/rsbac/help/net_helpers.c
@@ -0,0 +1,117 @@
+/*
+ * net_helpers.c: Helper functions for the Network.
+ *
+ * Author and Copyright (C) 1999-2009 Amon Ott <ao@rsbac.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation, version 2.
+ *
+ * Last modified 03/Feb/2009.
+ */
+
+#include <rsbac/types.h>
+#ifdef __KERNEL__
+#include <rsbac/network.h>
+#endif
+
+static __u32 ipv4_mask[32] = {
+  0x00000000, 0x00000080, 0x000000C0, 0x000000E0,
+  0x000000F0, 0x000000F8, 0x000000FC, 0x000000FE,
+  0x000000FF, 0x000080FF, 0x0000C0FF, 0x0000E0FF,
+  0x0000F0FF, 0x0000F8FF, 0x0000FCFF, 0x0000FEFF,
+  0x0000FFFF, 0x0080FFFF, 0x00C0FFFF, 0x00E0FFFF,
+  0x00F0FFFF, 0x00F8FFFF, 0x00FCFFFF, 0x00FEFFFF,
+  0x00FFFFFF, 0x80FFFFFF, 0xC0FFFFFF, 0xE0FFFFFF,
+  0xF0FFFFFF, 0xF8FFFFFF, 0xFCFFFFFF, 0xFEFFFFFF
+};
+
+static inline __u32 rsbac_net_make_mask_u32(__u8 bits)
+{                               
+        if (bits >= 32)         
+                return (__u32)-1UL;
+        return ipv4_mask[bits];
+}
+
+#ifdef __KERNEL__
+/* The lookup data param is always second, so we use it as description here! */
+int rsbac_net_compare_data(void *data1, void *data2)
+{
+	struct rsbac_net_temp_data_t *temp = data1;
+	struct rsbac_net_description_t *desc = data2;
+
+	if (!temp || !desc)
+		return 1;
+	if ((temp->address_family != RSBAC_NET_ANY)
+	    && (temp->address_family != desc->address_family)
+	    )
+		return 1;
+	switch (desc->address_family) {
+	case AF_INET:
+		{
+			__u32 mask;
+			int i;
+
+			if(temp->address.inet.nr_addr == 0)
+				return 1;
+			if ((temp->type != RSBAC_NET_ANY)
+			    && (desc->type != temp->type)
+			    )
+				return 1;
+			if ((temp->protocol != RSBAC_NET_ANY)
+			    && (desc->protocol != temp->protocol)
+			    )
+				return 1;
+			if(temp->ports.nr_ports > 0) {
+				i=0;
+				while(i < temp->ports.nr_ports) {
+					if ((desc->port >= temp->ports.ports[i].min)
+					&& (desc->port <= temp->ports.ports[i].max))
+						break;
+					i++;
+				}
+				if(i == temp->ports.nr_ports)
+					return 1;
+			}
+			if (temp->netdev[0]
+			    && (!desc->netdev[0]
+				|| strncmp(desc->netdev, temp->netdev,
+					   RSBAC_IFNAMSIZ))
+			    )
+				return 1;
+			if (!desc->address)
+				return 1;
+			i=0;
+			while(i < temp->address.inet.nr_addr) {
+				mask = rsbac_net_make_mask_u32(temp->address.inet.valid_bits[i]);
+				if ((((*(__u32 *) desc->address) & mask) ==
+					(temp->address.inet.addr[i] & mask))
+				    )
+				    return 0;
+				i++;
+			}
+			return 1;
+		}
+
+	case AF_NETLINK:
+		if ((temp->type != RSBAC_NET_ANY)
+		    && (desc->type != temp->type)
+		    )
+			return 1;
+		if ((temp->protocol != RSBAC_NET_NETLINK_PROTO_ANY)
+		    && (desc->protocol != temp->protocol)
+		    )
+			return 1;
+		return 0;
+
+		/* Other address families: only socket type checks for now */
+	default:
+		if ((temp->type != RSBAC_NET_ANY)
+		    && (desc->type != temp->type)
+		    )
+			return 1;
+		return 0;
+	}
+	return 1;
+}
+#endif
diff --git a/rsbac/help/pax_getname.c b/rsbac/help/pax_getname.c
new file mode 100644
index 0000000..0822b6e
--- /dev/null
+++ b/rsbac/help/pax_getname.c
@@ -0,0 +1,95 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 1999-2004:        */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for PAX module */
+/* Last modified: 06/Jan/2004       */
+/********************************** */
+
+#include <rsbac/types.h>
+#include <rsbac/pax_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#else
+#include <stdio.h>
+#include <string.h>
+#endif
+
+char * pax_print_flags(char * string, rsbac_pax_flags_t flags)
+  {
+    sprintf(string, "%c%c%c%c%c%c",
+           flags & PF_PAX_PAGEEXEC ? 'P' : 'p',
+           flags & PF_PAX_EMUTRAMP ? 'E' : 'e',
+           flags & PF_PAX_MPROTECT ? 'M' : 'm',
+           flags & PF_PAX_RANDMMAP ? 'R' : 'r',
+           flags & PF_PAX_RANDEXEC ? 'X' : 'x',
+           flags & PF_PAX_SEGMEXEC ? 'S' : 's');
+    return string;
+  }
+
+#ifndef __KERNEL__
+rsbac_pax_flags_t pax_strtoflags(char * string, rsbac_pax_flags_t init_flags)
+  {
+    char * p = string;
+    rsbac_pax_flags_t add_flags = 0;
+    rsbac_pax_flags_t remove_flags = 0;
+
+    if(!p)
+      return init_flags;
+    while(*p)
+      {
+        switch(*p)
+          {
+              case 'P':
+                add_flags |= PF_PAX_PAGEEXEC;
+                break;
+              case 'p':
+                remove_flags |= PF_PAX_PAGEEXEC;
+                break;
+              case 'E':
+                add_flags |= PF_PAX_EMUTRAMP;
+                break;
+              case 'e':
+                remove_flags |= PF_PAX_EMUTRAMP;
+                break;
+              case 'M':
+                add_flags |= PF_PAX_MPROTECT;
+                break;
+              case 'm':
+                remove_flags |= PF_PAX_MPROTECT;
+                break;
+              case 'R':
+                add_flags |= PF_PAX_RANDMMAP;
+                break;
+              case 'r':
+                remove_flags |= PF_PAX_RANDMMAP;
+                break;
+              case 'X':
+                add_flags |= PF_PAX_RANDEXEC;
+                break;
+              case 'x':
+                remove_flags |= PF_PAX_RANDEXEC;
+                break;
+              case 'S':
+                add_flags |= PF_PAX_SEGMEXEC;
+                break;
+              case 's':
+                remove_flags |= PF_PAX_SEGMEXEC;
+                break;
+              case 'z':
+                remove_flags = RSBAC_PAX_ALL_FLAGS;
+                break;
+              case 'a':
+                add_flags = RSBAC_PAX_ALL_FLAGS;
+                break;
+            default:
+              break;
+          }
+        p++;
+      }
+    return (init_flags | add_flags) & ~remove_flags;
+  }
+#endif
diff --git a/rsbac/help/rc_getname.c b/rsbac/help/rc_getname.c
new file mode 100644
index 0000000..eae4d72
--- /dev/null
+++ b/rsbac/help/rc_getname.c
@@ -0,0 +1,307 @@
+/*
+ * rc_getname.c: Getname functions for the RC module.
+ *
+ * Author and Copyright (C) 1999-2013 Amon Ott <ao@rsbac.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation, version 2.
+ *
+ * Last modified 27/Nov/2013.
+ */
+
+#include <rsbac/getname.h>
+#include <rsbac/rc_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+static char rc_target_list[RT_NONE + 1][13] = {
+	"ROLE",
+	"TYPE",
+	"NONE"
+};
+
+static char rc_admin_list[RC_none + 1][13] = {
+	"no_admin",
+	"role_admin",
+	"system_admin",
+	"none"
+};
+
+static char rc_scd_type_list[RST_none - RST_min + 1][20] = {
+	"auth_administration",
+	"udf_administration",
+	"none"
+};
+
+static char rc_item_list[RI_none + 1][30] = {
+	"role_comp",
+	"admin_roles",
+	"assign_roles",
+	"type_comp_fd",
+	"type_comp_dev",
+	"type_comp_user",
+	"type_comp_process",
+	"type_comp_ipc",
+	"type_comp_scd",
+	"type_comp_group",
+	"type_comp_netdev",
+	"type_comp_nettemp",
+	"type_comp_netobj",
+	"admin_type",
+	"name",
+	"def_fd_create_type",
+	"def_fd_ind_create_type",
+	"def_user_create_type",
+	"def_process_create_type",
+	"def_process_chown_type",
+	"def_process_execute_type",
+	"def_ipc_create_type",
+	"def_group_create_type",
+	"def_unixsock_create_type",
+	"boot_role",
+	"req_reauth",
+	"type_fd_name",
+	"type_dev_name",
+	"type_ipc_name",
+	"type_user_name",
+	"type_process_name",
+	"type_group_name",
+	"type_netdev_name",
+	"type_nettemp_name",
+	"type_netobj_name",
+	"type_fd_need_secdel",
+	"type_scd_name",
+	"remove_role",
+	"def_fd_ind_create_type_remove",
+	"type_fd_remove",
+	"type_dev_remove",
+	"type_ipc_remove",
+	"type_user_remove",
+	"type_process_remove",
+	"type_group_remove",
+	"type_netdev_remove",
+	"type_nettemp_remove",
+	"type_netobj_remove",
+#ifdef __KERNEL__
+#endif
+	"none"
+};
+
+#ifndef __KERNEL__
+static char rc_item_param_list[RI_none + 1][100] = {
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"\t0 = FALSE, 1 = TRUE",
+	"0 = FALSE, 1 = TRUE",
+	"0 = FALSE, 1 = TRUE",
+	"0 = FALSE, 1 = TRUE",
+	"\t0 = no_admin, 1 = role_admin, 2 = system_admin\n\t\t\t(for RC administration only)",
+	"\t\tString, max. 15 chars",
+	"number, -2 = inherit from parent, -3 = no_create",
+	"parent_type new_type, -2 = inherit from parent,\n\t\t\t-3 = no_create",
+	"number, -2 = inherit from parent, -3 = no_create",
+	"number, -1 = inherit from process,\n\t\t\t-3 = no_create",
+	"number, -2 = inherit from parent (keep),\n\t\t\t-3 = no_create",
+	"number, -2 = inherit from parent (keep),\n\t\t\t-5 = use def_create of new role, -6 = no_chown",
+	"number, -1 = inherit from process (keep),\n\t\t\t-4 = no_execute",
+	"number, -3 = no_create",
+	"number, -7 = use_template (do not set)",
+	"\t0 = FALSE, 1 = TRUE",
+	"\tString, max. 15 chars",
+	"\tString, max. 15 chars",
+	"\tString, max. 15 chars",
+	"\tString, max. 15 chars",
+	"String, max. 15 chars",
+	"\tString, max. 15 chars",
+	"String, max. 15 chars",
+	"String, max. 15 chars",
+	"String, max. 15 chars",
+	"0 = FALSE, 1 = TRUE",
+	"\tString, max. 15 chars (read-only)",
+	"\t\t(none)"
+};
+#endif
+
+static char rc_special_right_list[RCR_NONE - RSBAC_RC_SPECIAL_RIGHT_BASE +
+				  1][20] = {
+	"ADMIN",
+	"ASSIGN",
+	"ACCESS_CONTROL",
+	"SUPERVISOR",
+	"MODIFY_AUTH",
+	"CHANGE_AUTHED_OWNER",
+	"SELECT",
+	"MODIFY_UDF",
+	"NONE"
+};
+
+/*****************************************/
+
+char *get_rc_target_name(char *name, enum rsbac_rc_target_t value)
+{
+	if (!name)
+		return (NULL);
+	if (value > RT_NONE)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, rc_target_list[value]);
+	return (name);
+};
+
+enum rsbac_rc_target_t get_rc_target_nr(const char *name)
+{
+	enum rsbac_rc_target_t i;
+
+	if (!name)
+		return (RT_NONE);
+	for (i = 0; i < RT_NONE; i++) {
+		if (!strcmp(name, rc_target_list[i])) {
+			return (i);
+		}
+	}
+	return (RT_NONE);
+};
+
+char *get_rc_admin_name(char *name, enum rsbac_rc_admin_type_t value)
+{
+	if (!name)
+		return (NULL);
+	if (value > RC_none)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, rc_admin_list[value]);
+	return (name);
+};
+
+enum rsbac_rc_admin_type_t get_rc_admin_nr(const char *name)
+{
+	enum rsbac_rc_admin_type_t i;
+
+	if (!name)
+		return (RC_none);
+	for (i = 0; i < RC_none; i++) {
+		if (!strcmp(name, rc_admin_list[i])) {
+			return (i);
+		}
+	}
+	return (RC_none);
+};
+
+char *get_rc_scd_type_name(char *name, enum rsbac_rc_scd_type_t value)
+{
+	if (!name)
+		return (NULL);
+	if (value < RST_min) {
+		return (get_scd_type_name(name, value));
+	}
+	value -= RST_min;
+	if (value > RST_none) {
+		strcpy(name, "ERROR!");
+		return (name);
+	}
+	strcpy(name, rc_scd_type_list[value]);
+	return (name);
+};
+
+enum rsbac_rc_scd_type_t get_rc_scd_type_nr(const char *name)
+{
+	enum rsbac_rc_scd_type_t i;
+
+	if (!name)
+		return (RC_none);
+	for (i = 0; i < RC_none - RST_min; i++) {
+		if (!strcmp(name, rc_scd_type_list[i])) {
+			return (i + RST_min);
+		}
+	}
+	return (get_scd_type_nr(name));
+};
+
+char *get_rc_item_name(char *name, enum rsbac_rc_item_t value)
+{
+	if (!name)
+		return (NULL);
+	if (value > RI_none)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, rc_item_list[value]);
+	return (name);
+};
+
+enum rsbac_rc_item_t get_rc_item_nr(const char *name)
+{
+	enum rsbac_rc_item_t i;
+
+	if (!name)
+		return (RI_none);
+	for (i = 0; i < RI_none; i++) {
+		if (!strcmp(name, rc_item_list[i])) {
+			return (i);
+		}
+	}
+	return (RI_none);
+};
+
+#ifndef __KERNEL__
+char *get_rc_item_param(char *name, enum rsbac_rc_item_t value)
+{
+	if (!name)
+		return (NULL);
+	if (value > RI_none)
+		strcpy(name, "ERROR!");
+	else
+		strcpy(name, rc_item_param_list[value]);
+	return (name);
+};
+#endif
+
+char *get_rc_special_right_name(char *name,
+				enum rsbac_rc_special_rights_t value)
+{
+	if (!name)
+		return (NULL);
+	if (value < RSBAC_RC_SPECIAL_RIGHT_BASE) {
+		return (get_request_name(name, value));
+	}
+	value -= RSBAC_RC_SPECIAL_RIGHT_BASE;
+	if (value > RCR_NONE) {
+		strcpy(name, "ERROR!");
+		return (name);
+	}
+	strcpy(name, rc_special_right_list[value]);
+	return (name);
+};
+
+#ifndef __KERNEL__
+enum rsbac_rc_special_rights_t get_rc_special_right_nr(const char *name)
+{
+	enum rsbac_rc_special_rights_t i;
+
+	if (!name)
+		return (RCR_NONE);
+	for (i = 0; i < (RCR_NONE - RSBAC_RC_SPECIAL_RIGHT_BASE); i++) {
+		if (!strcmp(name, rc_special_right_list[i])) {
+			return (i + RSBAC_RC_SPECIAL_RIGHT_BASE);
+		}
+	}
+	return (get_request_nr(name));
+}
+#endif
diff --git a/rsbac/help/res_getname.c b/rsbac/help/res_getname.c
new file mode 100644
index 0000000..0641eb7
--- /dev/null
+++ b/rsbac/help/res_getname.c
@@ -0,0 +1,62 @@
+/********************************** */
+/* Rule Set Based Access Control    */
+/* Author and (c) 2002:             */
+/*   Amon Ott <ao@rsbac.org>        */
+/* Getname functions for RES module */
+/* Last modified: 22/Nov/2002       */
+/********************************** */
+
+#ifndef __KERNEL__
+
+#include <rsbac/getname.h>
+#include <rsbac/res_getname.h>
+#include <rsbac/helpers.h>
+#include <rsbac/error.h>
+
+#include <string.h>
+
+static char  res_list[RSBAC_RES_MAX+2][8] = {
+   "cpu",
+   "fsize",
+   "data",
+   "stack",
+   "core",
+   "rss",
+   "nproc",
+   "nofile",
+   "memlock",
+   "as",
+   "locks",
+   "NONE" };
+
+/*****************************************/
+
+char * get_res_name(char * name,
+                    u_int value)
+  {
+    if(!name)
+      return(NULL);
+    if(value > RSBAC_RES_MAX)
+      strcpy(name, "ERROR!");
+    else
+      strcpy(name, res_list[value]);
+    return(name);
+  };
+
+int get_res_nr(const char * name)
+  {
+    int i;
+    
+    if(!name)
+      return(RSBAC_RES_NONE);
+    for (i = 0; i <= RSBAC_RES_MAX; i++)
+      {
+        if (!strcmp(name, res_list[i]))
+          {
+            return(i);
+          }
+      }
+    return(RSBAC_RES_NONE);
+  };
+
+#endif /* !__KERNEL__ */
diff --git a/rsbac/help/rkmem.c b/rsbac/help/rkmem.c
new file mode 100644
index 0000000..c19b45b
--- /dev/null
+++ b/rsbac/help/rkmem.c
@@ -0,0 +1,77 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Author and (c) 1999-2010: Amon Ott <ao@rsbac.org> */
+/* (a lot copied from mm/slab.c, with other          */
+/*  copyrights)                                      */
+/* Memory allocation functions for all parts         */
+/* Last modified: 24/Jun/2010                        */
+/*************************************************** */
+
+#include <rsbac/types.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/debug.h>
+#include <rsbac/aci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/timer.h>
+
+/**
+ * rsbac_kmalloc - allocate memory
+ * @size: how many bytes of memory are required.
+ *
+ * rsbac_kmalloc is the normal method of allocating memory for RSBAC
+ * in the kernel. It will always be of type GFP_KERNEL in 2.4 and
+ * GFP_ATOMIC in 2.6.
+ *
+ * rsbac_kmalloc'd memory is freed by rsbac_kfree
+ */
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_kmalloc);
+#endif
+void * rsbac_kmalloc (size_t size)
+{
+        if(!size)
+          return NULL;
+
+	return kmalloc(size, GFP_ATOMIC);
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_kmalloc_unlocked);
+#endif
+void * rsbac_kmalloc_unlocked (size_t size)
+{
+        if(!size)
+          return NULL;
+
+	return kmalloc(size, GFP_KERNEL);
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_kmalloc_clear);
+#endif
+void * rsbac_kmalloc_clear (size_t size)
+{
+        if(!size)
+          return NULL;
+
+	return kmalloc(size, GFP_ATOMIC | __GFP_ZERO);
+}
+
+#if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
+EXPORT_SYMBOL(rsbac_kmalloc_clear_unlocked);
+#endif
+void * rsbac_kmalloc_clear_unlocked (size_t size)
+{
+        if(!size)
+          return NULL;
+
+	return kmalloc(size, GFP_KERNEL | __GFP_ZERO);
+}
+
+inline void rsbac_kfree (const void *objp)
+{
+	kfree(objp);
+}
diff --git a/rsbac/help/syscalls.c b/rsbac/help/syscalls.c
new file mode 100644
index 0000000..5457dba
--- /dev/null
+++ b/rsbac/help/syscalls.c
@@ -0,0 +1,9143 @@
+/*************************************************** */
+/* Rule Set Based Access Control                     */
+/* Implementation of RSBAC general system calls      */
+/* Author and (C) 1999-2016: Amon Ott <ao@rsbac.org> */
+/*                                                   */
+/* Last modified: 26/Mar/2016                        */
+/*************************************************** */
+
+#include <rsbac/types.h>
+#include <rsbac/aci.h>
+#include <rsbac/mac.h>
+#include <rsbac/auth.h>
+#include <rsbac/acl.h>
+#include <rsbac/reg.h>
+#include <rsbac/error.h>
+#include <rsbac/debug.h>
+#include <rsbac/helpers.h>
+#include <rsbac/getname.h>
+#include <rsbac/network.h>
+#include <linux/semaphore.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <rsbac/rkmem.h>
+#include <rsbac/gen_lists.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/namei.h>
+
+#include <rsbac/adf.h>
+#include <rsbac/adf_main.h>
+#include <rsbac/adf_syshelpers.h>
+#include <rsbac/rc.h>
+#include <rsbac/um.h>
+#include <rsbac/um_types.h>
+#include <rsbac/syscalls.h>
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+#include <rsbac/network.h>
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+#include <rsbac/daz.h>
+#endif
+#ifdef CONFIG_RSBAC_UDF
+#include <rsbac/udf.h>
+#endif
+
+/************************************************************************** */
+/*                          Global Variables                                */
+/************************************************************************** */
+
+extern struct semaphore rsbac_write_sem;
+
+#ifdef CONFIG_RSBAC_XSTATS
+extern __u64 syscall_count[RSYS_none];
+#endif
+
+/************************************************* */
+/*              Declarations                       */
+/************************************************* */
+
+/************************************************* */
+/*              General functions                  */
+/************************************************* */
+
+/* All functions return 0, if no error occurred, and a negative error code  */
+/* otherwise. The error codes are defined in rsbac/error.h.                 */
+
+int sys_rsbac_stats(void)
+  {
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_stats(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.scd = ST_rsbac;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                           task_pid(current),
+                           T_SCD,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    return rsbac_stats();
+  }
+
+long sys_sync(void);
+
+int sys_rsbac_check(int correct, int check_inode)
+  {
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+    int result;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_check(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.scd = ST_rsbac;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                           task_pid(current),
+                           T_SCD,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    rsbac_printk(KERN_INFO
+           "sys_rsbac_check(): triggering RSBAC consistency check, correct = %u, check_inode = %u!\n",
+           correct, check_inode);
+
+    result=rsbac_check_lists(correct);
+
+    /* call other checks */
+#if defined(CONFIG_RSBAC_ACL)
+    if(!result)
+	    result=rsbac_check_acl(correct);
+#endif
+#if defined(CONFIG_RSBAC_REG)
+    if(!result)
+	    result=rsbac_check_reg(correct, check_inode);
+#endif
+
+    return result;
+  }
+
+int sys_rsbac_write(void)
+  {
+#if defined(CONFIG_RSBAC_AUTO_WRITE)
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_write(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.scd = ST_rsbac;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_WRITE,
+                           task_pid(current),
+                           T_SCD,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    return rsbac_write();
+#else
+    return 0;
+#endif /* CONFIG_RSBAC_AUTO_WRITE */
+  };
+
+/************************************************* */
+/*               Attribute functions               */
+/************************************************* */
+
+int sys_rsbac_get_attr(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_switch_target_t module,
+  enum rsbac_target_t target,
+  union rsbac_target_id_t __user * tid,
+  enum rsbac_attribute_t attr,
+  union rsbac_attribute_value_t __user * value,
+  int inherit)
+    { 
+      union rsbac_target_id_t k_tid;
+      union rsbac_attribute_value_t k_value;
+      int   err = 0;
+      rsbac_boolean_t i_inherit;
+
+      if(module > SW_NONE)
+        return -RSBAC_EINVALIDMODULE;
+      if(!tid || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+      if(!value)
+        return -RSBAC_EINVALIDPOINTER;
+      if(attr >= A_none)
+        return -RSBAC_EINVALIDATTR;
+
+      if(module == SW_NONE)
+        {
+          module = get_attr_module(attr);
+          if(module == SW_NONE)
+            return -RSBAC_EINVALIDMODULE;
+        }
+
+      /* get values from user space */
+      rsbac_get_user(&k_tid, tid, sizeof(k_tid) );
+      rsbac_get_user(&k_value, value, sizeof(k_value) );
+
+       switch (target) {
+               case T_FD:
+                       return -RSBAC_EINVALIDTARGET;
+               case T_FILE:
+               case T_DIR:
+               case T_FIFO:
+               case T_SYMLINK:
+               case T_UNIXSOCK:
+                       k_tid.file.dentry_p = NULL;
+                       k_tid.dir.dentry_p = NULL;
+                       break;
+               case T_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                       if (RSBAC_UID_SET(k_tid.user) == RSBAC_UM_VIRTUAL_KEEP)
+                         k_tid.user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_tid.user));
+                       else
+                         if (   (RSBAC_UID_SET(k_tid.user) > RSBAC_UM_VIRTUAL_MAX)
+                             && (RSBAC_UID_SET(k_tid.user) != RSBAC_UM_VIRTUAL_ALL)
+                            )
+                           return -RSBAC_EINVALIDTARGET;
+#else
+                       k_tid.user = RSBAC_UID_NUM(k_tid.user);
+#endif
+                       break;
+               case T_GROUP:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                       if (RSBAC_GID_SET(k_tid.group) == RSBAC_UM_VIRTUAL_KEEP)
+                         k_tid.group = RSBAC_GEN_GID (rsbac_get_vset(), RSBAC_GID_NUM(k_tid.group));
+                       else
+                         if (   (RSBAC_GID_SET(k_tid.group) > RSBAC_UM_VIRTUAL_MAX)
+                             && (RSBAC_GID_SET(k_tid.group) != RSBAC_UM_VIRTUAL_ALL)
+                            )
+                           return -RSBAC_EINVALIDTARGET;
+#else
+                       k_tid.group = RSBAC_GID_NUM(k_tid.group);
+#endif
+                       break;
+               case T_PROCESS:
+                       k_tid.process = find_pid_ns(k_tid.uprocess, &init_pid_ns);
+                       if(!k_tid.process)
+                         return -RSBAC_EINVALIDTARGET;
+                       break;
+               default:
+                       break;
+       }
+
+      if(inherit)
+        i_inherit = TRUE;
+      else
+        i_inherit = FALSE;
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+      /* sanity check before using pointer */
+      if(   (target == T_NETOBJ)
+         && (   !k_tid.netobj.sock_p
+             || k_tid.netobj.remote_addr
+             || !k_tid.netobj.sock_p->file
+             || !k_tid.netobj.sock_p->file->f_path.dentry
+             || !k_tid.netobj.sock_p->file->f_path.dentry->d_inode
+             || (SOCKET_I(k_tid.netobj.sock_p->file->f_path.dentry->d_inode) != k_tid.netobj.sock_p)
+            )
+        )
+        return -RSBAC_EINVALIDTARGET;
+#endif
+
+      /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr(): calling ADF\n");
+        }
+#endif
+      if (!rsbac_adf_request(R_READ_ATTRIBUTE,
+                             task_pid(current),
+                             target,
+                             k_tid,
+                             attr,
+                             k_value))
+        {
+          return -EPERM;
+        }
+
+      err = rsbac_ta_get_attr(ta_number, module, target, k_tid, attr, &k_value, i_inherit);
+      /* put result value to user space */
+      if(!err)
+        {
+          err = rsbac_put_user(&k_value, value, sizeof(k_value) );
+        }
+      return err;
+    }      /* end of sys_rsbac_get_attr() */
+
+
+int sys_rsbac_get_attr_n(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_switch_target_t module,
+  enum rsbac_target_t target,
+  char __user * t_name,
+  enum rsbac_attribute_t attr,
+  union rsbac_attribute_value_t __user * value,
+  int inherit)
+    { 
+      union rsbac_attribute_value_t k_value;
+      struct dentry * t_dentry;
+      int     err = 0;
+      union rsbac_target_id_t tid;
+/*    struct passwd * user_description_p; */
+      rsbac_boolean_t i_inherit;
+      struct path path;
+
+      if(module > SW_NONE)
+        return -RSBAC_EINVALIDMODULE;
+      if(!t_name || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+      if(!value)
+        return -RSBAC_EINVALIDPOINTER;
+      if(attr >= A_none)
+        return -RSBAC_EINVALIDATTR;
+
+      if(module == SW_NONE)
+        {
+          module = get_attr_module(attr);
+          if(module == SW_NONE)
+            return -RSBAC_EINVALIDMODULE;
+        }
+
+      if(inherit)
+        i_inherit = TRUE;
+      else
+        i_inherit = FALSE;
+
+      /* get values from user space */
+      rsbac_get_user(&k_value, value, sizeof(k_value) );
+      switch (target) {
+               case T_FD:
+               case T_FILE:
+               case T_DIR:
+               case T_FIFO:
+               case T_SYMLINK:
+               case T_UNIXSOCK:
+                       tid.file.dentry_p = NULL;
+                       tid.dir.dentry_p = NULL;
+                       break;
+               default:
+                       return -RSBAC_EINVALIDTARGET;
+       }
+      
+      /* lookup filename */
+      if ((err = user_lpath(t_name, &path)))
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): call to user_lpath() returned %i\n", err);
+            }
+#endif
+          goto out;
+        }
+      t_dentry = path.dentry;
+      if (!t_dentry->d_inode)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): file not found\n");
+            }
+#endif
+          err = -RSBAC_EINVALIDTARGET;
+          goto out_dput;
+        }
+
+      switch (target)
+        {
+          /* is inode of right type? */
+          case T_FD:
+            if(S_ISREG(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISDIR(t_dentry->d_inode->i_mode))
+              {
+                target = T_DIR;
+              }
+            else
+            if(S_ISLNK(t_dentry->d_inode->i_mode))
+              {
+                target = T_SYMLINK;
+              }
+            else
+            if(S_ISFIFO(t_dentry->d_inode->i_mode))
+              {
+                target = T_FIFO;
+              }
+            else
+            if(S_ISBLK(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISCHR(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISSOCK(t_dentry->d_inode->i_mode))
+              {
+                target = T_UNIXSOCK;
+              }
+            else
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no filesystem object\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FILE:
+            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no file\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DIR:
+            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no dir\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FIFO:
+            /* is inode of type fifo? */
+            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no fifo\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_UNIXSOCK:
+            /* is inode of type socket? */
+            if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no socket\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_SYMLINK:
+            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no symlink\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DEV:
+            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): no dev\n");
+                  }
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDTARGET;
+            goto out_dput;
+        }
+
+      if(target == T_DEV)
+        {
+          if(S_ISBLK(t_dentry->d_inode->i_mode))
+            tid.dev.type = D_block;
+          else
+            tid.dev.type = D_char;
+          tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+          tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+        }
+      else
+        {
+          /* fill target id and call internal function */
+          tid.file.device = t_dentry->d_sb->s_dev;
+          tid.file.inode  = t_dentry->d_inode->i_ino;
+          tid.file.dentry_p = t_dentry;
+        }
+      /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr_n(): calling ADF\n");
+        }
+#endif
+      if (!rsbac_adf_request(R_READ_ATTRIBUTE,
+                             task_pid(current),
+                             target,
+                             tid,
+                             attr,
+                             k_value))
+        {
+          err = -EPERM;
+        }
+      else
+        {
+          err = rsbac_ta_get_attr(ta_number, module, target, tid, attr, &k_value, i_inherit);
+          /* put result value to user space */
+          if(!err)
+            rsbac_put_user(&k_value, value, sizeof(k_value) );
+        }
+
+out_dput:
+      path_put(&path);
+
+out:
+      return err;
+    }      /* end of sys_rsbac_get_attr_n() */
+
+/************************************************************************** */
+
+int sys_rsbac_set_attr(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_switch_target_t module,
+  enum rsbac_target_t target,
+  union rsbac_target_id_t __user * tid,
+  enum rsbac_attribute_t attr,
+  union rsbac_attribute_value_t __user * value)
+    { 
+      union rsbac_target_id_t k_tid;
+      union rsbac_attribute_value_t k_value;
+      int   err = 0;
+      
+      if(module > SW_NONE)
+        return -RSBAC_EINVALIDMODULE;
+      if(!tid || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+      if(!value)
+        return -RSBAC_EINVALIDPOINTER;
+      if(attr >= A_none)
+        return -RSBAC_EINVALIDATTR;
+
+      if(module == SW_NONE)
+        {
+          module = get_attr_module(attr);
+          if(module == SW_NONE)
+            return -RSBAC_EINVALIDMODULE;
+        }
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_set_attr(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+        
+      /* get values from user space */
+      rsbac_get_user(&k_tid, tid, sizeof(k_tid) );
+      rsbac_get_user(&k_value, value, sizeof(k_value) );
+
+
+      switch(target)
+        {
+          case T_PROCESS:
+            k_tid.process = find_pid_ns(k_tid.uprocess, &init_pid_ns);
+            if(!k_tid.process)
+              return -RSBAC_EINVALIDTARGET;
+            break;
+
+#ifdef CONFIG_RSBAC_NET_OBJ
+            /* sanity check before using pointer */
+          case T_NETOBJ:
+            if(   !k_tid.netobj.sock_p
+               || k_tid.netobj.remote_addr
+               || !k_tid.netobj.sock_p->file
+               || !k_tid.netobj.sock_p->file->f_path.dentry
+               || !k_tid.netobj.sock_p->file->f_path.dentry->d_inode
+               || (SOCKET_I(k_tid.netobj.sock_p->file->f_path.dentry->d_inode) != k_tid.netobj.sock_p)
+              )
+              return -RSBAC_EINVALIDTARGET;
+#endif
+            break;
+          case T_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(k_tid.user) == RSBAC_UM_VIRTUAL_KEEP)
+              k_tid.user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_tid.user));
+            else
+              if (   (RSBAC_UID_SET(k_tid.user) > RSBAC_UM_VIRTUAL_MAX)
+                  && (RSBAC_UID_SET(k_tid.user) != RSBAC_UM_VIRTUAL_ALL)
+                 )
+                return -RSBAC_EINVALIDTARGET;
+#else
+            k_tid.user = RSBAC_UID_NUM(k_tid.user);
+#endif
+            break;
+          case T_GROUP:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_GID_SET(k_tid.group) == RSBAC_UM_VIRTUAL_KEEP)
+              k_tid.group = RSBAC_GEN_GID (rsbac_get_vset(), RSBAC_GID_NUM(k_tid.group));
+            else
+              if (   (RSBAC_GID_SET(k_tid.group) > RSBAC_UM_VIRTUAL_MAX)
+                  && (RSBAC_GID_SET(k_tid.group) != RSBAC_UM_VIRTUAL_ALL)
+                 )
+                return -RSBAC_EINVALIDTARGET;
+#else
+            k_tid.group = RSBAC_GID_NUM(k_tid.group);
+#endif
+            break;
+
+          case T_FD:
+          case T_FILE:
+          case T_DIR:
+          case T_FIFO:
+          case T_SYMLINK:
+          case T_UNIXSOCK:
+            return -RSBAC_EINVALIDTARGET;
+
+          default:
+            break;
+        }
+      
+      /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef)
+        rsbac_printk(KERN_DEBUG
+               "sys_rsbac_set_attr(): calling ADF\n");
+#endif
+      if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                             task_pid(current),
+                             target,
+                             k_tid,
+                             attr,
+                             k_value))
+        {
+          return -EPERM;
+        }
+      err = rsbac_ta_set_attr(ta_number, module, target, k_tid, attr, k_value);
+      return err;
+    }      /* end of sys_rsbac_set_attr() */
+
+int sys_rsbac_set_attr_n(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_switch_target_t module,
+  enum rsbac_target_t target,
+  char __user * t_name,
+  enum rsbac_attribute_t attr,
+  union rsbac_attribute_value_t __user * value)
+    {
+      struct dentry * t_dentry;
+      int     err = 0;
+      union rsbac_attribute_value_t k_value;
+      union rsbac_target_id_t  tid;
+      struct path path;
+
+      if(module > SW_NONE)
+        return -RSBAC_EINVALIDMODULE;
+      if(!t_name || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+      if(!value)
+        return -RSBAC_EINVALIDPOINTER;
+      if(attr >= A_none)
+        return -RSBAC_EINVALIDATTR;
+        
+      if(module == SW_NONE)
+        {
+          module = get_attr_module(attr);
+          if(module == SW_NONE)
+            return -RSBAC_EINVALIDMODULE;
+        }
+
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_set_attr_n(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+      /* get values from user space */
+      rsbac_get_user(&k_value, value, sizeof(k_value) );
+
+      /* lookup filename */
+      if ((err = user_lpath(t_name, &path)))
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): call to user_lpath() returned %i\n", err);
+#endif
+          goto out;
+        }
+      t_dentry = path.dentry;
+      if (!t_dentry->d_inode)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): file not found\n");
+#endif
+          err = -RSBAC_EINVALIDTARGET;
+          goto out_dput;
+        }
+
+      switch (target)
+        {
+          /* is inode of right type? */
+          case T_FD:
+            if(S_ISREG(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISDIR(t_dentry->d_inode->i_mode))
+              {
+                target = T_DIR;
+              }
+            else
+            if(S_ISLNK(t_dentry->d_inode->i_mode))
+              {
+                target = T_SYMLINK;
+              }
+            else
+            if(S_ISFIFO(t_dentry->d_inode->i_mode))
+              {
+                target = T_FIFO;
+              }
+            else
+            if(S_ISSOCK(t_dentry->d_inode->i_mode))
+              {
+                target = T_UNIXSOCK;
+              }
+            else
+            if(S_ISBLK(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISCHR(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): no filesystem object\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FILE:
+            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): no file\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DIR:
+            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr(): no dir\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FIFO:
+            /* is inode of type fifo? */
+            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): no fifo\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_UNIXSOCK:
+            /* is inode of type fifo? */
+            if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): no socket\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_SYMLINK:
+            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): no symlink\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DEV:
+            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): no dev\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDTARGET;
+            goto out_dput;
+        }
+
+      if(target == T_DEV)
+        {
+          if(S_ISBLK(t_dentry->d_inode->i_mode))
+            tid.dev.type = D_block;
+          else
+            tid.dev.type = D_char;
+          tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+          tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+        }
+      else
+        {
+          /* fill target id and call internal function */
+          tid.file.device = t_dentry->d_sb->s_dev;
+          tid.file.inode  = t_dentry->d_inode->i_ino;
+          tid.file.dentry_p = t_dentry;
+        }
+      /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_set_attr_n(): calling ADF\n");
+#endif
+      if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                             task_pid(current),
+                             target,
+                             tid,
+                             attr,
+                             k_value))
+        {
+          err = -EPERM;
+        }
+      else
+        {
+          err = rsbac_ta_set_attr(ta_number, module, target, tid, attr, k_value);
+        }
+
+out_dput:
+      path_put(&path);
+
+out:
+      return err;
+    }      /* end of sys_rsbac_set_attr_n() */
+
+/************************************************************************** */
+
+int sys_rsbac_remove_target(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_target_t target,
+  union rsbac_target_id_t __user * tid)
+    { 
+      union rsbac_target_id_t k_tid;
+      int   err = 0;
+
+      /* for adf_request */
+      union rsbac_attribute_value_t rsbac_attribute_value;
+      
+      if(!tid || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+        
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_remove_target(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+      /* get values from user space */
+      rsbac_get_user(&k_tid, tid, sizeof(k_tid) );
+
+      switch (target) {
+        case T_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_UID_SET(k_tid.user) == RSBAC_UM_VIRTUAL_KEEP)
+            k_tid.user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_tid.user));
+#else
+          k_tid.user = RSBAC_UID_NUM(k_tid.user);
+#endif
+          break;
+        case T_GROUP:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if (RSBAC_GID_SET(k_tid.group) == RSBAC_UM_VIRTUAL_KEEP)
+            k_tid.group = RSBAC_GEN_GID (rsbac_get_vset(), RSBAC_GID_NUM(k_tid.group));
+#else
+          k_tid.group = RSBAC_GID_NUM(k_tid.group);
+#endif
+          break;
+        case T_PROCESS:
+          k_tid.process = find_pid_ns(k_tid.uprocess, &init_pid_ns);
+          if(!k_tid.process)
+            return -RSBAC_EINVALIDTARGET;
+          break;
+
+        default:
+          break;
+      }
+
+      /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target(): calling ADF\n");
+#endif
+      rsbac_attribute_value.dummy = 0;
+      if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                             task_pid(current),
+                             target,
+                             k_tid,
+                             A_none,
+                             rsbac_attribute_value))
+        {
+          return -EPERM;
+        }
+      err = rsbac_ta_remove_target(ta_number, target, k_tid);
+      return err;
+    }      /* end of sys_rsbac_remove_target() */
+
+int sys_rsbac_remove_target_n(
+  rsbac_list_ta_number_t ta_number,
+  enum rsbac_target_t target,
+  char __user * t_name)
+    { 
+      struct dentry * t_dentry;
+      int     err = 0;
+      union rsbac_target_id_t  tid;
+
+      /* for adf_request */
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+/*    struct passwd * user_description_p; */
+      
+      struct path path;
+
+      if(!t_name || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_remove_target_n(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+      /* lookup filename */
+      if ((err = user_lpath(t_name, &path)))
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): call to user_lpath() returned %i\n", err);
+#endif
+          goto out;
+        }
+      t_dentry = path.dentry;
+      if (!t_dentry->d_inode)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): file not found\n");
+#endif
+          err = -RSBAC_EINVALIDTARGET;
+          goto out_dput;
+        }
+
+      switch (target)
+        {
+          /* is inode of right type? */
+          case T_FD:
+            if(S_ISREG(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISDIR(t_dentry->d_inode->i_mode))
+              {
+                target = T_DIR;
+              }
+            else
+            if(S_ISLNK(t_dentry->d_inode->i_mode))
+              {
+                target = T_SYMLINK;
+              }
+            else
+            if(S_ISFIFO(t_dentry->d_inode->i_mode))
+              {
+                target = T_FIFO;
+              }
+            else
+            if(S_ISSOCK(t_dentry->d_inode->i_mode))
+              {
+                target = T_UNIXSOCK;
+              }
+            else
+            if(S_ISBLK(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISCHR(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): no filesystem object\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FILE:
+            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): no file\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DIR:
+            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_get_attr(): no dir\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FIFO:
+            /* is inode of type fifo? */
+            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): no fifo\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_UNIXSOCK:
+            /* is inode of type fifo? */
+            if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): no socket\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_SYMLINK:
+            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): no symlink\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DEV:
+            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): no dev\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDTARGET;
+            goto out_dput;
+        }
+
+      if(target == T_DEV)
+        {
+          if(S_ISBLK(t_dentry->d_inode->i_mode))
+            tid.dev.type = D_block;
+          else
+            tid.dev.type = D_char;
+          tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+          tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+        }
+      else
+        {
+          /* fill target id and call internal function */
+          tid.file.device = t_dentry->d_sb->s_dev;
+          tid.file.inode  = t_dentry->d_inode->i_ino;
+          tid.file.dentry_p = t_dentry;
+        }
+      /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_remove_target_n(): calling ADF\n");
+#endif
+      rsbac_attribute_value.dummy = 0;
+      if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                             task_pid(current),
+                             target,
+                             tid,
+                             A_none,
+                             rsbac_attribute_value))
+        {
+          err = -EPERM;
+        }
+      else
+        {
+          err = rsbac_ta_remove_target(ta_number, target, tid);
+        }
+
+out_dput:
+      path_put(&path);
+
+out:
+      return err;
+    }      /* end of sys_rsbac_remove_target_n() */
+
+int sys_rsbac_list_all_dev(
+  rsbac_list_ta_number_t ta_number,
+  struct rsbac_dev_desc_t __user * id_p,
+  u_long maxnum)
+  {
+    int err = 0;
+    long count;
+
+    if(id_p && maxnum)
+      {
+        struct rsbac_dev_desc_t * k_id_p = NULL;
+
+        count = rsbac_ta_list_all_dev(ta_number, &k_id_p);
+        if(count <= 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+
+        rsbac_kfree(k_id_p);
+
+        if(unlikely(err < 0))
+          return err;
+        else
+          return count;
+      }
+    else
+      return rsbac_ta_list_all_dev(ta_number, NULL);
+  }
+
+int sys_rsbac_list_all_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t __user * id_p,
+  u_long maxnum)
+  {
+    int err = 0;
+    long count;
+
+    if(id_p && maxnum)
+      {
+        rsbac_uid_t * k_id_p = NULL;
+
+        count = rsbac_ta_list_all_user(ta_number, &k_id_p);
+        if(count <= 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+
+        rsbac_kfree(k_id_p);
+
+        if(unlikely(err < 0))
+          return err;
+        else
+          return count;
+      }
+    else
+      return rsbac_ta_list_all_user(ta_number, NULL);
+  }
+
+int sys_rsbac_list_all_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t __user * id_p,
+  u_long maxnum)
+  {
+    int err = 0;
+    long count;
+
+    if(id_p && maxnum)
+      {
+        rsbac_gid_t * k_id_p = NULL;
+
+        count = rsbac_ta_list_all_group(ta_number, &k_id_p);
+        if(count <= 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+
+        rsbac_kfree(k_id_p);
+
+        if(unlikely(err < 0))
+          return err;
+        else
+          return count;
+      }
+    else
+      return rsbac_ta_list_all_group(ta_number, NULL);
+  }
+
+int sys_rsbac_list_all_ipc(rsbac_list_ta_number_t ta_number,
+			   struct rsbac_ipc_t __user * id_p, u_long maxnum)
+{
+	int err = 0;
+	long count;
+
+	if (id_p && maxnum) {
+		struct rsbac_ipc_t *k_id_p = NULL;
+
+		count = rsbac_ta_list_all_ipc(ta_number, &k_id_p);
+		if (count <= 0)
+			return count;
+		if (count > maxnum)
+			count = maxnum;
+
+		err = rsbac_put_user(k_id_p, id_p,
+				   count * sizeof(*k_id_p));
+
+		rsbac_kfree(k_id_p);
+
+		if(unlikely(err < 0))
+			return err;
+		else
+			return count;
+	} else
+		return rsbac_ta_list_all_ipc(ta_number, NULL);
+}
+
+int sys_rsbac_net_list_all_netdev(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_netdev_id_t __user * id_p,
+  u_long maxnum)
+  {
+#ifdef CONFIG_RSBAC_NET_DEV
+    int err = 0;
+    long count;
+
+    if(id_p && maxnum)
+      {
+        rsbac_netdev_id_t * k_id_p = NULL;
+
+        count = rsbac_ta_net_list_all_netdev(ta_number, &k_id_p);
+        if(count <= 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+
+        rsbac_kfree(k_id_p);
+
+        if(unlikely(err < 0))
+          return err;
+        else
+          return count;
+      }
+    else
+      return rsbac_ta_net_list_all_netdev(ta_number, NULL);
+
+#else
+    return -RSBAC_EINVALIDREQUEST;
+#endif /* CONFIG_RSBAC_NET_DEV */
+  }
+
+int sys_rsbac_net_template(rsbac_list_ta_number_t ta_number,
+			   enum rsbac_net_temp_syscall_t call,
+			   rsbac_net_temp_id_t id,
+			   union rsbac_net_temp_syscall_data_t __user * data_p)
+{
+#ifdef CONFIG_RSBAC_NET_OBJ
+	union rsbac_net_temp_syscall_data_t k_data;
+	int err = 0;
+	/* for adf_request */
+	union rsbac_target_id_t i_tid;
+	union rsbac_attribute_value_t i_attr_val;
+
+	if (!id)
+		return -RSBAC_EINVALIDVALUE;
+	if (!data_p)
+		return -RSBAC_EINVALIDPOINTER;
+
+	/* get data values from user space */
+	switch (call) {
+	case NTS_set_address:
+	case NTS_set_address_family:
+	case NTS_set_type:
+	case NTS_set_protocol:
+	case NTS_set_netdev:
+	case NTS_set_ports:
+	case NTS_set_name:
+	case NTS_new_template:
+	case NTS_copy_template:
+	case NTS_delete_template:
+#ifdef CONFIG_RSBAC_FREEZE
+		if (rsbac_freeze) {
+			rsbac_printk(KERN_WARNING "sys_rsbac_net_template(): RSBAC configuration frozen, no administration allowed\n");
+			return -EPERM;
+		}
+#endif
+		if (call != NTS_delete_template) {
+			err =
+			    rsbac_get_user(&k_data, data_p, sizeof(k_data));
+			if(unlikely(err < 0))
+				return err;
+		}
+		break;
+	case NTS_check_id:
+	case NTS_get_address:
+	case NTS_get_address_family:
+	case NTS_get_type:
+	case NTS_get_protocol:
+	case NTS_get_netdev:
+	case NTS_get_ports:
+	case NTS_get_name:
+		break;
+
+	default:
+		return -RSBAC_EINVALIDREQUEST;
+	}
+
+	if (   (call != NTS_new_template)
+	    && (call != NTS_copy_template)
+	    && !rsbac_ta_net_template_exists(ta_number, id)
+           )
+		return -RSBAC_EINVALIDTARGET;
+
+	rsbac_pr_debug(aef, "calling ADF\n");
+	i_tid.nettemp = id;
+	i_attr_val.dummy = 0;
+	switch (call) {
+	case NTS_new_template:
+		if (!rsbac_adf_request(R_CREATE,
+				       task_pid(current),
+				       T_NETTEMP,
+				       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+				return -EPERM;
+		break;
+
+	case NTS_copy_template:
+		if (!rsbac_ta_net_template_exist(ta_number, id)) {
+			if (!rsbac_adf_request(R_CREATE,
+					       task_pid(current),
+					       T_NETTEMP,
+					       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+				if (!rsbac_softmode)
+#endif
+					return -EPERM;
+		} else {
+			if (!rsbac_adf_request(R_WRITE,
+					       task_pid(current),
+					       T_NETTEMP,
+					       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+				if (!rsbac_softmode)
+#endif
+					return -EPERM;
+		}
+		i_tid.nettemp = k_data.id;
+		if (!rsbac_adf_request(R_READ,
+				       task_pid(current),
+				       T_NETTEMP,
+				       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+				return -EPERM;
+		break;
+
+	case NTS_delete_template:
+		if (!rsbac_adf_request(R_DELETE,
+				       task_pid(current),
+				       T_NETTEMP,
+				       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+				return -EPERM;
+		break;
+
+	case NTS_get_address:
+	case NTS_get_address_family:
+	case NTS_get_type:
+	case NTS_get_protocol:
+	case NTS_get_netdev:
+	case NTS_get_ports:
+		if (!rsbac_adf_request(R_READ,
+				       task_pid(current),
+				       T_NETTEMP,
+				       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+				return -EPERM;
+		break;
+
+	case NTS_set_address:
+	case NTS_set_address_family:
+	case NTS_set_type:
+	case NTS_set_protocol:
+	case NTS_set_netdev:
+	case NTS_set_ports:
+	case NTS_set_name:
+		if (!rsbac_adf_request(R_WRITE,
+				       task_pid(current),
+				       T_NETTEMP,
+				       i_tid, A_none, i_attr_val))
+#ifdef CONFIG_RSBAC_SOFTMODE
+			if (!rsbac_softmode)
+#endif
+				return -EPERM;
+		break;
+
+	default:
+		break;
+	}
+
+	err = rsbac_ta_net_template(ta_number, call, id, &k_data);
+	if (!err) {
+		/* put data values to user space */
+		switch (call) {
+		case NTS_check_id:
+		case NTS_get_address:
+		case NTS_get_address_family:
+		case NTS_get_type:
+		case NTS_get_protocol:
+		case NTS_get_netdev:
+		case NTS_get_ports:
+		case NTS_get_name:
+			err = rsbac_put_user(&k_data,
+					   data_p,
+					   sizeof(k_data));
+			break;
+		default:
+			break;
+		}
+	}
+	return err;
+
+#else
+	return -RSBAC_EINVALIDREQUEST;
+#endif				/* NET_OBJ */
+}
+
+int sys_rsbac_net_list_all_template(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_net_temp_id_t __user * id_p,
+  u_long maxnum)
+  {
+#ifdef CONFIG_RSBAC_NET_OBJ
+    int err = 0;
+    int count;
+    union rsbac_target_id_t i_tid;
+    union rsbac_attribute_value_t i_attr_val;
+
+    i_tid.nettemp = 0;
+    i_attr_val.dummy = 0;
+    if (!rsbac_adf_request(R_READ,
+                           task_pid(current),
+                           T_NETTEMP,
+                           i_tid,
+                           A_none,
+                           i_attr_val))
+      return -EPERM;
+    if(id_p && maxnum)
+      {
+        rsbac_net_temp_id_t * k_id_p = NULL;
+
+        count = rsbac_ta_net_list_all_template(ta_number, &k_id_p);
+        if(count <= 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+
+        rsbac_kfree(k_id_p);
+
+        if(unlikely(err < 0))
+          return err;
+        else
+          return count;
+      }
+    else
+      return rsbac_ta_net_list_all_template(ta_number, NULL);
+
+#else
+    return -RSBAC_EINVALIDREQUEST;
+#endif /* CONFIG_RSBAC_NET_OBJ */
+  }
+
+
+/************************************************* */
+/*                 ADF functions                   */
+/************************************************* */
+
+int sys_rsbac_switch(enum rsbac_switch_target_t module, int value)
+  {
+#if defined(CONFIG_RSBAC_SWITCH) || defined(CONFIG_RSBAC_SOFTMODE)
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+    char                         * switch_name;
+  
+    /* call ADF */
+    if(module >= SW_NONE)
+      return -RSBAC_EINVALIDTARGET;
+    if (   (value < 0)
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+        || (value > 3)
+#else
+        || (value > 1)
+#endif
+       )
+      return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_SOFTMODE
+    if(   rsbac_softmode_prohibit
+       && (   (   (value == 1)
+               && (module == SW_SOFTMODE)
+              )
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+           || (value == 3)
+#endif
+          )
+      )
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_switch(): setting of softmode prohibited!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      rsbac_printk(KERN_DEBUG "sys_rsbac_switch(): calling ADF\n");
+#endif
+    rsbac_target_id.dummy = 0;
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
+    if(module == SW_DAC_DISABLE)
+      {
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+        if(value > 1)
+          return -RSBAC_EINVALIDVALUE;
+#endif
+        rsbac_attribute_value.dummy = 0;
+        if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+                               task_pid(current),
+                               T_NONE,
+                               rsbac_target_id,
+                               A_none,
+                               rsbac_attribute_value))
+          {
+            return -EPERM;
+          }
+      }
+    else
+#endif
+      {
+        rsbac_attribute_value.switch_target = module;
+        if (!rsbac_adf_request(R_SWITCH_MODULE,
+                               task_pid(current),
+                               T_NONE,
+                               rsbac_target_id,
+                               A_switch_target,
+                               rsbac_attribute_value))
+          {
+            return -EPERM;
+          }
+      }
+
+    switch(value)
+      {
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+        case 2:
+        case 3:
+          rsbac_ind_softmode[module] = value - 2;
+          break;
+#endif
+
+        default:
+          switch (module)
+            {
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+              case SW_DAC_DISABLE: rsbac_dac_disable = value;
+                   break;
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE
+              case SW_SOFTMODE: rsbac_softmode = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+              case SW_FREEZE:
+                  if(rsbac_freeze)
+                    {
+                      rsbac_printk(KERN_WARNING
+                                   "sys_rsbac_switch(): RSBAC configuration frozen, no administration allowed!\n");
+                      return -EPERM;
+                    }
+                  rsbac_freeze = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+              case SW_MAC:
+#ifndef CONFIG_RSBAC_SWITCH_ON
+                  if(value)
+                    return -RSBAC_EINVALIDMODULE;
+#endif
+                  rsbac_switch_mac = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+              case SW_DAZ:
+                  rsbac_switch_daz = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_FF
+              case SW_FF:
+                  rsbac_switch_ff = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_RC
+              case SW_RC:
+#ifndef CONFIG_RSBAC_SWITCH_ON
+                  if(value)
+                    return -RSBAC_EINVALIDMODULE;
+#endif
+                  rsbac_switch_rc = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+              case SW_AUTH:
+                  rsbac_switch_auth = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+              case SW_ACL:
+                  rsbac_switch_acl = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+              case SW_CAP:
+                  rsbac_switch_cap = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+              case SW_JAIL:
+                  rsbac_switch_jail = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_RES
+              case SW_RES:
+                  rsbac_switch_res = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+              case SW_PAX:
+                  rsbac_switch_pax = value;
+                  break;
+#endif
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+              case SW_UDF:
+                  rsbac_switch_udf = value;
+                  break;
+#endif
+              default:
+                return -RSBAC_EINVALIDMODULE;
+            }
+      }
+
+    switch_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+    if(switch_name)
+      {
+        int show_value = value;
+
+        get_switch_target_name(switch_name, module);
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+        switch(value)
+          {
+            case 2:
+            case 3:
+              strcat(switch_name, " softmode");
+              show_value -= 2;
+              break;
+            default:
+              break;
+          }
+#endif
+        rsbac_printk(KERN_WARNING
+               "sys_rsbac_switch(): user %u switched RSBAC module %s to %i!\n",
+               __kuid_val(current_uid()), switch_name, show_value);
+        rsbac_kfree(switch_name);
+      }
+    return 0;
+#else
+    return -RSBAC_EINVALIDREQUEST;
+#endif /* SWITCH || SOFTMODE*/
+  }
+
+/**
+ * sys_rsbac_get_switch - get the module status 
+ * (is switchable ? is softmodable ?)
+ *
+ * @module:		the target module
+ * @value_p:		0: module is enabled
+ * 			1: module is softmodded
+ * @switchable_p:	0: module can be turned on
+ * 			1: module can be turned off
+ * 			2: softmode can be turned on, but not off
+ * 			3: softmode can be turned on or off
+ *
+ * Returns 0 on success
+ */
+int sys_rsbac_get_switch(enum rsbac_switch_target_t module,
+			int __user * value_p,
+			int __user * switchable_p)
+{
+	int                           value = 1; // default if module exists and RSBAC_SWITCH is not compiled
+	int                           switchable = 0;
+	int                           allow_softmode = 0;
+	int                           err = 0;
+	union rsbac_target_id_t       rsbac_target_id;
+	union rsbac_attribute_value_t rsbac_attribute_value;
+
+	if(module >= SW_NONE)
+		return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_DEBUG
+	if(rsbac_debug_aef)
+		rsbac_printk(KERN_DEBUG "sys_rsbac_get_switch(): calling ADF\n");
+#endif
+	rsbac_target_id.scd = ST_rsbac;
+	rsbac_attribute_value.dummy = 0;
+	if(!rsbac_adf_request(R_GET_STATUS_DATA,
+				task_pid(current),
+				T_SCD,
+				rsbac_target_id,
+				A_none,
+				rsbac_attribute_value))
+	{
+		return -EPERM;
+	}
+	switch(module)
+	{
+		case SW_GEN:
+			allow_softmode = 0;
+			switchable = 0;
+			break;
+#ifdef CONFIG_RSBAC_UM
+		case SW_UM:
+			allow_softmode = 0;
+			switchable = 0;
+			break;
+#endif
+#ifdef CONFIG_RSBAC_REG
+		case SW_REG:
+			allow_softmode = 1;
+			switchable = 0;
+			break;
+#endif
+#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE_FULL
+		case SW_DAC_DISABLE:
+			allow_softmode = 0;
+			value = rsbac_dac_disable;
+			switchable = 3;
+			break;
+#endif
+#ifdef CONFIG_RSBAC_SOFTMODE
+		case SW_SOFTMODE:
+			allow_softmode = 0;
+			value = rsbac_softmode;
+			switchable = (rsbac_softmode_prohibit?2:3);
+			break;
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+		case SW_FREEZE:
+			allow_softmode = 0;
+			value = rsbac_freeze;
+			switchable = 1;
+			break;
+#endif
+#ifdef CONFIG_RSBAC_MAC
+		case SW_MAC:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_MAC
+			value = rsbac_switch_mac;
+#ifdef CONFIG_RSBAC_SWITCH_ON
+			switchable = 3;
+#else
+			switchable = 2;
+#endif
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+		case SW_DAZ:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_DAZ
+			value = rsbac_switch_daz;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_FF
+		case SW_FF:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_FF
+			value = rsbac_switch_ff;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_RC
+		case SW_RC:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_RC
+			value = rsbac_switch_rc;
+#ifdef CONFIG_RSBAC_SWITCH_ON
+			switchable = 3;
+#else
+			switchable = 2;
+#endif
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_AUTH
+		case SW_AUTH:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_AUTH
+			value = rsbac_switch_auth;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_ACL
+		case SW_ACL:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_ACL
+			value = rsbac_switch_acl;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_CAP
+		case SW_CAP:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_CAP
+			value = rsbac_switch_cap;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+		case SW_JAIL:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_JAIL
+			value = rsbac_switch_jail;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_RES
+		case SW_RES:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_RES
+			value = rsbac_switch_res;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_PAX
+		case SW_PAX:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_PAX
+			value = rsbac_switch_pax;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+#ifdef CONFIG_RSBAC_UDF
+		case SW_UDF:
+			allow_softmode = 1;
+#ifdef CONFIG_RSBAC_SWITCH_UDF
+			value = rsbac_switch_udf;
+			switchable = 3;
+#else
+			switchable = 0;
+#endif
+			break;
+#endif
+		default:
+			return -RSBAC_EINVALIDMODULE;
+	}
+
+#ifdef CONFIG_RSBAC_SOFTMODE_IND
+	if(allow_softmode) {
+		value |= rsbac_ind_softmode[module] << 1;
+		switchable |= (rsbac_softmode_prohibit?2:3) << 2;
+	}
+#endif
+	if(value_p)
+		err = rsbac_put_user(&value, value_p, sizeof(int));
+	if(!err && switchable_p)
+		err = rsbac_put_user(&switchable, switchable_p, sizeof(int));
+	return err;
+}
+
+/************** MAC ***************/
+
+#ifdef CONFIG_RSBAC_MAC
+int sys_rsbac_mac_set_curr_level(rsbac_security_level_t level,
+                                 rsbac_mac_category_vector_t __user * categories_p)
+  {
+    rsbac_mac_category_vector_t k_categories;
+    int err;
+
+    if(!categories_p)
+      return -RSBAC_EINVALIDPOINTER;
+    err = rsbac_get_user(&k_categories, categories_p, sizeof(k_categories));
+    if(unlikely(err < 0))
+      return err;
+    return rsbac_mac_set_curr_level(level, k_categories);
+  }
+
+int sys_rsbac_mac_get_curr_level(rsbac_security_level_t __user * level_p,
+                                 rsbac_mac_category_vector_t __user * categories_p)
+  {
+    int err = 0;
+    rsbac_security_level_t k_level;
+    rsbac_mac_category_vector_t k_categories;
+
+    err = rsbac_mac_get_curr_level(&k_level, &k_categories);
+    if(unlikely(err < 0))
+      return err;
+    if(level_p)
+      {
+        err = rsbac_put_user(&k_level, level_p, sizeof(k_level));
+        if(unlikely(err < 0))
+          return err;
+      }
+    if(categories_p)
+      {
+        err = rsbac_put_user(&k_categories, categories_p, sizeof(k_categories));
+      }
+    return err;
+  }
+
+int sys_rsbac_mac_get_max_level(rsbac_security_level_t __user * level_p,
+                                rsbac_mac_category_vector_t __user * categories_p)
+  {
+    int err = 0;
+    rsbac_security_level_t k_level;
+    rsbac_mac_category_vector_t k_categories;
+
+    err = rsbac_mac_get_max_level(&k_level, &k_categories);
+    if(unlikely(err < 0))
+      return err;
+    if(level_p)
+      {
+        err = rsbac_put_user(&k_level, level_p, sizeof(k_level));
+        if(unlikely(err < 0))
+          return err;
+      }
+    if(categories_p)
+      {
+        err = rsbac_put_user(&k_categories, categories_p, sizeof(k_categories));
+      }
+    return err;
+  }
+
+int sys_rsbac_mac_get_min_level(rsbac_security_level_t __user * level_p,
+                                rsbac_mac_category_vector_t __user * categories_p)
+  {
+    int err = 0;
+    rsbac_security_level_t k_level;
+    rsbac_mac_category_vector_t k_categories;
+
+    err = rsbac_mac_get_min_level(&k_level, &k_categories);
+    if(unlikely(err < 0))
+      return err;
+    if(level_p)
+      {
+        err = rsbac_put_user(&k_level, level_p, sizeof(k_level));
+        if(unlikely(err < 0))
+          return err;
+      }
+    if(categories_p)
+      {
+        err = rsbac_put_user(&k_categories, categories_p, sizeof(k_categories));
+      }
+    return err;
+  }
+
+/* Provide means for adding and removing of capabilities */
+int sys_rsbac_mac_add_p_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_upid_t upid,
+  rsbac_uid_t uid,
+  rsbac_time_t ttl)
+  {
+    rsbac_pid_t pid;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_mac_add_p_tru(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+      uid = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(uid));
+    else
+      if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+#else
+    uid = RSBAC_UID_NUM(uid);
+#endif
+
+    pid = find_pid_ns(upid, &init_pid_ns);
+    if(!pid)
+      return -RSBAC_EINVALIDTARGET;
+
+    return rsbac_mac_add_p_tru(ta_number, pid, uid, ttl);
+  }
+
+int sys_rsbac_mac_remove_p_tru(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_upid_t upid,
+  rsbac_uid_t uid)
+  {
+    rsbac_pid_t pid;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_mac_remove_p_tru(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+      uid = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(uid));
+    else
+      if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+#else
+    uid = RSBAC_UID_NUM(uid);
+#endif
+
+    pid = find_pid_ns(upid, &init_pid_ns);
+    if(!pid)
+      return -RSBAC_EINVALIDTARGET;
+    return rsbac_mac_remove_p_tru(ta_number, pid, uid);
+  }
+
+int sys_rsbac_mac_add_f_tru(
+  rsbac_list_ta_number_t ta_number,
+  char __user * filename,
+  rsbac_uid_t uid,
+  rsbac_time_t ttl)
+  {
+    struct dentry * t_dentry;
+    int     err = 0;
+    enum  rsbac_target_t     target;
+    union rsbac_target_id_t  tid;
+
+    struct path path;
+
+    if(!filename)
+      return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_mac_add_f_tru(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+      uid = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(uid));
+    else
+      if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+#else
+    uid = RSBAC_UID_NUM(uid);
+#endif
+
+    if ((err = user_lpath(filename, &path)))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_mac)
+          rsbac_printk(KERN_DEBUG "sys_rsbac_mac_add_f_tru(): call to user_lpath() returned %i\n", err);
+#endif
+        goto out;
+      }
+      t_dentry = path.dentry;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file? */
+    if(S_ISREG(t_dentry->d_inode->i_mode))
+      target = T_FILE;
+    else
+    if(S_ISDIR(t_dentry->d_inode->i_mode))
+      target = T_DIR;
+    else
+      { /* This is no file or dir */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    tid.file.device = t_dentry->d_sb->s_dev;
+    tid.file.inode  = t_dentry->d_inode->i_ino;
+    tid.file.dentry_p = t_dentry;
+
+    err = rsbac_mac_add_f_tru(ta_number, tid.file, uid, ttl);
+
+out_dput:
+    path_put(&path);
+
+out:
+    return err;
+  }
+
+int sys_rsbac_mac_remove_f_tru(
+  rsbac_list_ta_number_t ta_number,
+  char __user * filename,
+  rsbac_uid_t uid)
+  {
+    struct dentry * t_dentry;
+    int     err = 0;
+    enum  rsbac_target_t     target;
+    union rsbac_target_id_t  tid;
+
+    struct path path;
+
+    if(!filename)
+      return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_mac_remove_f_tru(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+      uid = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(uid));
+    else
+      if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+#else
+    uid = RSBAC_UID_NUM(uid);
+#endif
+
+    if ((err = user_lpath(filename, &path)))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_mac)
+          rsbac_printk(KERN_DEBUG "sys_rsbac_mac_remove_f_tru(): call to user_lpath() returned %i\n", err);
+#endif
+        goto out;
+      }
+      t_dentry = path.dentry;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file or dir? */
+    if(S_ISREG(t_dentry->d_inode->i_mode))
+      target = T_FILE;
+    else
+    if(S_ISDIR(t_dentry->d_inode->i_mode))
+      target = T_DIR;
+    else
+      { /* This is no file or dir */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    tid.file.device = t_dentry->d_sb->s_dev;
+    tid.file.inode  = t_dentry->d_inode->i_ino;
+    tid.file.dentry_p = t_dentry;
+
+    err = rsbac_mac_remove_f_tru(ta_number, tid.file, uid);
+
+out_dput:
+    path_put(&path);
+out:
+    return err;
+  }
+
+/* trulist must have space for maxnum rsbac_uid_t entries! */
+int sys_rsbac_mac_get_f_trulist(
+  rsbac_list_ta_number_t ta_number,
+  char __user * filename,
+  rsbac_uid_t __user trulist[],
+  rsbac_time_t __user ttllist[],
+  u_int maxnum)
+  {
+    struct dentry * t_dentry;
+    int     err = 0, tmperr = 0;
+    enum  rsbac_target_t     target;
+    union rsbac_target_id_t  tid;
+    rsbac_uid_t * k_trulist;
+    rsbac_time_t * k_ttllist;
+
+    struct path path;
+
+    if(!filename)
+      return -RSBAC_EINVALIDTARGET;
+    if(!trulist)
+      return -RSBAC_EINVALIDPOINTER;
+    if(maxnum <= 0)
+      return -RSBAC_EINVALIDVALUE;
+    if(maxnum > RSBAC_MAC_MAX_MAXNUM)
+      maxnum = RSBAC_MAC_MAX_MAXNUM;
+
+    if ((err = user_lpath(filename, &path)))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_mac)
+          rsbac_printk(KERN_DEBUG "sys_rsbac_mac_get_f_trulist(): call to user_lpath() returned %i\n", err);
+#endif
+        goto out;
+      }
+      t_dentry = path.dentry;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file or dir? */
+    if(S_ISREG(t_dentry->d_inode->i_mode))
+      target = T_FILE;
+    else
+    if(S_ISDIR(t_dentry->d_inode->i_mode))
+      target = T_DIR;
+    else
+      { /* This is no file or dir */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    tid.file.device = t_dentry->d_sb->s_dev;
+    tid.file.inode  = t_dentry->d_inode->i_ino;
+    tid.file.dentry_p = t_dentry;
+
+    err = rsbac_mac_get_f_trulist(ta_number, tid.file, &k_trulist, &k_ttllist);
+    if(err>0)
+      {
+        if(err > maxnum)
+          err = maxnum;
+        tmperr = rsbac_put_user(k_trulist, trulist,
+                                sizeof(rsbac_uid_t) * err);
+        if(tmperr < 0)
+          err = tmperr;
+        else
+          {
+            if(ttllist)
+              {
+                tmperr = rsbac_put_user(k_ttllist, ttllist,
+                                        sizeof(rsbac_time_t) * err);
+                if(tmperr < 0)
+                  err = tmperr;
+              }
+          }
+        rsbac_kfree(k_trulist);
+        rsbac_kfree(k_ttllist);
+      }
+
+out_dput:
+    path_put(&path);
+out:
+    return err;
+  }
+
+int sys_rsbac_mac_get_p_trulist(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_upid_t upid,
+  rsbac_uid_t __user trulist[],
+  rsbac_time_t __user ttllist[],
+  u_int maxnum)
+  {
+    int     err = 0, tmperr = 0;
+    union rsbac_target_id_t  tid;
+    rsbac_uid_t * k_trulist;
+    rsbac_time_t * k_ttllist;
+
+    if(!upid)
+      return -RSBAC_EINVALIDTARGET;
+    if(!trulist)
+      return -RSBAC_EINVALIDPOINTER;
+    if(maxnum <= 0)
+      return -RSBAC_EINVALIDVALUE;
+    if(maxnum > RSBAC_MAC_MAX_MAXNUM)
+      maxnum = RSBAC_MAC_MAX_MAXNUM;
+
+    tid.process = find_pid_ns(upid, &init_pid_ns);
+    if(!tid.process)
+      return -RSBAC_EINVALIDTARGET;
+
+    err = rsbac_mac_get_p_trulist(ta_number, tid.process, &k_trulist, &k_ttllist);
+    if(err>0)
+      {
+        if(err > maxnum)
+          err = maxnum;
+        tmperr = rsbac_put_user(k_trulist, trulist,
+                                sizeof(rsbac_uid_t) * err);
+        if(tmperr < 0)
+          err = tmperr;
+        else
+          {
+            if(ttllist)
+              {
+                tmperr = rsbac_put_user(k_ttllist, ttllist,
+                                        sizeof(rsbac_time_t) * err);
+                if(tmperr < 0)
+                  err = tmperr;
+              }
+          }
+        rsbac_kfree(k_trulist);
+        rsbac_kfree(k_ttllist);
+      }
+
+    return err;
+  }
+#endif
+
+/************** DAZ ***************/
+
+#ifdef CONFIG_RSBAC_DAZ
+int sys_rsbac_daz_flush_cache(void)
+  {
+#ifndef CONFIG_RSBAC_DAZ_CACHE
+    return 0;
+#else
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    /* Security Officer or admin? */
+    i_tid.user = __kuid_val(current_uid());
+    if (rsbac_get_attr(SW_DAZ,
+                       T_USER,
+                       i_tid,
+                       A_daz_role,
+                       &i_attr_val1,
+                       TRUE))
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_daz_flush_cache(): rsbac_get_attr() returned error!\n");
+        return -EPERM;
+      }
+    /* if not sec_officer or admin, deny */
+    if (   (i_attr_val1.system_role != SR_security_officer)
+        && (i_attr_val1.system_role != SR_administrator)
+       )
+      #ifdef CONFIG_RSBAC_SOFTMODE
+      if(   !rsbac_softmode
+      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+         && !rsbac_ind_softmode[SW_DAZ]
+      #endif
+        )
+      #endif
+      return -EPERM;
+
+    rsbac_printk(KERN_INFO
+           "sys_rsbac_daz_flush_cache(): flushing DAZuko result cache!\n");
+
+    return rsbac_daz_flush_cache();
+#endif
+  }
+#endif
+
+/************** RC ***************/
+
+#ifdef CONFIG_RSBAC_RC
+int sys_rsbac_rc_copy_role(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_rc_role_id_t from_role,
+  rsbac_rc_role_id_t to_role)
+  {
+    if(   (from_role > RC_role_max_value)
+       || (from_role > RC_role_max_value))
+      return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef_rc)
+      rsbac_printk(KERN_DEBUG
+             "sys_rsbac_rc_copy_role(): from %i, to %i!\n",
+             from_role, to_role);
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_rc_copy_role(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    /* call rc function and return its result */
+    return rsbac_rc_sys_copy_role(ta_number, from_role, to_role);
+  }
+
+int sys_rsbac_rc_copy_type(
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t      target,
+        rsbac_rc_type_id_t     from_type,
+        rsbac_rc_type_id_t     to_type)
+  {
+    if(   (from_type > RC_type_max_value)
+       || (from_type > RC_type_max_value))
+      return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef_rc)
+      rsbac_printk(KERN_DEBUG
+             "sys_rsbac_rc_copy_type(): from %i, to %i!\n",
+             from_type, to_type);
+#endif
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_rc_copy_type(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    /* call rc function and return its result */
+    return rsbac_rc_sys_copy_type(ta_number, target, from_type, to_type);
+  }
+
+/* Getting values */
+int sys_rsbac_rc_get_item (
+        rsbac_list_ta_number_t  ta_number,
+  enum  rsbac_rc_target_t       target,
+  union rsbac_rc_target_id_t __user * tid_p,
+  union rsbac_rc_target_id_t __user * subtid_p,
+  enum  rsbac_rc_item_t         item,
+  union rsbac_rc_item_value_t __user * value_p,
+        rsbac_time_t          __user * ttl_p)
+  {
+    union rsbac_rc_target_id_t  k_tid;
+    union rsbac_rc_target_id_t  k_subtid;
+    union rsbac_rc_item_value_t k_value;
+          rsbac_time_t          k_ttl;
+    int err = 0;
+
+    if(   (target >= RT_NONE)
+       || (item >= RI_none))
+      return -RSBAC_EINVALIDVALUE;
+    /* get values from user space */
+    rsbac_get_user(&k_tid, tid_p, sizeof(k_tid) );
+    rsbac_get_user(&k_subtid, subtid_p, sizeof(k_subtid) );
+    rsbac_get_user(&k_value, value_p, sizeof(k_value) );
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef_rc)
+      rsbac_printk(KERN_DEBUG
+             "sys_rsbac_rc_get_item(): target %i, item %i!\n",
+             target, item);
+#endif
+    /* call rc function and return its result */
+    err = rsbac_rc_sys_get_item(ta_number, target, k_tid, k_subtid,
+                                item, &k_value, &k_ttl);
+    /* put result value to user space */
+    if(!err)
+      {
+        err = rsbac_put_user(&k_value, value_p, sizeof(k_value) );
+        if(!err && ttl_p)
+          err = rsbac_put_user(&k_ttl, ttl_p, sizeof(k_ttl) );
+      }
+    return err;
+  }
+
+/* Setting values */
+int sys_rsbac_rc_set_item(
+  rsbac_list_ta_number_t        ta_number,
+  enum  rsbac_rc_target_t       target,
+  union rsbac_rc_target_id_t __user * tid_p,
+  union rsbac_rc_target_id_t __user * subtid_p,
+  enum  rsbac_rc_item_t         item,
+  union rsbac_rc_item_value_t __user * value_p,
+        rsbac_time_t            ttl)
+  {
+    union rsbac_rc_target_id_t  k_tid;
+    union rsbac_rc_target_id_t  k_subtid;
+    union rsbac_rc_item_value_t k_value;
+
+    if(   (target >= RT_NONE)
+       || (item >= RI_none))
+      return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_rc_set_item(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    /* get values from user space */
+    rsbac_get_user(&k_tid, tid_p, sizeof(k_tid) );
+    rsbac_get_user(&k_subtid, subtid_p, sizeof(k_subtid) );
+    rsbac_get_user(&k_value, value_p, sizeof(k_value) );
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef_rc)
+      rsbac_printk(KERN_DEBUG
+             "sys_rsbac_rc_set_item(): target %i, item %i!\n",
+             target, item);
+#endif
+    /* call rc function and return its result */
+    return rsbac_rc_sys_set_item(ta_number, target, k_tid, k_subtid, item, k_value, ttl);
+  }
+
+int sys_rsbac_rc_get_list(
+        rsbac_list_ta_number_t ta_number,
+  enum  rsbac_rc_target_t      target,
+  union rsbac_rc_target_id_t __user * tid_p,
+  enum  rsbac_rc_item_t        item,
+        u_int                  maxnum,
+        __u32                __user * array_p,
+        rsbac_time_t         __user * ttl_array_p)
+  {
+    union rsbac_rc_target_id_t  k_tid;
+    int err;
+
+    rsbac_get_user(&k_tid, tid_p, sizeof(k_tid));
+    if(array_p)
+      {
+        __u32 * k_array_p;
+        rsbac_time_t * k_ttl_array_p;
+
+        if(!maxnum)
+          return -RSBAC_EINVALIDVALUE;
+        /* call rc function and return its result */
+        err = rsbac_rc_get_list(ta_number, target, k_tid, item,
+                                &k_array_p, &k_ttl_array_p);
+        /* put result value to user space */
+        if(err > 0)
+          {
+            int tmperr;
+
+            if(err > maxnum)
+              err = maxnum;
+            tmperr = rsbac_put_user(k_array_p, array_p, err * sizeof(*k_array_p) );
+            if(tmperr)
+              err = tmperr;
+            rsbac_kfree(k_array_p);
+            if(k_ttl_array_p && ttl_array_p)
+              {
+                tmperr = rsbac_put_user(k_ttl_array_p, ttl_array_p, err * sizeof(*k_ttl_array_p) );
+                if(tmperr)
+                  err = tmperr;
+              }
+            rsbac_kfree(k_ttl_array_p);
+          }
+        return err;
+      }
+    else
+      return rsbac_rc_get_list(ta_number, target, k_tid, item, NULL, NULL);
+  }
+
+/* Set own role */
+int sys_rsbac_rc_change_role (rsbac_rc_role_id_t role, char __user * pass)
+  {
+    if(role > RC_role_max_value)
+      return -RSBAC_EINVALIDVALUE;
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef_rc)
+      rsbac_printk(KERN_DEBUG
+             "sys_rsbac_rc_change_role(): role %i!\n",
+             role);
+#endif
+    /* call rc function and return its result */
+    return rsbac_rc_sys_change_role(role, pass);
+  }
+
+/* Getting own effective rights */
+int sys_rsbac_rc_get_eff_rights_n(
+        rsbac_list_ta_number_t      ta_number,
+  enum  rsbac_target_t              target,
+        char                      __user * t_name,
+        rsbac_rc_request_vector_t __user * request_vector_p,
+        rsbac_time_t              __user * ttl_p)
+  {
+      struct dentry * t_dentry;
+      int     err = 0;
+      rsbac_rc_request_vector_t k_req_vec;
+      rsbac_time_t          k_ttl;
+      union rsbac_target_id_t  tid;
+
+      struct path path;
+
+      if(!t_name || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+
+      if ((err = user_lpath(t_name, &path)))
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_rc)
+            rsbac_printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): call to user_lpath() returned %i\n", err);
+#endif
+          goto out;
+        }
+      t_dentry = path.dentry;
+      if (!t_dentry->d_inode)
+        {
+          err = -RSBAC_EINVALIDTARGET;
+          goto out_dput;
+        }
+        
+      switch (target)
+        {
+          case T_FD:
+            if(S_ISREG(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISDIR(t_dentry->d_inode->i_mode))
+              {
+                target = T_DIR;
+              }
+            else
+            if(S_ISLNK(t_dentry->d_inode->i_mode))
+              {
+                target = T_SYMLINK;
+              }
+            else
+            if(S_ISFIFO(t_dentry->d_inode->i_mode))
+              {
+                target = T_FIFO;
+              }
+            else
+            if(S_ISSOCK(t_dentry->d_inode->i_mode))
+              {
+                target = T_UNIXSOCK;
+              }
+            else
+            if(S_ISBLK(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+            if(S_ISCHR(t_dentry->d_inode->i_mode))
+              {
+                target = T_FILE;
+              }
+            else
+              {
+#ifdef CONFIG_RSBAC_DEBUG
+                if (rsbac_debug_aef)
+                  rsbac_printk(KERN_DEBUG "sys_rsbac_rc_get_eff_rights_n(): no filesystem object\n");
+#endif
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FILE:
+            /* is inode of type file, symlink or block/char device? */
+            if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              { /* This is no file or device */
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DIR:
+            if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+              { /* This is no file */
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_FIFO:
+            /* is inode of type fifo? */
+            if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+              { /* This is no file or device */
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_UNIXSOCK:
+            /* is inode of type fifo? */
+            if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+              {
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_SYMLINK:
+            /* is inode of type symlink? */
+            if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+              { /* This is no file or device */
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          case T_DEV:
+            /* is inode of type block/char device? */
+            if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+              { /* This is no dev */
+                err = -RSBAC_EINVALIDTARGET;
+                goto out_dput;
+              }
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDTARGET;
+            goto out_dput;
+        }
+
+      if(target == T_DEV)
+        {
+          if(S_ISBLK(t_dentry->d_inode->i_mode))
+            tid.dev.type = D_block;
+          else
+            tid.dev.type = D_char;
+          tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+          tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+        }
+      else
+        {
+          /* fill target id and call internal function */
+          tid.file.device = t_dentry->d_sb->s_dev;
+          tid.file.inode  = t_dentry->d_inode->i_ino;
+          tid.file.dentry_p = t_dentry;
+        }
+      err = rsbac_rc_sys_get_eff_rights(ta_number, target, tid, &k_req_vec, &k_ttl);
+      /* put result value to user space */
+      if(!err)
+        {
+          err = rsbac_put_user(&k_req_vec, request_vector_p, sizeof(k_req_vec) );
+          if(!err && ttl_p)
+            err = rsbac_put_user(&k_ttl, ttl_p, sizeof(k_ttl) );
+        }
+
+  out_dput:
+      path_put(&path);
+
+  out:
+      return err;
+  }
+
+/* Get current process role */
+int sys_rsbac_rc_get_current_role (rsbac_rc_role_id_t __user * role_p)
+  {
+    rsbac_rc_role_id_t k_role;
+    int err;
+
+    if(!role_p)
+      return -RSBAC_EINVALIDPOINTER;
+    /* call rc function and return its result */
+    err = rsbac_rc_sys_get_current_role(&k_role);
+    if(!err)
+      {
+        err = rsbac_put_user(&k_role, role_p, sizeof(k_role) );
+      }
+    return err;
+  }
+
+int sys_rsbac_rc_select_fd_create_type(rsbac_rc_type_id_t type)
+{
+	int err;
+
+	err = rsbac_rc_select_fd_create_type(type);
+
+	return err;
+}
+#endif
+
+/************** AUTH ***************/
+
+#ifdef CONFIG_RSBAC_AUTH
+/* Provide means for adding and removing of capabilities */
+int sys_rsbac_auth_add_p_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_upid_t upid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range,
+         rsbac_time_t ttl)
+  {
+    rsbac_pid_t pid;
+
+    if(cap_type >= ACT_none)
+      return -RSBAC_EINVALIDTARGET;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(cap_range.first) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.first = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.first));
+    else
+      if (   (RSBAC_UID_SET(cap_range.first) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.first) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+    if (RSBAC_UID_SET(cap_range.last) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.last = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.last));
+    else
+      if (   (RSBAC_UID_SET(cap_range.last) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.last) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+#else
+    cap_range.first = RSBAC_UID_NUM(cap_range.first);
+    cap_range.last = RSBAC_UID_NUM(cap_range.last);
+#endif
+
+    if(cap_range.first > cap_range.last)
+      return -RSBAC_EINVALIDVALUE;
+    if(   (RSBAC_UID_NUM(cap_range.first) > RSBAC_AUTH_MAX_RANGE_UID)
+       || (RSBAC_UID_NUM(cap_range.last) > RSBAC_AUTH_MAX_RANGE_UID)
+      )
+      return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_auth_add_p_cap(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    pid = find_pid_ns(upid, &init_pid_ns);
+    if(!pid)
+      return -RSBAC_EINVALIDTARGET;
+
+    /* call auth function and return its result */
+    /* permission checking is done there */
+    return rsbac_auth_add_p_cap(ta_number, pid, cap_type, cap_range, ttl);
+  }
+
+int sys_rsbac_auth_remove_p_cap(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_upid_t upid,
+  enum   rsbac_auth_cap_type_t cap_type,
+  struct rsbac_auth_cap_range_t cap_range)
+  {
+    rsbac_pid_t pid;
+
+    if(cap_type >= ACT_none)
+      return -RSBAC_EINVALIDTARGET;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(cap_range.first) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.first = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.first));
+    else
+      if (   (RSBAC_UID_SET(cap_range.first) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.first) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+    if (RSBAC_UID_SET(cap_range.last) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.last = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.last));
+    else
+      if (   (RSBAC_UID_SET(cap_range.last) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.last) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+#else
+    cap_range.first = RSBAC_UID_NUM(cap_range.first);
+    cap_range.last = RSBAC_UID_NUM(cap_range.last);
+#endif
+    if(cap_range.first > cap_range.last)
+      return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_auth_remove_p_cap(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    pid = find_pid_ns(upid, &init_pid_ns);
+    if(!pid)
+      return -RSBAC_EINVALIDTARGET;
+    /* call auth function and return its result */
+    /* permission checking is done there */
+    return rsbac_auth_remove_p_cap(ta_number, pid, cap_type, cap_range);
+  }
+
+int sys_rsbac_auth_add_f_cap(
+         rsbac_list_ta_number_t   ta_number,
+         char                  __user * filename,
+  enum   rsbac_auth_cap_type_t    cap_type,
+  struct rsbac_auth_cap_range_t   cap_range,
+         rsbac_time_t             ttl)
+  {
+    struct dentry * t_dentry;
+    int     err = 0;
+    enum  rsbac_target_t     target;
+    union rsbac_target_id_t  tid;
+#if defined(CONFIG_RSBAC_AUTH)
+    union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+    struct path path;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(cap_range.first) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.first = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.first));
+    else
+      if (   (RSBAC_UID_SET(cap_range.first) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.first) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+    if (RSBAC_UID_SET(cap_range.last) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.last = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.last));
+    else
+      if (   (RSBAC_UID_SET(cap_range.last) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.last) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+#else
+    cap_range.first = RSBAC_UID_NUM(cap_range.first);
+    cap_range.last = RSBAC_UID_NUM(cap_range.last);
+#endif
+    if(cap_range.first > cap_range.last)
+      return -RSBAC_EINVALIDVALUE;
+
+    if(!filename)
+      return -RSBAC_EINVALIDTARGET;
+    if(cap_type >= ACT_none)
+      return -RSBAC_EINVALIDTARGET;
+    if(cap_range.first > cap_range.last)
+      return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_auth_add_f_cap(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    if ((err = user_lpath(filename, &path)))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_auth)
+          rsbac_printk(KERN_DEBUG "sys_rsbac_auth_add_f_cap(): call to user_lpath() returned %i\n", err);
+#endif
+        goto out;
+      }
+    t_dentry = path.dentry;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file? */
+    if(S_ISREG(t_dentry->d_inode->i_mode))
+      target = T_FILE;
+    else
+    if(S_ISDIR(t_dentry->d_inode->i_mode))
+      target = T_DIR;
+    else
+      { /* This is no file or dir */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    tid.file.device = t_dentry->d_sb->s_dev;
+    tid.file.inode  = t_dentry->d_inode->i_ino;
+    tid.file.dentry_p = t_dentry;
+#if defined(CONFIG_RSBAC_AUTH)
+    /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      rsbac_printk(KERN_DEBUG "sys_rsbac_auth_add_f_cap(): calling ADF\n");
+#endif
+    rsbac_attribute_value.auth_cap_range = cap_range;
+    if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                           task_pid(current),
+                           target,
+                           tid,
+                           A_auth_add_f_cap,
+                           rsbac_attribute_value))
+      {
+        err = -EPERM;
+      }
+    else
+#endif
+      err = rsbac_auth_add_f_cap(ta_number, tid.file, cap_type, cap_range, ttl);
+
+out_dput:
+    path_put(&path);
+out:
+    return err;
+  }
+
+int sys_rsbac_auth_remove_f_cap(
+         rsbac_list_ta_number_t   ta_number,
+         char                  __user * filename,
+  enum   rsbac_auth_cap_type_t    cap_type,
+  struct rsbac_auth_cap_range_t   cap_range)
+  {
+    struct dentry * t_dentry;
+    int     err = 0;
+    enum  rsbac_target_t     target;
+    union rsbac_target_id_t  tid;
+
+    /* for adf_request */
+#if defined(CONFIG_RSBAC_AUTH)
+    union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+    struct path path;
+
+    if(!filename)
+      return -RSBAC_EINVALIDTARGET;
+    if(cap_type >= ACT_none)
+      return -RSBAC_EINVALIDTARGET;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(cap_range.first) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.first = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.first));
+    else
+      if (   (RSBAC_UID_SET(cap_range.first) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.first) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+    if (RSBAC_UID_SET(cap_range.last) == RSBAC_UM_VIRTUAL_KEEP)
+      cap_range.last = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(cap_range.last));
+    else
+      if (   (RSBAC_UID_SET(cap_range.last) > RSBAC_UM_VIRTUAL_MAX)
+          && (RSBAC_UID_SET(cap_range.last) != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+#else
+    cap_range.first = RSBAC_UID_NUM(cap_range.first);
+    cap_range.last = RSBAC_UID_NUM(cap_range.last);
+#endif
+    if(cap_range.first > cap_range.last)
+      return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_FREEZE
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_auth_remove_f_cap(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+    if ((err = user_lpath(filename, &path)))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_auth)
+          rsbac_printk(KERN_DEBUG "sys_rsbac_auth_remove_f_cap(): call to user_lpath() returned %i\n", err);
+#endif
+        goto out;
+      }
+    t_dentry = path.dentry;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file or dir? */
+    if(S_ISREG(t_dentry->d_inode->i_mode))
+      target = T_FILE;
+    else
+    if(S_ISDIR(t_dentry->d_inode->i_mode))
+      target = T_DIR;
+    else
+      { /* This is no file or dir */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    tid.file.device = t_dentry->d_sb->s_dev;
+    tid.file.inode  = t_dentry->d_inode->i_ino;
+    tid.file.dentry_p = t_dentry;
+#if defined(CONFIG_RSBAC_AUTH)
+    /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_auth_add_f_cap(): calling ADF\n");
+#endif
+    rsbac_attribute_value.auth_cap_range = cap_range;
+    if (!rsbac_adf_request(R_MODIFY_ATTRIBUTE,
+                           task_pid(current),
+                           target,
+                           tid,
+                           A_auth_remove_f_cap,
+                           rsbac_attribute_value))
+      {
+        err = -EPERM;
+      }
+    else
+#endif
+      err = rsbac_auth_remove_f_cap(ta_number, tid.file, cap_type, cap_range);
+
+out_dput:
+    path_put(&path);
+out:
+    return err;
+  }
+
+/* caplist must have space for maxnum auth_cap_range entries - first and last each! */
+int sys_rsbac_auth_get_f_caplist(
+         rsbac_list_ta_number_t   ta_number,
+         char                  __user * filename,
+  enum   rsbac_auth_cap_type_t    cap_type,
+  struct rsbac_auth_cap_range_t  __user caplist[],
+         rsbac_time_t            __user ttllist[],
+         u_int                    maxnum)
+  {
+    struct dentry * t_dentry;
+    int     err = 0, tmperr = 0;
+    enum  rsbac_target_t     target;
+    union rsbac_target_id_t  tid;
+    struct rsbac_auth_cap_range_t * k_caplist;
+    rsbac_time_t * k_ttllist;
+
+    /* for adf_request */
+#if defined(CONFIG_RSBAC_AUTH)
+    union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+    struct path path;
+
+    if(!filename)
+      return -RSBAC_EINVALIDTARGET;
+    if(cap_type >= ACT_none)
+      return -RSBAC_EINVALIDTARGET;
+    if(!caplist)
+      return -RSBAC_EINVALIDPOINTER;
+    if(maxnum <= 0)
+      return -RSBAC_EINVALIDVALUE;
+    if(maxnum > RSBAC_AUTH_MAX_MAXNUM)
+      maxnum = RSBAC_AUTH_MAX_MAXNUM;
+
+    if ((err = user_lpath(filename, &path)))
+      {
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_auth)
+          rsbac_printk(KERN_DEBUG "sys_rsbac_auth_get_f_caplist(): call to user_lpath() returned %i\n", err);
+#endif
+        goto out;
+      }
+    t_dentry = path.dentry;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file or dir? */
+    if(S_ISREG(t_dentry->d_inode->i_mode))
+      target = T_FILE;
+    else
+    if(S_ISDIR(t_dentry->d_inode->i_mode))
+      target = T_DIR;
+    else
+      { /* This is no file or dir */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    tid.file.device = t_dentry->d_sb->s_dev;
+    tid.file.inode  = t_dentry->d_inode->i_ino;
+    tid.file.dentry_p = t_dentry;
+#if defined(CONFIG_RSBAC_AUTH)
+    /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_auth_get_f_caplist(): calling ADF\n");
+#endif
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_READ_ATTRIBUTE,
+                           task_pid(current),
+                           target,
+                           tid,
+                           A_auth_get_caplist,
+                           rsbac_attribute_value))
+      {
+        err = -EPERM;
+        goto out_dput;
+      }
+#endif
+    err = rsbac_auth_get_f_caplist(ta_number, tid.file, cap_type, &k_caplist, &k_ttllist);
+    if(err>0)
+      {
+        if(err > maxnum)
+          err = maxnum;
+        tmperr = rsbac_put_user(k_caplist, caplist,
+                                sizeof(struct rsbac_auth_cap_range_t) * err);
+        if(tmperr < 0)
+          err = tmperr;
+        else
+          {
+            if(ttllist)
+              {
+                tmperr = rsbac_put_user(k_ttllist, ttllist,
+                                        sizeof(rsbac_time_t) * err);
+                if(tmperr < 0)
+                  err = tmperr;
+              }
+          }
+        rsbac_kfree(k_caplist);
+        rsbac_kfree(k_ttllist);
+      }
+
+out_dput:
+    path_put(&path);
+out:
+    return err;
+  }
+
+int sys_rsbac_auth_get_p_caplist(
+         rsbac_list_ta_number_t ta_number,
+         rsbac_upid_t           upid,
+  enum   rsbac_auth_cap_type_t  cap_type,
+  struct rsbac_auth_cap_range_t __user caplist[],
+         rsbac_time_t           __user ttllist[],
+         u_int                  maxnum)
+  {
+    int     err = 0, tmperr = 0;
+    union rsbac_target_id_t  tid;
+    struct rsbac_auth_cap_range_t * k_caplist;
+    rsbac_time_t * k_ttllist;
+
+    /* for adf_request */
+#if defined(CONFIG_RSBAC_AUTH)
+    union rsbac_attribute_value_t rsbac_attribute_value;
+#endif
+
+    if(!upid)
+      return -RSBAC_EINVALIDTARGET;
+    if(cap_type >= ACT_none)
+      return -RSBAC_EINVALIDVALUE;
+    if(!caplist)
+      return -RSBAC_EINVALIDPOINTER;
+    if(maxnum <= 0)
+      return -RSBAC_EINVALIDVALUE;
+    if(maxnum > RSBAC_AUTH_MAX_MAXNUM)
+      maxnum = RSBAC_AUTH_MAX_MAXNUM;
+
+    tid.process = find_pid_ns(upid, &init_pid_ns);
+    if (!tid.process)
+      return -RSBAC_EINVALIDTARGET;
+#if defined(CONFIG_RSBAC_AUTH)
+    /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef) rsbac_printk(KERN_DEBUG "sys_rsbac_auth_get_p_caplist(): calling ADF\n");
+#endif
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_READ_ATTRIBUTE,
+                           task_pid(current),
+                           T_PROCESS,
+                           tid,
+                           A_auth_get_caplist,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+#endif
+    err = rsbac_auth_get_p_caplist(ta_number, tid.process, cap_type,
+                                   &k_caplist, &k_ttllist);
+    if(err>0)
+      {
+        if(err > maxnum)
+          err = maxnum;
+        tmperr = rsbac_put_user(k_caplist, caplist,
+                                sizeof(struct rsbac_auth_cap_range_t) * err);
+        if(tmperr < 0)
+          err = tmperr;
+        else
+          {
+            if(ttllist)
+              {
+                tmperr = rsbac_put_user(k_ttllist, ttllist,
+                                        sizeof(rsbac_time_t) * err);
+                if(tmperr < 0)
+                  err = tmperr;
+              }
+          }
+        rsbac_kfree(k_caplist);
+        rsbac_kfree(k_ttllist);
+      }
+
+    return err;
+  }
+#endif
+
+/**********************************/
+/************** REG ***************/
+
+#ifdef CONFIG_RSBAC_REG
+int sys_rsbac_reg(rsbac_reg_handle_t handle,
+                             void __user * arg)
+  {
+    return rsbac_reg_syscall(handle, arg);
+  }
+#endif
+
+/**********************************/
+/************** ACL ***************/
+
+#ifdef CONFIG_RSBAC_ACL
+int sys_rsbac_acl(
+         rsbac_list_ta_number_t     ta_number,
+  enum   rsbac_acl_syscall_type_t   call,
+  struct rsbac_acl_syscall_arg_t __user * arg)
+    { 
+      struct rsbac_acl_syscall_arg_t k_arg;
+      int   err = 0;
+      
+      if(call >= ACLC_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(!arg)
+        return -RSBAC_EINVALIDPOINTER;
+
+      /* get values from user space */
+      err = rsbac_get_user(&k_arg, arg, sizeof(k_arg));
+      if(err < 0)
+        return err;
+
+      if(k_arg.target >= T_NONE)
+        return -RSBAC_EINVALIDTARGET;
+/*      rsbac_printk(KERN_DEBUG "sys_rsbac_acl(): target = %u, call = %u, subj_type = %u, subj_id = %u!\n",
+             k_arg.target, call, k_arg.subj_type, k_arg.subj_id); */
+
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_acl(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+      if(call != ACLC_set_mask)
+        {
+          switch(k_arg.subj_type)
+            {
+              case ACLS_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                if (RSBAC_UID_SET(k_arg.subj_id) == RSBAC_UM_VIRTUAL_KEEP)
+                  k_arg.subj_id = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_arg.subj_id));
+                else
+                  if (RSBAC_UID_SET(k_arg.subj_id) > RSBAC_UM_VIRTUAL_MAX)
+                    return -RSBAC_EINVALIDVALUE;
+#else
+                k_arg.subj_id = RSBAC_UID_NUM(k_arg.subj_id);
+#endif
+                break;
+              case ACLS_GROUP:
+                if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
+                  {
+                    struct rsbac_acl_group_entry_t entry;
+                           rsbac_uid_t caller;
+
+                    if(   rsbac_acl_get_group_entry(ta_number, k_arg.subj_id, &entry)
+                       || rsbac_get_owner(&caller)
+                       || (   (entry.owner != caller)
+                           && (entry.type != ACLG_GLOBAL)
+                          )
+                      )
+                      return -RSBAC_EINVALIDVALUE;
+                  }
+                break;
+              #if defined(CONFIG_RSBAC_RC)
+              case ACLS_ROLE:
+                if(k_arg.subj_id > RC_role_max_value)
+                  {
+                    rsbac_printk(KERN_DEBUG "sys_rsbac_acl(): Invalid role %u!\n", k_arg.subj_id);
+                    return -RSBAC_EINVALIDVALUE;
+                  }
+                break;
+              #endif
+              default:
+                rsbac_printk(KERN_DEBUG "sys_rsbac_acl(): Invalid subject type %u!\n", k_arg.subj_type);
+                return -RSBAC_EINVALIDVALUE;
+            }
+          if(   (call == ACLC_remove_user)
+             && (k_arg.target != T_USER)
+            )
+            return -RSBAC_EINVALIDTARGET;
+          
+        }
+        
+      /* call acl function */
+      switch(call)
+        {
+          case ACLC_set_acl_entry:
+            err = rsbac_acl_sys_set_acl_entry(ta_number,
+                                              k_arg.target,
+                                              k_arg.tid,
+                                              k_arg.subj_type,
+                                              k_arg.subj_id,
+                                              k_arg.rights,
+                                              k_arg.ttl);
+            break;
+          case ACLC_remove_acl_entry:
+            err = rsbac_acl_sys_remove_acl_entry(ta_number,
+                                                 k_arg.target,
+                                                 k_arg.tid,
+                                                 k_arg.subj_type,
+                                                 k_arg.subj_id);
+            break;
+          case ACLC_remove_acl:
+            err = rsbac_acl_sys_remove_acl(ta_number,
+                                           k_arg.target,
+                                           k_arg.tid);
+            break;
+          case ACLC_add_to_acl_entry:
+            err = rsbac_acl_sys_add_to_acl_entry(ta_number,
+                                                 k_arg.target,
+                                                 k_arg.tid,
+                                                 k_arg.subj_type,
+                                                 k_arg.subj_id,
+                                                 k_arg.rights,
+                                                 k_arg.ttl);
+            break;
+          case ACLC_remove_from_acl_entry:
+            err = rsbac_acl_sys_remove_from_acl_entry(ta_number,
+                                                      k_arg.target,
+                                                      k_arg.tid,
+                                                      k_arg.subj_type,
+                                                      k_arg.subj_id,
+                                                      k_arg.rights);
+            break;
+          case ACLC_set_mask:
+            err = rsbac_acl_sys_set_mask(ta_number,
+                                         k_arg.target,
+                                         k_arg.tid,
+                                         k_arg.rights);
+            break;
+          case ACLC_remove_user:
+            err = rsbac_acl_sys_remove_user(ta_number,
+                                            k_arg.tid.user);
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDREQUEST;
+        }
+      return err;
+    }      /* end of sys_rsbac_acl() */
+
+
+int sys_rsbac_acl_n(
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_acl_syscall_type_t    call,
+  struct rsbac_acl_syscall_n_arg_t __user * arg)
+    {
+      struct dentry * t_dentry = NULL;
+      int     err = 0;
+      union rsbac_target_id_t  tid;
+      struct rsbac_acl_syscall_n_arg_t k_arg;
+
+      struct path path;
+
+      if(call >= ACLC_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(!arg)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_acl_n(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+      /* get values from user space */
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+      if((task_thread_info(current)->status & TS_COMPAT) || test_thread_flag(TIF_IA32)) {
+        struct rsbac_acl_syscall_n_arg_ia32_t k_arg_ia32;
+
+        err = rsbac_get_user(&k_arg_ia32, arg, sizeof(k_arg_ia32) );
+        if(err < 0)
+          return err;
+        memset(&k_arg, 0, sizeof(k_arg));
+        k_arg.target = k_arg_ia32.target;
+        k_arg.name = (void __user *)(long)k_arg_ia32.name;
+        k_arg.subj_type = k_arg_ia32.subj_type;
+        k_arg.subj_id = k_arg_ia32.subj_id;
+        k_arg.rights = k_arg_ia32.rights;
+        k_arg.ttl = k_arg_ia32.ttl;
+      } else {
+#endif
+        err = rsbac_get_user(&k_arg, arg, sizeof(k_arg) );
+        if(err < 0)
+          return err;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+      }
+#endif
+
+      if(k_arg.target >= T_NONE)
+        return -RSBAC_EINVALIDTARGET;
+      if(call != ACLC_set_mask)
+        {
+          switch(k_arg.subj_type)
+            {
+              case ACLS_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                if (RSBAC_UID_SET(k_arg.subj_id) == RSBAC_UM_VIRTUAL_KEEP)
+                  k_arg.subj_id = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_arg.subj_id));
+                else
+                  if (RSBAC_UID_SET(k_arg.subj_id) > RSBAC_UM_VIRTUAL_MAX)
+                    return -RSBAC_EINVALIDVALUE;
+#else
+                k_arg.subj_id = RSBAC_UID_NUM(k_arg.subj_id);
+#endif
+                break;
+              case ACLS_GROUP:
+                if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
+                  {
+                    struct rsbac_acl_group_entry_t entry;
+                           rsbac_uid_t caller;
+
+                    if(   rsbac_acl_get_group_entry(ta_number, k_arg.subj_id, &entry)
+                       || rsbac_get_owner(&caller)
+                       || (   (entry.owner != caller)
+                           && (entry.type != ACLG_GLOBAL)
+                          )
+                      )
+                      return -RSBAC_EINVALIDVALUE;
+                  }
+                break;
+              #if defined(CONFIG_RSBAC_RC)
+              case ACLS_ROLE:
+                if(k_arg.subj_id > RC_role_max_value)
+                  return -RSBAC_EINVALIDVALUE;
+                break;
+              #endif
+              default:
+                return -RSBAC_EINVALIDVALUE;
+            }
+        }
+        
+      if(k_arg.name)
+        {
+          /* lookup filename */
+          if ((err = user_lpath(k_arg.name, &path)))
+            {
+#ifdef CONFIG_RSBAC_DEBUG
+              if (rsbac_debug_aef)
+                rsbac_printk(KERN_DEBUG "sys_rsbac_acl_n(): call to user_lpath() returned %i\n", err);
+#endif
+              goto out;
+            }
+          t_dentry = path.dentry;
+          if (!t_dentry->d_inode)
+            {
+#ifdef CONFIG_RSBAC_DEBUG
+              if (rsbac_debug_aef)
+                rsbac_printk(KERN_DEBUG "sys_rsbac_acl_n(): file not found\n");
+#endif
+              err = -RSBAC_EINVALIDTARGET;
+              goto out_dput;
+            }
+          tid.file.device = t_dentry->d_sb->s_dev;
+          tid.file.inode  = t_dentry->d_inode->i_ino;
+          tid.file.dentry_p = t_dentry;
+        }
+      else
+        {
+          tid.file.device = RSBAC_ZERO_DEV;
+          tid.file.inode  = 0;
+          tid.file.dentry_p = NULL;
+        }
+
+      switch (k_arg.target)
+        {
+          case T_FD:
+            if(k_arg.name)
+              {
+                if(S_ISREG(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_FILE;
+                  }
+                else
+                if(S_ISDIR(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_DIR;
+                  }
+                else
+                if(S_ISLNK(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_SYMLINK;
+                  }
+                else
+                if(S_ISFIFO(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_FIFO;
+                  }
+                else
+                if(S_ISSOCK(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_UNIXSOCK;
+                  }
+                else
+                if(S_ISBLK(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_FILE;
+                  }
+                else
+                if(S_ISCHR(t_dentry->d_inode->i_mode))
+                  {
+                    k_arg.target = T_FILE;
+                  }
+                else
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_n(): no filesystem object\n");
+#endif
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+              }
+            else
+              k_arg.target = T_FILE;
+            break;
+
+          case T_FILE:
+            if(k_arg.name)
+              {
+                /* is inode of type file, symlink or block/char device? */
+                if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                    && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+              }
+            break;
+
+          case T_DIR:
+            if(k_arg.name)
+              {
+                if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+                  { /* This is no dir */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+              }
+            break;
+
+          case T_FIFO:
+            if(k_arg.name)
+              {
+                /* is inode of type fifo? */
+                if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+              }
+            break;
+
+          case T_UNIXSOCK:
+            if(k_arg.name)
+              {
+                /* is inode of type fifo? */
+                if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+              }
+            break;
+
+          case T_SYMLINK:
+            if(k_arg.name)
+              {
+                /* is inode of type symlink? */
+                if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+              }
+            break;
+
+          case T_DEV:
+            if(k_arg.name)
+              {
+                /* is inode of type block/char device? */
+                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* fill target id and call internal function */
+                if(S_ISBLK(t_dentry->d_inode->i_mode))
+                  tid.dev.type = D_block;
+                else
+                  tid.dev.type = D_char;
+                tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+                tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+              }
+            else
+              {
+                tid.dev = RSBAC_ZERO_DEV_DESC;
+              }
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDTARGET;
+            goto out_dput;
+        }
+      /* call acl function */
+      switch(call)
+        {
+          case ACLC_set_acl_entry:
+            err = rsbac_acl_sys_set_acl_entry(ta_number,
+                                              k_arg.target,
+                                              tid,
+                                              k_arg.subj_type,
+                                              k_arg.subj_id,
+                                              k_arg.rights,
+                                              k_arg.ttl);
+            break;
+          case ACLC_remove_acl_entry:
+            err = rsbac_acl_sys_remove_acl_entry(ta_number,
+                                                 k_arg.target,
+                                                 tid,
+                                                 k_arg.subj_type,
+                                                 k_arg.subj_id);
+            break;
+          case ACLC_remove_acl:
+            err = rsbac_acl_sys_remove_acl(ta_number,
+                                           k_arg.target,
+                                           tid);
+            break;
+          case ACLC_add_to_acl_entry:
+            err = rsbac_acl_sys_add_to_acl_entry(ta_number,
+                                                 k_arg.target,
+                                                 tid,
+                                                 k_arg.subj_type,
+                                                 k_arg.subj_id,
+                                                 k_arg.rights,
+                                                 k_arg.ttl);
+            break;
+          case ACLC_remove_from_acl_entry:
+            err = rsbac_acl_sys_remove_from_acl_entry(ta_number,
+                                                      k_arg.target,
+                                                      tid,
+                                                      k_arg.subj_type,
+                                                      k_arg.subj_id,
+                                                      k_arg.rights);
+            break;
+          case ACLC_set_mask:
+            err = rsbac_acl_sys_set_mask(ta_number,
+                                         k_arg.target,
+                                         tid,
+                                         k_arg.rights);
+            break;
+
+          default:
+            err = -RSBAC_EINVALIDREQUEST;
+        }
+
+out_dput:
+      if(k_arg.name)
+        {
+          path_put(&path);
+        }
+
+out:
+      return err;
+    }      /* end of sys_rsbac_acl_n() */
+
+/************************************************************************** */
+
+int sys_rsbac_acl_get_rights(
+         rsbac_list_ta_number_t      ta_number,
+  struct rsbac_acl_syscall_arg_t   __user * arg,
+         rsbac_acl_rights_vector_t __user * rights_p,
+         u_int                       effective)
+    { 
+      struct rsbac_acl_syscall_arg_t k_arg;
+      rsbac_acl_rights_vector_t k_rights = 0;
+      int   err = 0;
+      
+      if(!arg || !rights_p)
+        return -RSBAC_EINVALIDPOINTER;
+      /* get values from user space */
+      rsbac_get_user(&k_arg, arg, sizeof(k_arg) );
+
+      if(k_arg.target >= T_NONE)
+        return -RSBAC_EINVALIDTARGET;
+/*      printk(KERN_DEBUG "sys_rsbac_acl_get_rights(): target = %u, subj_type = %u, subj_id = %u!\n",
+             k_arg.target, k_arg.subj_type, k_arg.subj_id); */
+      switch(k_arg.subj_type)
+        {
+          case ACLS_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(k_arg.subj_id) == RSBAC_UM_VIRTUAL_KEEP)
+              k_arg.subj_id = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_arg.subj_id));
+            else
+              if (RSBAC_UID_SET(k_arg.subj_id) > RSBAC_UM_VIRTUAL_MAX)
+                return -RSBAC_EINVALIDVALUE;
+#else
+            k_arg.subj_id = RSBAC_UID_NUM(k_arg.subj_id);
+#endif
+            break;
+          case ACLS_GROUP:
+            if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
+              {
+                struct rsbac_acl_group_entry_t entry;
+                       rsbac_uid_t caller;
+
+                if(   rsbac_acl_get_group_entry(ta_number, k_arg.subj_id, &entry)
+                   || rsbac_get_owner(&caller)
+                   || (   (entry.owner != caller)
+                       && (entry.type != ACLG_GLOBAL)
+                      )
+                  )
+                  return -RSBAC_EINVALIDVALUE;
+              }
+            break;
+          case ACLS_ROLE:
+          #if defined(CONFIG_RSBAC_RC)
+            if(k_arg.subj_id > RC_role_max_value)
+              return -RSBAC_EINVALIDVALUE;
+          #endif
+            break;
+          default:
+            rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_rights(): Invalid subject type %u!\n", k_arg.subj_type);
+            return -RSBAC_EINVALIDVALUE;
+        }
+
+      /* call acl function */
+      err = rsbac_acl_sys_get_rights(ta_number,
+                                     k_arg.target,
+                                     k_arg.tid,
+                                     k_arg.subj_type,
+                                     k_arg.subj_id,
+                                     &k_rights,
+                                     effective);
+      if(!err)
+        {
+          err = rsbac_put_user(&k_rights, rights_p, sizeof(k_rights) );
+        }
+      return err;
+    }      /* end of sys_rsbac_acl_get_rights() */
+
+
+int sys_rsbac_acl_get_rights_n(
+         rsbac_list_ta_number_t      ta_number,
+  struct rsbac_acl_syscall_n_arg_t __user * arg,
+         rsbac_acl_rights_vector_t __user * rights_p,
+         u_int                       effective)
+    {
+      struct dentry * t_dentry = NULL;
+      rsbac_boolean_t need_put = FALSE;
+      int     err = 0;
+      union rsbac_target_id_t  tid;
+      struct rsbac_acl_syscall_n_arg_t k_arg;
+      rsbac_acl_rights_vector_t k_rights = 0;
+     
+      struct path path;
+
+      if(!arg || !rights_p)
+        return -RSBAC_EINVALIDPOINTER;
+      /* get values from user space */
+      rsbac_get_user(&k_arg, arg, sizeof(k_arg) );
+
+      if(k_arg.target >= T_NONE)
+        return -RSBAC_EINVALIDTARGET;
+      switch(k_arg.subj_type)
+        {
+          case ACLS_USER:
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+            if (RSBAC_UID_SET(k_arg.subj_id) == RSBAC_UM_VIRTUAL_KEEP)
+              k_arg.subj_id = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(k_arg.subj_id));
+            else
+              if (RSBAC_UID_SET(k_arg.subj_id) > RSBAC_UM_VIRTUAL_MAX)
+                return -RSBAC_EINVALIDVALUE;
+#else
+            k_arg.subj_id = RSBAC_UID_NUM(k_arg.subj_id);
+#endif
+            break;
+          case ACLS_GROUP:
+            if(k_arg.subj_id != RSBAC_ACL_GROUP_EVERYONE)
+              {
+                struct rsbac_acl_group_entry_t entry;
+                       rsbac_uid_t caller;
+
+                if(   rsbac_acl_get_group_entry(ta_number, k_arg.subj_id, &entry)
+                   || rsbac_get_owner(&caller)
+                   || (   (entry.owner != caller)
+                       && (entry.type != ACLG_GLOBAL)
+                      )
+                  )
+                  return -RSBAC_EINVALIDVALUE;
+              }
+            break;
+          case ACLS_ROLE:
+          #if defined(CONFIG_RSBAC_RC)
+            if(k_arg.subj_id > RC_role_max_value)
+              return -RSBAC_EINVALIDVALUE;
+          #endif
+            break;
+          default:
+            return -RSBAC_EINVALIDVALUE;
+        }
+        
+      switch (k_arg.target)
+        {
+          case T_FD:
+          case T_FILE:
+          case T_DIR:
+          case T_FIFO:
+          case T_UNIXSOCK:
+          case T_SYMLINK:
+            if(k_arg.name)
+              {
+                if ((err = user_lpath(k_arg.name, &path)))
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef_acl)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_lpath() returned %i\n", err);
+#endif
+                    goto out;
+                   }
+                t_dentry = path.dentry;
+                need_put = TRUE;
+                if (!t_dentry->d_inode)
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* is inode of type file, symlink or block/char device? */
+                switch(k_arg.target)
+                  {
+                    case T_FD:
+                      if(S_ISREG(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_FILE;
+                        }
+                      else
+                      if(S_ISDIR(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_DIR;
+                        }
+                      else
+                      if(S_ISLNK(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_SYMLINK;
+                        }
+                      else
+                      if(S_ISFIFO(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_FIFO;
+                        }
+                      else
+                      if(S_ISSOCK(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_UNIXSOCK;
+                        }
+                      else
+                      if(S_ISBLK(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_FILE;
+                        }
+                      else
+                      if(S_ISCHR(t_dentry->d_inode->i_mode))
+                        {
+                          k_arg.target = T_FILE;
+                        }
+                      else
+                        { /* This is no file or device */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_FILE:
+                      if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                          && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                          && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                        { /* This is no file or device */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_DIR:
+                      if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+                        { /* This is no dir */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_FIFO:
+                      /* is inode of type fifo? */
+                      if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+                        { /* This is no fifo */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_UNIXSOCK:
+                      if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+                        {
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_SYMLINK:
+                      /* is inode of type symlink? */
+                      if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+                        { /* This is no symlink */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    default:
+                      err = -RSBAC_EINVALIDTARGET;
+                      goto out_dput;
+                  }
+                tid.file.device = t_dentry->d_sb->s_dev;
+                tid.file.inode  = t_dentry->d_inode->i_ino;
+                tid.file.dentry_p = t_dentry;
+              }
+            else
+              {
+                if(k_arg.target == T_FD)
+                  k_arg.target = T_FILE;
+                tid.file.device = RSBAC_ZERO_DEV;
+                tid.file.inode  = 0;
+                tid.file.dentry_p = NULL;
+              }
+            break;
+
+          case T_DEV:
+            if(k_arg.name)
+              {
+                if ((err = user_lpath(k_arg.name, &path)))
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef_acl)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_rights_n(): call to user_lpath() returned %i\n", err);
+#endif
+                    goto out;
+                   }
+                t_dentry = path.dentry;
+                need_put = TRUE;
+                if (!t_dentry->d_inode)
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* is inode of type file, symlink or block/char device? */
+                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* fill target id and call internal function */
+                if(S_ISBLK(t_dentry->d_inode->i_mode))
+                  tid.dev.type = D_block;
+                else
+                  tid.dev.type = D_char;
+                tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+                tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+              }
+            else
+              {
+                tid.dev = RSBAC_ZERO_DEV_DESC;
+              }
+            break;
+
+          default:
+            return -RSBAC_EINVALIDTARGET;
+        }
+
+      /* call acl function */
+      err = rsbac_acl_sys_get_rights(ta_number,
+                                     k_arg.target,
+                                     tid,
+                                     k_arg.subj_type,
+                                     k_arg.subj_id,
+                                     &k_rights,
+                                     effective);
+
+out_dput:
+      if(need_put)
+        path_put(&path);
+out:
+      if(!err)
+        {
+          rsbac_put_user(&k_rights, rights_p, sizeof(k_rights) );
+        }
+      return err;
+    }      /* end of sys_rsbac_acl_get_rights_n() */
+
+/************************************************************************** */
+
+int sys_rsbac_acl_get_tlist (
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t  __user * tid,
+  struct rsbac_acl_entry_t  __user   entry_array[],
+         rsbac_time_t       __user   ttl_array[],
+         u_int                       maxnum)
+    { 
+      union  rsbac_target_id_t   k_tid;
+      struct rsbac_acl_entry_t * k_entry_p;
+             rsbac_time_t      * k_ttl_p;
+             int   err = 0;
+
+      if(!tid || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+      if(!entry_array)
+        return -RSBAC_EINVALIDPOINTER;
+      if(!maxnum)
+        return -RSBAC_EINVALIDVALUE;
+      if(maxnum > RSBAC_ACL_MAX_MAXNUM)
+        maxnum = RSBAC_ACL_MAX_MAXNUM;
+
+      /* get values from user space */
+      err = rsbac_get_user(&k_tid, tid, sizeof(k_tid) );
+      if(unlikely(err < 0))
+        return err;
+      switch (target) {
+              case T_FD:
+                      return -RSBAC_EINVALIDTARGET;
+              case T_FILE:
+              case T_DIR:
+              case T_FIFO:
+              case T_UNIXSOCK:
+              case T_SYMLINK:
+                      k_tid.file.dentry_p = NULL;
+                      k_tid.dir.dentry_p = NULL;
+                      break;
+              case T_PROCESS:
+                      k_tid.process = find_pid_ns(k_tid.uprocess, &init_pid_ns);
+                      if(!k_tid.process)
+                        return -RSBAC_EINVALIDTARGET;
+                      break;
+              default:
+                      break;
+      }
+
+      /* call acl function */
+      err = rsbac_acl_sys_get_tlist(ta_number, target, k_tid, &k_entry_p, &k_ttl_p);
+      if(err>0)
+        {
+          if(err > maxnum)
+            err = maxnum;
+          rsbac_put_user(k_entry_p,
+                         entry_array,
+                         err * sizeof(*k_entry_p) );
+          if(ttl_array)
+            {
+              rsbac_put_user(k_ttl_p,
+                             ttl_array,
+                             err * sizeof(*k_ttl_p) );
+            }
+          rsbac_kfree(k_entry_p);
+          rsbac_kfree(k_ttl_p);
+        }
+      return err;
+    }      /* end of sys_rsbac_acl_get_tlist() */
+
+int sys_rsbac_acl_get_tlist_n(
+         rsbac_list_ta_number_t   ta_number,
+  enum   rsbac_target_t           target,
+         char                     __user * t_name,
+  struct rsbac_acl_entry_t        __user entry_array[],
+         rsbac_time_t             __user ttl_array[],
+         u_int                    maxnum)
+    {
+      struct dentry * t_dentry = NULL;
+      struct rsbac_acl_entry_t * k_entry_p;
+      rsbac_time_t * k_ttl_p;
+      rsbac_boolean_t need_put = FALSE;
+      int     err = 0;
+      union rsbac_target_id_t  tid;
+     
+      struct path path;
+        
+      if(target >= T_NONE)
+        return -RSBAC_EINVALIDTARGET;
+      if(!entry_array)
+        return -RSBAC_EINVALIDPOINTER;
+
+      switch (target)
+        {
+          case T_FD:
+          case T_FILE:
+          case T_DIR:
+          case T_FIFO:
+          case T_UNIXSOCK:
+          case T_SYMLINK:
+            if(t_name)
+              {
+                if ((err = user_lpath(t_name, &path)))
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef_acl)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_lpath() returned %i\n", err);
+#endif
+                    goto out;
+                   }
+                t_dentry = path.dentry;
+                need_put = TRUE;
+                if (!t_dentry->d_inode)
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* is inode of type file, symlink or block/char device? */
+                switch(target)
+                  {
+                    case T_FD:
+                      if(S_ISREG(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FILE;
+                        }
+                      else
+                      if(S_ISDIR(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_DIR;
+                        }
+                      else
+                      if(S_ISLNK(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_SYMLINK;
+                        }
+                      else
+                      if(S_ISFIFO(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FIFO;
+                        }
+                      else
+                      if(S_ISSOCK(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_UNIXSOCK;
+                        }
+                      else
+                      if(S_ISBLK(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FILE;
+                        }
+                      else
+                      if(S_ISCHR(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FILE;
+                        }
+                      else
+                        { /* This is no file or device */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_FILE:
+                      if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                          && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                          && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                        { /* This is no file or device */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_DIR:
+                      if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+                        { /* This is no dir */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_FIFO:
+                      /* is inode of type fifo? */
+                      if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+                        { /* This is no fifo */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_UNIXSOCK:
+                      if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+                        {
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_SYMLINK:
+                      /* is inode of type symlink? */
+                      if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+                        { /* This is no symlink */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    default:
+                      err = -RSBAC_EINVALIDTARGET;
+                      goto out_dput;
+                  }
+                tid.file.device = t_dentry->d_sb->s_dev;
+                tid.file.inode  = t_dentry->d_inode->i_ino;
+                tid.file.dentry_p = t_dentry;
+              }
+            else
+              {
+                if(target == T_FD)
+                  target = T_FILE;
+                tid.file.device = RSBAC_ZERO_DEV;
+                tid.file.inode  = 0;
+                tid.file.dentry_p = NULL;
+              }
+            break;
+
+          case T_DEV:
+            if(t_name)
+              {
+                if ((err = user_lpath(t_name, &path)))
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef_acl)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_tlist_n(): call to user_lpath() returned %i\n", err);
+#endif
+                    goto out;
+                   }
+                t_dentry = path.dentry;
+                need_put = TRUE;
+                if (!t_dentry->d_inode)
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* is inode of type file, symlink or block/char device? */
+                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* fill target id and call internal function */
+                if(S_ISBLK(t_dentry->d_inode->i_mode))
+                  tid.dev.type = D_block;
+                else
+                  tid.dev.type = D_char;
+                tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+                tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+              }
+            else
+              {
+                tid.dev = RSBAC_ZERO_DEV_DESC;
+              }
+            break;
+
+          default:
+            return -RSBAC_EINVALIDTARGET;
+        }
+      /* call ACL function */
+      err = rsbac_acl_sys_get_tlist(ta_number, target, tid,
+                                    &k_entry_p, &k_ttl_p);
+
+out_dput:
+      if(need_put)
+        path_put(&path);
+out:
+      if(err>0)
+        {
+          if(err > maxnum)
+            err = maxnum;
+          rsbac_put_user(k_entry_p,
+                         entry_array,
+                         err * sizeof(*k_entry_p) );
+          if(ttl_array)
+            {
+              rsbac_put_user(k_ttl_p,
+                             ttl_array,
+                             err * sizeof(*k_ttl_p) );
+            }
+          rsbac_kfree(k_entry_p);
+          rsbac_kfree(k_ttl_p);
+        }
+      return err;
+    }      /* end of sys_rsbac_acl_get_tlist_n() */
+
+/************************************************************************** */
+
+int sys_rsbac_acl_get_mask (
+         rsbac_list_ta_number_t      ta_number,
+  enum   rsbac_target_t              target,
+  union  rsbac_target_id_t         __user * tid,
+         rsbac_acl_rights_vector_t __user * mask_p)
+    { 
+      union  rsbac_target_id_t k_tid;
+             rsbac_acl_rights_vector_t k_mask;
+             int   err = 0;
+      
+      if(!tid || (target >= T_NONE))
+        return -RSBAC_EINVALIDTARGET;
+      if(!mask_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+      /* get values from user space */
+      rsbac_get_user(&k_tid, tid, sizeof(k_tid) );
+      switch (target) {
+              case T_FD:
+                      return -RSBAC_EINVALIDTARGET;
+              case T_FILE:
+              case T_DIR:
+              case T_FIFO:
+              case T_UNIXSOCK:
+              case T_SYMLINK:
+                      k_tid.file.dentry_p = NULL;
+                      k_tid.dir.dentry_p = NULL;
+                      break;
+              case T_PROCESS:
+                      k_tid.process = find_pid_ns(k_tid.uprocess, &init_pid_ns);
+                      if(!k_tid.process)
+                        return -RSBAC_EINVALIDTARGET;
+                      break;
+              default:
+                      break;
+      }
+      /* call acl function */
+      err = rsbac_acl_sys_get_mask(ta_number, target, k_tid, &k_mask);
+      if(!err)
+        {
+          rsbac_put_user(&k_mask,
+                         mask_p,
+                         sizeof(k_mask) );
+        }
+      return err;
+    }      /* end of sys_rsbac_acl_get_mask() */
+
+int sys_rsbac_acl_get_mask_n(
+       rsbac_list_ta_number_t      ta_number,
+  enum rsbac_target_t              target,
+       char                        __user * t_name,
+       rsbac_acl_rights_vector_t   __user * mask_p)
+    {
+      struct dentry * t_dentry = NULL;
+      rsbac_acl_rights_vector_t k_mask;
+      rsbac_boolean_t need_put = FALSE;
+      int     err = 0;
+      union rsbac_target_id_t  tid;
+
+      struct path path;
+
+      if(target >= T_NONE)
+        return -RSBAC_EINVALIDTARGET;
+      if(!mask_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+      switch (target)
+        {
+          case T_FD:
+          case T_FILE:
+          case T_DIR:
+          case T_FIFO:
+          case T_UNIXSOCK:
+          case T_SYMLINK:
+            if(t_name)
+              {
+                if ((err = user_lpath(t_name, &path)))
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef_acl)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_lpath() returned %i\n", err);
+#endif
+                    goto out;
+                   }
+                t_dentry = path.dentry;
+                need_put = TRUE;
+                if (!t_dentry->d_inode)
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* is inode of type file, symlink or block/char device? */
+                switch(target)
+                  {
+                    case T_FD:
+                      if(S_ISREG(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FILE;
+                        }
+                      else
+                      if(S_ISDIR(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_DIR;
+                        }
+                      else
+                      if(S_ISLNK(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_SYMLINK;
+                        }
+                      else
+                      if(S_ISFIFO(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FIFO;
+                        }
+                      else
+                      if(S_ISSOCK(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_UNIXSOCK;
+                        }
+                      else
+                      if(S_ISBLK(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FILE;
+                        }
+                      else
+                      if(S_ISCHR(t_dentry->d_inode->i_mode))
+                        {
+                          target = T_FILE;
+                        }
+                      else
+                        { /* This is no file or device */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_FILE:
+                      if (   !(S_ISREG(t_dentry->d_inode->i_mode))
+                          && !(S_ISBLK(t_dentry->d_inode->i_mode))
+                          && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                        { /* This is no file or device */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_DIR:
+                      if ( !(S_ISDIR(t_dentry->d_inode->i_mode)) )
+                        { /* This is no dir */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_FIFO:
+                      if (   !(S_ISFIFO(t_dentry->d_inode->i_mode)))
+                        { /* This is no fifo */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_UNIXSOCK:
+                      if (   !(S_ISSOCK(t_dentry->d_inode->i_mode)))
+                        {
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    case T_SYMLINK:
+                      if (   !(S_ISLNK(t_dentry->d_inode->i_mode)))
+                        { /* This is no symlink */
+                          err = -RSBAC_EINVALIDTARGET;
+                          goto out_dput;
+                        }
+                      break;
+                    default:
+                      err = -RSBAC_EINVALIDTARGET;
+                      goto out_dput;
+                  }
+                tid.file.device = t_dentry->d_sb->s_dev;
+                tid.file.inode  = t_dentry->d_inode->i_ino;
+                tid.file.dentry_p = t_dentry;
+              }
+            else
+              {
+                if(target == T_FD)
+                  target = T_FILE;
+                tid.file.device = RSBAC_ZERO_DEV;
+                tid.file.inode  = 0;
+                tid.file.dentry_p = NULL;
+              }
+            break;
+
+          case T_DEV:
+            if(t_name)
+              {
+                if ((err = user_lpath(t_name, &path)))
+                  {
+#ifdef CONFIG_RSBAC_DEBUG
+                    if (rsbac_debug_aef_acl)
+                      rsbac_printk(KERN_DEBUG "sys_rsbac_acl_get_mask_n(): call to user_lpath() returned %i\n", err);
+#endif
+                    goto out;
+                   }
+                t_dentry = path.dentry;
+                need_put = TRUE;
+                if (!t_dentry->d_inode)
+                  {
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* is inode of type block/char device? */
+                if (   !(S_ISBLK(t_dentry->d_inode->i_mode))
+                    && !(S_ISCHR(t_dentry->d_inode->i_mode)) )
+                  { /* This is no file or device */
+                    err = -RSBAC_EINVALIDTARGET;
+                    goto out_dput;
+                  }
+                /* fill target id and call internal function */
+                if(S_ISBLK(t_dentry->d_inode->i_mode))
+                  tid.dev.type = D_block;
+                else
+                  tid.dev.type = D_char;
+                tid.dev.major = RSBAC_MAJOR(t_dentry->d_inode->i_rdev);
+                tid.dev.minor = RSBAC_MINOR(t_dentry->d_inode->i_rdev);
+              }
+            else
+              {
+                tid.dev = RSBAC_ZERO_DEV_DESC;
+              }
+            break;
+
+          default:
+            return -RSBAC_EINVALIDTARGET;
+        }
+      /* call ACL function */
+      err = rsbac_acl_sys_get_mask(ta_number, target, tid, &k_mask);
+
+out_dput:
+      if(need_put)
+        path_put(&path);
+out:
+      if(!err)
+        {
+          rsbac_put_user(&k_mask,
+                         mask_p,
+                         sizeof(k_mask) );
+        }
+      return err;
+    }      /* end of sys_rsbac_acl_get_mask_n() */
+
+/********  ACL groups *********/
+
+int sys_rsbac_acl_group(
+        rsbac_list_ta_number_t           ta_number,
+  enum  rsbac_acl_group_syscall_type_t   call,
+  union rsbac_acl_group_syscall_arg_t __user * arg_p)
+    { 
+      union rsbac_acl_group_syscall_arg_t k_arg;
+      int   err = 0;
+
+      if(call >= ACLGS_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(!arg_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          switch(call)
+            {
+              case ACLGS_add_group:
+              case ACLGS_change_group:
+              case ACLGS_remove_group:
+              case ACLGS_add_member:
+              case ACLGS_remove_member:
+                rsbac_printk(KERN_WARNING
+                             "sys_rsbac_acl_group(): RSBAC configuration frozen, no administration allowed!\n");
+                return -EPERM;
+
+              default:
+                break;
+            }
+        }
+#endif
+
+      /* get values from user space */
+      err = rsbac_get_user(&k_arg, arg_p, sizeof(k_arg) );
+
+      /* call acl function */
+      if(err >= 0)
+        err = rsbac_acl_sys_group(ta_number, call, k_arg);
+      return err;
+    }      /* end of sys_rsbac_acl() */
+
+int sys_rsbac_acl_list_all_dev(
+  rsbac_list_ta_number_t ta_number,
+  struct rsbac_dev_desc_t __user * id_p,
+  u_long maxnum)
+  {
+    int err = 0;
+    long count;
+    long count2;
+
+    if(id_p && maxnum)
+      {
+        struct rsbac_dev_desc_t * k_id_p = NULL;
+
+        count = rsbac_acl_list_all_major_dev(ta_number, &k_id_p);
+        if(count < 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        if(count)
+          {
+            err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+            rsbac_kfree(k_id_p);
+            if(unlikely(err < 0))
+              return err;
+            id_p += count;
+            maxnum -= count;
+            if(!maxnum)
+              return count;
+          }
+
+        count2 = rsbac_acl_list_all_dev(ta_number, &k_id_p);
+        if(count2 < 0)
+          return count2;
+        if(count2 > maxnum)
+          count2 = maxnum;
+
+        if(count2)
+          {
+            err = rsbac_put_user(k_id_p, id_p, count2 * sizeof(*k_id_p) );
+            rsbac_kfree(k_id_p);
+            if(unlikely(err < 0))
+              return err;
+            count += count2;
+          }
+        return count;
+      }
+    else
+      {
+        count = rsbac_acl_list_all_major_dev(ta_number, NULL);
+        if(count < 0)
+          return count;
+        count2 = rsbac_acl_list_all_dev(ta_number, NULL);
+        if(count2 < 0)
+          return count2;
+        else
+          return count + count2;
+      }
+  }
+
+int sys_rsbac_acl_list_all_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t __user * id_p,
+  u_long maxnum)
+  {
+    int err = 0;
+    long count;
+
+    if(id_p && maxnum)
+      {
+        rsbac_uid_t * k_id_p = NULL;
+
+        count = rsbac_acl_list_all_user(ta_number, &k_id_p);
+        if(count < 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        if(count)
+          {
+            err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+            rsbac_kfree(k_id_p);
+            if(unlikely(err < 0))
+              return err;
+          }
+        return count;
+      }
+    else
+      {
+        return rsbac_acl_list_all_user(ta_number, NULL);
+      }
+  }
+
+int sys_rsbac_acl_list_all_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t __user * id_p,
+  u_long maxnum)
+  {
+#ifdef CONFIG_RSBAC_ACL_UM_PROT
+    int err = 0;
+    long count;
+
+    if(id_p && maxnum)
+      {
+        rsbac_gid_t * k_id_p = NULL;
+
+        count = rsbac_acl_list_all_group(ta_number, &k_id_p);
+        if(count < 0)
+          return count;
+        if(count > maxnum)
+          count = maxnum;
+
+        if(count)
+          {
+            err = rsbac_put_user(k_id_p, id_p, count * sizeof(*k_id_p) );
+            rsbac_kfree(k_id_p);
+            if(unlikely(err < 0))
+              return err;
+          }
+        return count;
+      }
+    else
+      {
+        return rsbac_acl_list_all_group(ta_number, NULL);
+      }
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+  }
+#endif
+
+/********  JAIL *********/
+
+#ifdef CONFIG_RSBAC_JAIL
+int sys_rsbac_jail(rsbac_version_t version,
+                   char __user * path,
+                   rsbac_jail_ip_t ip,
+                   rsbac_jail_flags_t flags,
+                   rsbac_cap_vector_t max_caps,
+                   rsbac_jail_scd_vector_t scd_get,
+                   rsbac_jail_scd_vector_t scd_modify)
+    { 
+      return rsbac_jail_sys_jail(version, path, ip, flags,
+                                 max_caps, scd_get, scd_modify);
+    }
+#endif
+
+/********  UM *********/
+
+#ifdef CONFIG_RSBAC_UM
+int sys_rsbac_um_auth_name(
+  char __user * name,
+  char __user * pass)
+    { 
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      int err;
+      char * k_name;
+      char * k_pass;
+      union rsbac_target_id_t i_tid;
+      union rsbac_attribute_value_t i_attr_val;
+
+      if(!name || !pass)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_name(): NULL name or pass\n");
+            }
+#endif
+          return -RSBAC_EINVALIDPOINTER;
+        }
+      k_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_name)
+        return -RSBAC_ENOMEM;
+      k_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_pass)
+        {
+          rsbac_kfree(k_name);
+          return -RSBAC_ENOMEM;
+        }
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        goto out_free;
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+      err = strncpy_from_user(k_pass, pass, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        goto out_free;
+      k_pass[RSBAC_MAXNAMELEN-1] = 0;
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_name(): authenticating user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      if(err) {
+        if(err == -RSBAC_ENOTFOUND) {
+          err = -EPERM;
+          ssleep(1);
+        }
+        goto out_free;
+      }
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_name(): calling ADF\n");
+      }
+#endif
+    i_tid.user = uid;
+    i_attr_val.dummy = 0;
+    if (!rsbac_adf_request(R_AUTHENTICATE,
+                           task_pid(current),
+                           T_USER,
+                           i_tid,
+                           A_none,
+                           i_attr_val))
+      {
+        err = -EPERM;
+        ssleep(1);
+        goto out_free;
+      }
+
+      err = rsbac_um_check_pass(uid, k_pass);
+      if(err) {
+        if(err == -RSBAC_ENOTFOUND) {
+          err = -EPERM;
+        }
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_um)
+          {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	    if(RSBAC_UID_SET(uid))
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): authenticating user %u/%u failed\n",
+                           RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+            else
+#endif
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): authenticating user %u failed\n",
+                           RSBAC_UID_NUM(uid));
+        }
+#endif
+	ssleep(1);
+        goto out_free;
+      }
+
+#ifdef CONFIG_RSBAC_AUTH
+      /* set auth_last_auth for this process */
+      i_tid.process = task_pid(current);
+      i_attr_val.auth_last_auth = uid;
+      if (rsbac_set_attr(SW_AUTH,
+                         T_PROCESS,
+                         i_tid,
+                         A_auth_last_auth,
+                         i_attr_val))
+        {
+          rsbac_ds_set_error("sys_rsbac_um_auth_name()", A_auth_last_auth);
+        }
+#endif /* AUTH */
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_name(): setting process %u vset to %u\n",
+                       current->pid, RSBAC_UID_SET(uid));
+      }
+#endif
+      /* set vset for this process */
+      i_tid.process = task_pid(current);
+      i_attr_val.vset = RSBAC_UID_SET(uid);
+      if (rsbac_set_attr(SW_GEN,
+                         T_PROCESS,
+                         i_tid,
+                         A_vset,
+                         i_attr_val))
+        {
+          rsbac_ds_set_error("sys_rsbac_um_auth_name()", A_vset);
+        }
+#endif
+
+out_free:
+      rsbac_kfree(k_name);
+      memset(k_pass, 0, RSBAC_MAXNAMELEN);
+      rsbac_kfree(k_pass);
+      return err;
+    }
+
+int sys_rsbac_um_auth_uid(rsbac_uid_t uid,
+                          char __user * pass)
+    { 
+      int err;
+      char * k_pass;
+      union rsbac_target_id_t i_tid;
+      union rsbac_attribute_value_t i_attr_val;
+
+      if(!pass)
+        return -RSBAC_EINVALIDPOINTER;
+      k_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_pass)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_pass, pass, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        goto out_free;
+      k_pass[RSBAC_MAXNAMELEN-1] = 0;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+          if(RSBAC_UID_SET(uid))
+            rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): authenticating user %u/%u\n",
+                       RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+          else
+#endif
+            rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): authenticating user %u\n",
+                       RSBAC_UID_NUM(uid));
+      }
+#endif
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): calling ADF\n");
+      }
+#endif
+    i_tid.user = uid;
+    i_attr_val.dummy = 0;
+    if (!rsbac_adf_request(R_AUTHENTICATE,
+                           task_pid(current),
+                           T_USER,
+                           i_tid,
+                           A_none,
+                           i_attr_val))
+      {
+        err = -EPERM;
+        ssleep(1);
+        goto out_free;
+      }
+
+      err = rsbac_um_check_pass(uid, k_pass);
+      if(err) {
+        if(err == -RSBAC_ENOTFOUND) {
+          err = -EPERM;
+        }
+#ifdef CONFIG_RSBAC_DEBUG
+        if (rsbac_debug_aef_um)
+          {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+	    if(RSBAC_UID_SET(uid))
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): authenticating user %u/%u failed\n",
+                           RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+            else
+#endif
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_uid(): authenticating user %u failed\n",
+                           RSBAC_UID_NUM(uid));
+        }
+#endif
+        goto out_free;
+      }
+
+#ifdef CONFIG_RSBAC_AUTH
+      /* set auth_last_auth for this process */
+      i_tid.process = task_pid(current);
+      i_attr_val.auth_last_auth = uid;
+      if (rsbac_set_attr(SW_AUTH,
+                         T_PROCESS,
+                         i_tid,
+                         A_auth_last_auth,
+                         i_attr_val))
+        {
+          rsbac_ds_set_error("sys_rsbac_um_auth_uid()", A_auth_last_auth);
+        }
+#endif /* AUTH */
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      /* set vset for this process */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_auth_name(): setting process %u vset to %u\n",
+                       current->pid, RSBAC_UID_SET(uid));
+      }
+#endif
+      i_tid.process = task_pid(current);
+      i_attr_val.vset = RSBAC_UID_SET(uid);
+      if (rsbac_set_attr(SW_GEN,
+                         T_PROCESS,
+                         i_tid,
+                         A_vset,
+                         i_attr_val))
+        {
+          rsbac_ds_set_error("sys_rsbac_um_auth_uid()", A_vset);
+        }
+#endif
+
+out_free:
+      memset(k_pass, 0, RSBAC_MAXNAMELEN);
+      rsbac_kfree(k_pass);
+      return err;
+    }
+
+int sys_rsbac_um_add_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid,
+  struct rsbac_um_user_entry_t __user * entry_p,
+  char __user * pass,
+  rsbac_time_t ttl)
+    { 
+      int err;
+      struct rsbac_um_user_entry_t * k_entry_p;
+      char * k_pass;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_target_id_t       rsbac_new_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(!entry_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_um_add_user(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_add_user(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_CREATE,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      k_entry_p = rsbac_kmalloc_unlocked(sizeof(*k_entry_p));
+      if(!k_entry_p)
+        return -RSBAC_ENOMEM;
+      if(pass)
+        {
+          k_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_pass)
+            {
+              rsbac_kfree(k_entry_p);
+              return -RSBAC_ENOMEM;
+            }
+        }
+      else
+        k_pass = NULL;
+      err = rsbac_get_user(k_entry_p, entry_p, sizeof(*k_entry_p));
+      if(unlikely(err < 0))
+        goto out_free;
+      if(!k_entry_p->name[0])
+        {
+          err = -RSBAC_EINVALIDVALUE;
+          goto out_free;
+        }
+      k_entry_p->name[RSBAC_UM_NAME_LEN - 1] = 0;
+      k_entry_p->fullname[RSBAC_UM_FULLNAME_LEN - 1] = 0;
+      k_entry_p->homedir[RSBAC_UM_HOMEDIR_LEN - 1] = 0;
+      k_entry_p->shell[RSBAC_UM_SHELL_LEN - 1] = 0;
+      err = rsbac_um_get_uid(0, k_entry_p->name, &uid);
+      if(!err) {
+        err = -RSBAC_EEXISTS;
+        goto out_free;
+      }
+      if(pass)
+        {
+          err = strncpy_from_user(k_pass, pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            goto out_free;
+          k_pass[RSBAC_MAXNAMELEN-1] = 0;
+        }
+      err = rsbac_um_add_user(ta_number, &uid, k_entry_p, k_pass, ttl);
+
+      /* RSBAC: notify ADF of new user */
+      if(!err)
+        {
+          rsbac_target_id.user = uid;
+          rsbac_new_target_id.dummy = 0;
+          if (rsbac_adf_set_attr(R_CREATE,
+                                 task_pid(current),
+                                 T_USER,
+                                 rsbac_target_id,
+                                 T_NONE,
+                                 rsbac_new_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_add_user(): rsbac_adf_set_attr() returned error\n");
+            }
+        }
+
+out_free:
+      rsbac_kfree(k_entry_p);
+      if(k_pass)
+        {
+          memset(k_pass, 0, RSBAC_MAXNAMELEN);
+          rsbac_kfree(k_pass);
+        }
+      return err;
+    }
+
+int sys_rsbac_um_add_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t gid,
+  struct rsbac_um_group_entry_t __user * entry_p,
+  char __user * pass,
+  rsbac_time_t ttl)
+    { 
+      int err;
+      struct rsbac_um_group_entry_t * k_entry_p;
+      char * k_pass;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_target_id_t       rsbac_new_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(!entry_p)
+      return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_add_group(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_GID_SET(gid) == RSBAC_UM_VIRTUAL_KEEP)
+        gid = RSBAC_GEN_GID (rsbac_get_vset(), RSBAC_GID_NUM(gid));
+      else
+        if (RSBAC_GID_SET(gid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      gid = RSBAC_GID_NUM(gid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_add_group(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.group = gid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_CREATE,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      k_entry_p = rsbac_kmalloc_unlocked(sizeof(*k_entry_p));
+      if(!k_entry_p)
+        return -RSBAC_ENOMEM;
+      if(pass)
+        {
+          k_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_pass)
+            {
+              rsbac_kfree(k_entry_p);
+              return -RSBAC_ENOMEM;
+            }
+        }
+      else
+        k_pass = NULL;
+      err = rsbac_get_user(k_entry_p, entry_p, sizeof(*k_entry_p));
+      if(unlikely(err < 0))
+        goto out_free;
+      if(!k_entry_p->name[0])
+        {
+          err = -RSBAC_EINVALIDVALUE;
+          goto out_free;
+        }
+      k_entry_p->name[RSBAC_UM_NAME_LEN - 1] = 0;
+      err = rsbac_um_get_gid(0, k_entry_p->name, &gid);
+      if(!err) {
+        err = -RSBAC_EEXISTS;
+        goto out_free;
+      }
+      if(pass)
+        {
+          err = strncpy_from_user(k_pass, pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            goto out_free;
+          k_pass[RSBAC_MAXNAMELEN-1] = 0;
+        }
+      err = rsbac_um_add_group(ta_number, &gid, k_entry_p, k_pass, ttl);
+
+      /* RSBAC: notify ADF of new group */
+      if(!err)
+        {
+          rsbac_target_id.group = gid;
+          rsbac_new_target_id.dummy = 0;
+          if (rsbac_adf_set_attr(R_CREATE,
+                                 task_pid(current),
+                                 T_GROUP,
+                                 rsbac_target_id,
+                                 T_NONE,
+                                 rsbac_new_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_add_group(): rsbac_adf_set_attr() returned error\n");
+            }
+        }
+
+out_free:
+      rsbac_kfree(k_entry_p);
+      if(k_pass)
+        {
+          memset(k_pass, 0, RSBAC_MAXNAMELEN);
+          rsbac_kfree(k_pass);
+        }
+      return err;
+    }
+
+int sys_rsbac_um_add_gm(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  rsbac_gid_num_t group,
+  rsbac_time_t ttl)
+  {
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_add_gm(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(user) == RSBAC_UM_VIRTUAL_KEEP)
+        user = RSBAC_GEN_UID (rsbac_get_vset(), user);
+      else
+        if (RSBAC_UID_SET(user) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      user = RSBAC_UID_NUM(user);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_add_gm(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = user;
+    rsbac_attribute_value.group = group;
+    if (!rsbac_adf_request(R_CHANGE_GROUP,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_group,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    return rsbac_um_add_gm(ta_number, user, group, ttl);
+  }
+
+int sys_rsbac_um_mod_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t __user * data_p)
+    { 
+      int err;
+      union rsbac_um_mod_data_t * k_data_p;
+      enum  rsbac_adf_request_t     rsbac_request;
+      union rsbac_target_id_t       rsbac_target_id;
+      enum  rsbac_attribute_t       rsbac_attribute = A_none;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(mod >= UM_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(   !data_p
+         && (mod != UM_pass)
+        )
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_mod_user(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+      if(data_p)
+        {
+          k_data_p = rsbac_kmalloc_unlocked(sizeof(*k_data_p));
+          if(!k_data_p)
+            return -RSBAC_ENOMEM;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+          if ((task_thread_info(current)->status & TS_COMPAT) || test_thread_flag(TIF_IA32))
+              err = rsbac_get_user(k_data_p, data_p, sizeof(union rsbac_um_mod_data_ia32_t));
+          else
+#endif
+              err = rsbac_get_user(k_data_p, data_p, sizeof(*k_data_p));
+          if(unlikely(err < 0))
+            {
+              rsbac_kfree(k_data_p);
+              return err;
+            }
+          k_data_p->string[RSBAC_MAXNAMELEN-1] = 0;
+        }
+      else
+        k_data_p = NULL;
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_mod_user(): calling ADF\n");
+      }
+#endif
+    rsbac_attribute_value.dummy = 0;
+    switch(mod)
+      {
+        case UM_name:
+          rsbac_request = R_RENAME;
+          break;
+
+        case UM_pass:
+        case UM_cryptpass:
+          rsbac_request = R_MODIFY_PERMISSIONS_DATA;
+          break;
+
+        case UM_fullname:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_homedir:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_shell:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_group:
+          rsbac_request = R_CHANGE_GROUP;
+          if (!k_data_p)
+            return -RSBAC_EINVALIDPOINTER;
+          rsbac_attribute = A_group;
+          rsbac_attribute_value.group = k_data_p->group;
+          break;
+
+        case UM_lastchange:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_minchange:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_maxchange:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_warnchange:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_inactive:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_expire:
+          rsbac_request = R_WRITE;
+          break;
+
+        case UM_ttl:
+          rsbac_request = R_DELETE;
+          break;
+
+        default:
+          if(k_data_p)
+            rsbac_kfree(k_data_p);
+          return -RSBAC_EINVALIDREQUEST;
+      }
+    rsbac_target_id.user = uid;
+    if (!rsbac_adf_request(rsbac_request,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           rsbac_attribute,
+                           rsbac_attribute_value))
+      {
+        if(k_data_p)
+          rsbac_kfree(k_data_p);
+        return -EPERM;
+      }
+
+      err = rsbac_um_mod_user(ta_number, uid, mod, k_data_p);
+
+      if(k_data_p)
+        rsbac_kfree(k_data_p);
+      return err;
+    }
+
+int sys_rsbac_um_mod_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t gid,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t __user * data_p)
+    { 
+      int err;
+      union rsbac_um_mod_data_t * k_data_p;
+      enum  rsbac_adf_request_t     rsbac_request;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(mod >= UM_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(   !data_p
+         && (mod != UM_pass)
+        )
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_mod_group(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_GID_SET(gid) == RSBAC_UM_VIRTUAL_KEEP)
+        gid = RSBAC_GEN_GID (rsbac_get_vset(), RSBAC_GID_NUM(gid));
+      else
+        if (RSBAC_GID_SET(gid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      gid = RSBAC_GID_NUM(gid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_mod_group(): calling ADF\n");
+      }
+#endif
+    switch(mod)
+      {
+        case UM_name:
+          rsbac_request = R_RENAME;
+          break;
+
+        case UM_pass:
+        case UM_cryptpass:
+          rsbac_request = R_MODIFY_PERMISSIONS_DATA;
+          break;
+
+        case UM_ttl:
+          rsbac_request = R_DELETE;
+          break;
+
+        default:
+          return -RSBAC_EINVALIDREQUEST;
+      }
+    rsbac_target_id.group = gid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(rsbac_request,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      if(data_p)
+        {
+          k_data_p = rsbac_kmalloc_unlocked(sizeof(*k_data_p));
+          if(!k_data_p)
+            return -RSBAC_ENOMEM;
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+          if ((task_thread_info(current)->status & TS_COMPAT) || test_thread_flag(TIF_IA32))
+              err = rsbac_get_user(k_data_p, data_p, sizeof(union rsbac_um_mod_data_ia32_t));
+          else
+#endif
+            err = rsbac_get_user(k_data_p, data_p, sizeof(*k_data_p));
+          if(unlikely(err < 0))
+            {
+              rsbac_kfree(k_data_p);
+              return err;
+            }
+          k_data_p->string[RSBAC_MAXNAMELEN-1] = 0;
+        }
+      else
+        k_data_p = NULL;
+
+      err = rsbac_um_mod_group(ta_number, gid, mod, k_data_p);
+
+      if(k_data_p)
+        rsbac_kfree(k_data_p);
+      return err;
+    }
+
+int sys_rsbac_um_get_user_item(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t __user * data_p)
+    { 
+      int err;
+      union rsbac_um_mod_data_t * k_data_p;
+      enum  rsbac_adf_request_t     rsbac_request;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(mod >= UM_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(!data_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_user_item(): calling ADF\n");
+      }
+#endif
+    rsbac_attribute_value.dummy = 0;
+    switch(mod)
+      {
+        case UM_name:
+          rsbac_request = R_SEARCH;
+          break;
+
+        case UM_group:
+        case UM_fullname:
+        case UM_homedir:
+        case UM_shell:
+          rsbac_request = R_GET_STATUS_DATA;
+          break;
+
+        case UM_pass:
+          rsbac_request = R_GET_PERMISSIONS_DATA;
+          break;
+
+        case UM_lastchange:
+        case UM_minchange:
+        case UM_maxchange:
+        case UM_warnchange:
+        case UM_inactive:
+        case UM_expire:
+        case UM_ttl:
+          rsbac_request = R_READ;
+          break;
+
+        default:
+          return -RSBAC_EINVALIDREQUEST;
+      }
+    rsbac_target_id.user = uid;
+    if (!rsbac_adf_request(rsbac_request,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      k_data_p = rsbac_kmalloc_unlocked(sizeof(*k_data_p));
+      if(!k_data_p)
+        return -RSBAC_ENOMEM;
+      memset(k_data_p, 0, sizeof(*k_data_p));
+
+      err = rsbac_um_get_user_item(ta_number, uid, mod, k_data_p);
+      if(!err)
+        {
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+          if ((task_thread_info(current)->status & TS_COMPAT) || test_thread_flag(TIF_IA32))
+              err = rsbac_put_user(k_data_p, data_p, sizeof(union rsbac_um_mod_data_ia32_t) );
+          else
+#endif
+            err = rsbac_put_user(k_data_p, data_p, sizeof(*k_data_p) );
+        }
+      rsbac_kfree(k_data_p);
+      return err;
+    }
+
+int sys_rsbac_um_get_group_item(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t gid,
+  enum rsbac_um_mod_t mod,
+  union rsbac_um_mod_data_t __user * data_p)
+    { 
+      int err;
+      union rsbac_um_mod_data_t * k_data_p;
+      enum  rsbac_adf_request_t     rsbac_request;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(mod >= UM_none)
+        return -RSBAC_EINVALIDREQUEST;
+      if(!data_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_GID_SET(gid) == RSBAC_UM_VIRTUAL_KEEP)
+        gid = RSBAC_GEN_GID (rsbac_get_vset(), gid);
+      else
+        if (RSBAC_GID_SET(gid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      gid = RSBAC_GID_NUM(gid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_group_item(): getting item %u for %u/%u\n",
+                       mod, RSBAC_GID_SET(gid), RSBAC_GID_NUM(gid));
+        }
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_group_item(): calling ADF\n");
+      }
+#endif
+    rsbac_attribute_value.dummy = 0;
+    switch(mod)
+      {
+        case UM_name:
+          rsbac_request = R_SEARCH;
+          break;
+
+        case UM_pass:
+          rsbac_request = R_GET_PERMISSIONS_DATA;
+          break;
+
+        case UM_ttl:
+          rsbac_request = R_GET_STATUS_DATA;
+          break;
+
+        default:
+          return -RSBAC_EINVALIDREQUEST;
+      }
+    rsbac_target_id.group = gid;
+    if (!rsbac_adf_request(rsbac_request,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      k_data_p = rsbac_kmalloc_unlocked(sizeof(*k_data_p));
+      if(!k_data_p)
+        return -RSBAC_ENOMEM;
+      memset(k_data_p, 0, sizeof(*k_data_p));
+
+      err = rsbac_um_get_group_item(ta_number, gid, mod, k_data_p);
+      if(!err)
+        {
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+          if ((task_thread_info(current)->status & TS_COMPAT) || test_thread_flag(TIF_IA32))
+            err = rsbac_put_user(k_data_p, data_p, sizeof(union rsbac_um_mod_data_ia32_t) );
+          else
+#endif
+            err = rsbac_put_user(k_data_p, data_p, sizeof(*k_data_p) );
+        }
+      rsbac_kfree(k_data_p);
+      return err;
+    }
+
+int sys_rsbac_um_remove_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid)
+  { 
+    int err;
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_target_id_t       rsbac_new_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_remove_user(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_remove_user(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_DELETE,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    err = rsbac_um_remove_user(ta_number, uid);
+
+    if(!err)
+      {
+        rsbac_new_target_id.dummy = 0;
+        if (rsbac_adf_set_attr(R_DELETE,
+                               task_pid(current),
+                               T_USER,
+                               rsbac_target_id,
+                               T_NONE,
+                               rsbac_new_target_id,
+                               A_none,
+                               rsbac_attribute_value))
+          {
+            rsbac_printk(KERN_WARNING
+                         "sys_rsbac_um_remove_user(): rsbac_adf_set_attr() returned error");
+          }
+      }
+
+    return err;
+  }
+
+int sys_rsbac_um_remove_group(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t gid)
+  { 
+    int err;
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_target_id_t       rsbac_new_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_remove_group(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_GID_SET(gid) == RSBAC_UM_VIRTUAL_KEEP)
+        gid = RSBAC_GEN_GID (rsbac_get_vset(), gid);
+      else
+        if (RSBAC_GID_SET(gid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      gid = RSBAC_GID_NUM(gid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_remove_group(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.group = gid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_DELETE,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    err = rsbac_um_remove_group(ta_number, gid);
+
+    if(!err)
+      {
+        rsbac_new_target_id.dummy = 0;
+        if (rsbac_adf_set_attr(R_DELETE,
+                               task_pid(current),
+                               T_GROUP,
+                               rsbac_target_id,
+                               T_NONE,
+                               rsbac_new_target_id,
+                               A_none,
+                               rsbac_attribute_value))
+          {
+            rsbac_printk(KERN_WARNING
+                         "sys_rsbac_um_remove_group(): rsbac_adf_set_attr() returned error");
+          }
+      }
+
+    return err;
+  }
+
+int sys_rsbac_um_remove_gm(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  rsbac_gid_num_t group)
+  {
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+    if(rsbac_freeze)
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_um_remove_gm(): RSBAC configuration frozen, no administration allowed!\n");
+        return -EPERM;
+      }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(user) == RSBAC_UM_VIRTUAL_KEEP)
+        user = RSBAC_GEN_UID (rsbac_get_vset(), user);
+      else
+        if (RSBAC_UID_SET(user) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      user = RSBAC_UID_NUM(user);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_remove_gm(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = user;
+    rsbac_attribute_value.group = group;
+    if (!rsbac_adf_request(R_CHANGE_GROUP,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_group,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    return rsbac_um_remove_gm(ta_number, user, group);
+  }
+
+int sys_rsbac_um_user_exists(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t uid)
+    { 
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_user_exists(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_SEARCH,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      return rsbac_um_user_exists(ta_number, uid);
+    }
+
+int sys_rsbac_um_group_exists(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t gid)
+    { 
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_GID_SET(gid) == RSBAC_UM_VIRTUAL_KEEP)
+        gid = RSBAC_GEN_GID (rsbac_get_vset(), gid);
+      else
+        if (RSBAC_GID_SET(gid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      gid = RSBAC_GID_NUM(gid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_group_exists(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.group = gid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_SEARCH,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      return rsbac_um_group_exists(ta_number, gid);
+    }
+
+int sys_rsbac_um_get_next_user(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t old_user,
+  rsbac_uid_t __user * next_user_p)
+    {
+      rsbac_uid_t k_next_user;
+      int err;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(!next_user_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(old_user) == RSBAC_UM_VIRTUAL_KEEP)
+        old_user = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(old_user));
+      else
+        if (RSBAC_UID_SET(old_user) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      old_user = RSBAC_UID_NUM(old_user);
+#endif
+
+      while (!(err = rsbac_um_get_next_user(ta_number, old_user, &k_next_user)))
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_next_user(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.user = k_next_user;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_SEARCH,
+                               task_pid(current),
+                               T_USER,
+                               rsbac_target_id,
+                               A_none,
+                               rsbac_attribute_value))
+            {
+              old_user = k_next_user;
+              continue;
+            }
+        err = rsbac_put_user(&k_next_user, next_user_p, sizeof(k_next_user));
+        break;
+      }
+      return err;
+    }
+
+int sys_rsbac_um_get_user_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_um_set_t vset,
+  rsbac_uid_t __user user_array[],
+  u_int       maxnum)
+  { 
+    long count;
+    rsbac_uid_t * k_user_array;
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(maxnum > RSBAC_UM_MAX_MAXNUM)
+      maxnum = RSBAC_UM_MAX_MAXNUM;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (vset == RSBAC_UM_VIRTUAL_KEEP)
+      vset = rsbac_get_vset();
+    else
+      if (   (vset > RSBAC_UM_VIRTUAL_MAX)
+          && (vset != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+#else
+    vset = 0;
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_user_list(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = RSBAC_GEN_UID(vset, RSBAC_ALL_USERS);
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_SEARCH,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      /* count only */
+      if(!user_array || !maxnum)
+        return rsbac_um_get_user_list(ta_number, vset, NULL);
+
+      count = rsbac_um_get_user_list(ta_number, vset, &k_user_array);
+      if(count>0)
+        {
+          if(count > maxnum)
+            count = maxnum;
+          rsbac_put_user(k_user_array,
+                         user_array,
+                         count * sizeof(*k_user_array) );
+          rsbac_kfree(k_user_array);
+        }
+      return count;
+  } /* end of sys_rsbac_um_get_user_list() */
+
+int sys_rsbac_um_get_gm_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_uid_t user,
+  rsbac_gid_num_t __user group_array[],
+  u_int       maxnum)
+    { 
+      long count;
+      rsbac_gid_num_t * k_group_array;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(maxnum > RSBAC_UM_MAX_MAXNUM)
+        maxnum = RSBAC_UM_MAX_MAXNUM;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(user) == RSBAC_UM_VIRTUAL_KEEP)
+        user = RSBAC_GEN_UID (rsbac_get_vset(), user);
+      else
+        if (RSBAC_UID_SET(user) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      user = RSBAC_UID_NUM(user);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_gm_list(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = user;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      /* count only */
+      if(!group_array || !maxnum)
+        return rsbac_um_get_gm_list(ta_number, user, NULL);
+
+      count = rsbac_um_get_gm_list(ta_number, user, &k_group_array);
+      if(count>0)
+        {
+          if(count > maxnum)
+            count = maxnum;
+          rsbac_put_user(k_group_array,
+                         group_array,
+                         count * sizeof(*k_group_array) );
+          rsbac_kfree(k_group_array);
+        }
+      return count;
+  } /* end of sys_rsbac_um_get_gm_list() */
+
+int sys_rsbac_um_get_gm_user_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_gid_t group,
+  rsbac_uid_num_t __user user_array[],
+  u_int       maxnum)
+  { 
+    long count;
+    rsbac_uid_num_t * k_user_array;
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(maxnum > RSBAC_UM_MAX_MAXNUM)
+      maxnum = RSBAC_UM_MAX_MAXNUM;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_GID_SET(group) == RSBAC_UM_VIRTUAL_KEEP)
+      group = RSBAC_GEN_GID (rsbac_get_vset(), group);
+    else
+      if (RSBAC_GID_SET(group) > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+#else
+    group = RSBAC_GID_NUM(group);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_gm_user_list(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.group = group;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_READ,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    /* count number of all users */
+    if(!user_array || !maxnum)
+      return rsbac_um_get_gm_user_list(ta_number, group, NULL);
+
+    count = rsbac_um_get_gm_user_list(ta_number, group, &k_user_array);
+    if(count>0)
+      {
+        if(count > maxnum)
+          count = maxnum;
+        rsbac_put_user(k_user_array,
+                       user_array,
+                       count * sizeof(*k_user_array) );
+        rsbac_kfree(k_user_array);
+      }
+    return count;
+    } /* end of sys_rsbac_um_get_gm_user_list() */
+
+int sys_rsbac_um_get_group_list(
+  rsbac_list_ta_number_t ta_number,
+  rsbac_um_set_t vset,
+  rsbac_gid_t __user group_array[],
+  u_int       maxnum)
+  { 
+    long count;
+    rsbac_gid_t * k_group_array;
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if(maxnum > RSBAC_UM_MAX_MAXNUM)
+      maxnum = RSBAC_UM_MAX_MAXNUM;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (vset == RSBAC_UM_VIRTUAL_KEEP)
+      vset = rsbac_get_vset();
+    else
+      if (   (vset > RSBAC_UM_VIRTUAL_MAX)
+          && (vset != RSBAC_UM_VIRTUAL_ALL)
+         )
+        return -RSBAC_EINVALIDVALUE;
+#else
+    vset = 0;
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_group_list(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.group = RSBAC_GEN_GID(vset, RSBAC_ALL_USERS);
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_SEARCH,
+                           task_pid(current),
+                           T_GROUP,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      /* count only */
+      if(!group_array || !maxnum)
+        return rsbac_um_get_group_list(ta_number, vset, NULL);
+
+      count = rsbac_um_get_group_list(ta_number, vset, &k_group_array);
+      if(count>0)
+        {
+          if(count > maxnum)
+            count = maxnum;
+          rsbac_put_user(k_group_array,
+                         group_array,
+                         count * sizeof(*k_group_array) );
+          rsbac_kfree(k_group_array);
+        }
+      return count;
+    } /* end of sys_rsbac_um_get_group_list() */
+
+int sys_rsbac_um_get_uid(
+  rsbac_list_ta_number_t ta_number,
+  char __user * name,
+  rsbac_uid_t __user * uid_p)
+    { 
+      rsbac_uid_t k_uid;
+      int err;
+      char k_name[RSBAC_MAXNAMELEN];
+
+      if(!name || !uid_p)
+        return -RSBAC_EINVALIDPOINTER;
+
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        return err;
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+      err = rsbac_get_user(&k_uid, uid_p, sizeof(k_uid));
+      if(unlikely(err < 0))
+        return err;
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_uid(): looking up %u/%s\n",
+                       RSBAC_UID_SET(k_uid), k_name);
+        }
+#endif
+      /* vset checks are in rsbac_um_get_uid() */
+      err = rsbac_um_get_uid(ta_number, k_name, &k_uid);
+      if(!err)
+        {
+          union rsbac_target_id_t       rsbac_target_id;
+          union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_uid(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.user = k_uid;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_SEARCH,
+                                 task_pid(current),
+                                 T_USER,
+                                 rsbac_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            err = -EPERM;
+          else
+            err = rsbac_put_user(&k_uid, uid_p, sizeof(k_uid));
+        }
+      return err;
+    }
+
+int sys_rsbac_um_get_gid(
+  rsbac_list_ta_number_t ta_number,
+  char __user * name,
+  rsbac_gid_t __user * gid_p)
+    { 
+      rsbac_gid_t k_gid;
+      int err;
+      char k_name[RSBAC_MAXNAMELEN];
+
+      if(!name || !gid_p)
+        return -RSBAC_EINVALIDPOINTER;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        return err;
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+      err = rsbac_get_user(&k_gid, gid_p, sizeof(k_gid));
+      if(unlikely(err < 0))
+        return err;
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_gid(): looking up %u/%s\n",
+                       RSBAC_GID_SET(k_gid), k_name);
+        }
+#endif
+      /* vset checks are in rsbac_um_get_gid() */
+      err = rsbac_um_get_gid(ta_number, k_name, &k_gid);
+      if(!err)
+        {
+          union rsbac_target_id_t       rsbac_target_id;
+          union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_gid(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.group = k_gid;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_SEARCH,
+                                 task_pid(current),
+                                 T_GROUP,
+                                 rsbac_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            err = -EPERM;
+          else
+            err = rsbac_put_user(&k_gid, gid_p, sizeof(k_gid));
+        }
+      return err;
+    }
+
+int sys_rsbac_um_set_pass(rsbac_uid_t uid,
+                          char __user * old_pass,
+                          char __user * new_pass)
+    { 
+      int err;
+      char __user * k_new_pass;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      rsbac_um_set_t vset;
+#endif
+
+      if(!new_pass)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      vset = rsbac_get_vset();
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (vset, uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+      k_new_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_new_pass)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_new_pass, new_pass, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        {
+          rsbac_kfree(k_new_pass);
+          return err;
+        }
+      k_new_pass[RSBAC_MAXNAMELEN-1] = 0;
+
+      if(   old_pass
+         && (RSBAC_UID_NUM(uid) == __kuid_val(current_uid()))
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+         && (RSBAC_UID_SET(uid) == vset)
+#endif
+        )
+        {
+          char * k_old_pass;
+
+          k_old_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_old_pass)
+            {
+              rsbac_kfree(k_new_pass);
+              return -RSBAC_ENOMEM;
+            }
+          err = strncpy_from_user(k_old_pass, old_pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            {
+              rsbac_kfree(k_old_pass);
+              rsbac_kfree(k_new_pass);
+              return err;
+            }
+          k_old_pass[RSBAC_MAXNAMELEN-1] = 0;
+          err = rsbac_um_check_pass(uid, k_old_pass);
+          rsbac_kfree(k_old_pass);
+          if(err)
+            {
+              rsbac_kfree(k_new_pass);
+              rsbac_printk(KERN_INFO "sys_rsbac_um_set_pass(): old password check failed\n");
+              return err;
+            }
+          err = rsbac_um_good_pass(uid, k_new_pass);
+          if(err)
+            {
+              rsbac_kfree(k_new_pass);
+#ifdef CONFIG_RSBAC_DEBUG
+              if (rsbac_debug_aef_um)
+                {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                  if(RSBAC_UID_SET(uid))
+                    rsbac_printk(KERN_DEBUG
+                               "sys_rsbac_um_set_pass(): new password goodness check failed for user %u/%u\n",
+                               RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+                  else
+#endif
+                    rsbac_printk(KERN_DEBUG
+                               "sys_rsbac_um_set_pass(): new password goodness check failed for user %u\n",
+                               RSBAC_UID_NUM(uid));
+                }
+#endif
+              return err;
+            }
+        }
+      else
+        {
+          /* check admin rights here */
+          union rsbac_target_id_t       rsbac_target_id;
+          union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+          if(rsbac_freeze)
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_set_pass(): RSBAC configuration frozen, no administration allowed!\n");
+              rsbac_kfree(k_new_pass);
+              return -EPERM;
+            }
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_pass(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.user = uid;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+                                 task_pid(current),
+                                 T_USER,
+                                 rsbac_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            {
+              rsbac_kfree(k_new_pass);
+              return -EPERM;
+            }
+        }
+
+      err = rsbac_um_set_pass(uid, k_new_pass);
+      rsbac_kfree(k_new_pass);
+      return err;
+    }
+
+int sys_rsbac_um_set_pass_name(char __user * name,
+                               char __user * old_pass,
+                               char __user * new_pass)
+    {
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char * k_name;
+
+      if(!name || !new_pass)
+        return -RSBAC_EINVALIDPOINTER;
+      k_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_name)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        {
+          rsbac_kfree(k_name);
+          return err;
+        }
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_pass_name(): user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      rsbac_kfree(k_name);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_pass_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+        }
+      else
+        err = sys_rsbac_um_set_pass(uid, old_pass, new_pass);
+
+      return err;
+    }
+
+int sys_rsbac_um_add_onetime(rsbac_uid_t uid,
+                          char __user * old_pass,
+                          char __user * new_pass,
+                          rsbac_time_t ttl)
+    { 
+#if defined(CONFIG_RSBAC_UM_ONETIME)
+      int err;
+      char * k_new_pass;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      rsbac_um_set_t vset;
+#endif
+
+      if(!new_pass)
+        return -RSBAC_EINVALIDPOINTER;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      vset = rsbac_get_vset();
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (vset, uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+      k_new_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_new_pass)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_new_pass, new_pass, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        {
+          rsbac_kfree(k_new_pass);
+          return err;
+        }
+      k_new_pass[RSBAC_MAXNAMELEN-1] = 0;
+
+      if(   old_pass
+         && (RSBAC_UID_NUM(uid) == __kuid_val(current_uid()))
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+         && (RSBAC_UID_SET(uid) == vset)
+#endif
+        )
+        {
+          char * k_old_pass;
+
+          k_old_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_old_pass)
+            {
+              rsbac_kfree(k_new_pass);
+              return -RSBAC_ENOMEM;
+            }
+          err = strncpy_from_user(k_old_pass, old_pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            {
+              rsbac_kfree(k_old_pass);
+              rsbac_kfree(k_new_pass);
+              return err;
+            }
+          k_old_pass[RSBAC_MAXNAMELEN-1] = 0;
+          err = rsbac_um_check_pass(uid, k_old_pass);
+          rsbac_kfree(k_old_pass);
+          if(err)
+            {
+              rsbac_kfree(k_new_pass);
+              rsbac_printk(KERN_INFO "sys_rsbac_um_add_onetime(): old password check failed\n");
+              return err;
+            }
+          err = rsbac_um_good_pass(uid, k_new_pass);
+          if(err)
+            {
+              rsbac_kfree(k_new_pass);
+#ifdef CONFIG_RSBAC_DEBUG
+              if (rsbac_debug_aef_um)
+                {
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+                  if(RSBAC_UID_SET(uid))
+                    rsbac_printk(KERN_DEBUG
+                               "sys_rsbac_um_add_onetime(): new password goodness check failed for user %u/%u\n",
+                               RSBAC_UID_SET(uid), RSBAC_UID_NUM(uid));
+                  else
+#endif
+                    rsbac_printk(KERN_DEBUG
+                               "sys_rsbac_um_add_onetime(): new password goodness check failed for user %u\n",
+                               RSBAC_UID_NUM(uid));
+                }
+#endif
+              return err;
+            }
+        }
+      else
+        {
+          /* check admin rights here */
+          union rsbac_target_id_t       rsbac_target_id;
+          union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+          if(rsbac_freeze)
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_add_onetime(): RSBAC configuration frozen, no administration allowed!\n");
+              rsbac_kfree(k_new_pass);
+              return -EPERM;
+            }
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_add_onetime(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.user = uid;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+                                 task_pid(current),
+                                 T_USER,
+                                 rsbac_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            {
+              rsbac_kfree(k_new_pass);
+              return -EPERM;
+            }
+        }
+
+      err = rsbac_um_add_onetime(uid, k_new_pass, ttl);
+      rsbac_kfree(k_new_pass);
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+
+int sys_rsbac_um_add_onetime_name(char __user * name,
+                               char __user * old_pass,
+                               char __user * new_pass,
+                               rsbac_time_t ttl)
+    {
+#if defined(CONFIG_RSBAC_UM_ONETIME)
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char * k_name;
+
+      if(!name || !new_pass)
+        return -RSBAC_EINVALIDPOINTER;
+      k_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_name)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        {
+          rsbac_kfree(k_name);
+          return err;
+        }
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_add_onetime_name(): user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      rsbac_kfree(k_name);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_add_onetime_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+        }
+      else
+        err = sys_rsbac_um_add_onetime(uid, old_pass, new_pass, ttl);
+
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+
+int sys_rsbac_um_remove_all_onetime(rsbac_uid_t uid,
+                          char __user * old_pass)
+    { 
+#if defined(CONFIG_RSBAC_UM_ONETIME)
+      int err;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      rsbac_um_set_t vset;
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      vset = rsbac_get_vset();
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (vset, uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+      if(   old_pass
+         && (RSBAC_UID_NUM(uid) == __kuid_val(current_uid()))
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+         && (RSBAC_UID_SET(uid) == vset)
+#endif
+        )
+        {
+          char * k_old_pass;
+
+          k_old_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_old_pass)
+            {
+              return -RSBAC_ENOMEM;
+            }
+          err = strncpy_from_user(k_old_pass, old_pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            {
+              rsbac_kfree(k_old_pass);
+              return err;
+            }
+          k_old_pass[RSBAC_MAXNAMELEN-1] = 0;
+          err = rsbac_um_check_pass(uid, k_old_pass);
+          rsbac_kfree(k_old_pass);
+          if(err)
+            {
+              rsbac_printk(KERN_INFO "sys_rsbac_um_remove_all_onetime(): old password check failed\n");
+              return err;
+            }
+        }
+      else
+        {
+          /* check admin rights here */
+          union rsbac_target_id_t       rsbac_target_id;
+          union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+          if(rsbac_freeze)
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_remove_all_onetime(): RSBAC configuration frozen, no administration allowed!\n");
+              return -EPERM;
+            }
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_remove_all_onetime(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.user = uid;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+                                 task_pid(current),
+                                 T_USER,
+                                 rsbac_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            {
+              return -EPERM;
+            }
+        }
+
+      err = rsbac_um_remove_all_onetime(uid);
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+
+int sys_rsbac_um_remove_all_onetime_name(char __user * name,
+                               char __user * old_pass)
+    {
+#if defined(CONFIG_RSBAC_UM_ONETIME)
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char * k_name;
+
+      if(!name)
+        return -RSBAC_EINVALIDPOINTER;
+      k_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_name)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        {
+          rsbac_kfree(k_name);
+          return err;
+        }
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_remove_all_onetime_name(): user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      rsbac_kfree(k_name);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_remove_all_onetime_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+        }
+      else
+        err = sys_rsbac_um_remove_all_onetime(uid, old_pass);
+
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+
+int sys_rsbac_um_count_onetime(rsbac_uid_t uid,
+                          char __user * old_pass)
+    { 
+#if defined(CONFIG_RSBAC_UM_ONETIME)
+      int err;
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      rsbac_um_set_t vset;
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      vset = rsbac_get_vset();
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (vset, uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+      if(   old_pass
+         && (RSBAC_UID_NUM(uid) == __kuid_val(current_uid()))
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+         && (RSBAC_UID_SET(uid) == vset)
+#endif
+        )
+        {
+          char * k_old_pass;
+
+          k_old_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_old_pass)
+            {
+              return -RSBAC_ENOMEM;
+            }
+          err = strncpy_from_user(k_old_pass, old_pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            {
+              rsbac_kfree(k_old_pass);
+              return err;
+            }
+          k_old_pass[RSBAC_MAXNAMELEN-1] = 0;
+          err = rsbac_um_check_pass(uid, k_old_pass);
+          rsbac_kfree(k_old_pass);
+          if(err)
+            {
+              rsbac_printk(KERN_INFO "sys_rsbac_um_count_onetime(): old password check failed\n");
+              return err;
+            }
+        }
+      else
+        {
+          /* check admin rights here */
+          union rsbac_target_id_t       rsbac_target_id;
+          union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+          if(rsbac_freeze)
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_count_onetime(): RSBAC configuration frozen, no administration allowed!\n");
+              return -EPERM;
+            }
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_count_onetime(): calling ADF\n");
+            }
+#endif
+          rsbac_target_id.user = uid;
+          rsbac_attribute_value.dummy = 0;
+          if (!rsbac_adf_request(R_READ,
+                                 task_pid(current),
+                                 T_USER,
+                                 rsbac_target_id,
+                                 A_none,
+                                 rsbac_attribute_value))
+            {
+              return -EPERM;
+            }
+        }
+
+      return rsbac_um_count_onetime(uid);
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+
+int sys_rsbac_um_count_onetime_name(char __user * name,
+                               char __user * old_pass)
+    {
+#if defined(CONFIG_RSBAC_UM_ONETIME)
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char * k_name;
+
+      if(!name)
+        return -RSBAC_EINVALIDPOINTER;
+      k_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+      if(!k_name)
+        return -RSBAC_ENOMEM;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        {
+          rsbac_kfree(k_name);
+          return err;
+        }
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_count_onetime_name(): user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      rsbac_kfree(k_name);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_count_onetime_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+        }
+      else
+        err = sys_rsbac_um_count_onetime(uid, old_pass);
+
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+
+int sys_rsbac_um_set_group_pass(rsbac_gid_t gid,
+                                char __user * new_pass)
+    { 
+      int err;
+      char * k_new_pass;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_FREEZE_UM
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_um_set_group_pass(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_GID_SET(gid) == RSBAC_UM_VIRTUAL_KEEP)
+        gid = RSBAC_GEN_GID (rsbac_get_vset(), RSBAC_GID_NUM(gid));
+      else
+        if (RSBAC_GID_SET(gid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      gid = RSBAC_GID_NUM(gid);
+#endif
+
+      /* check admin rights here */
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_group_pass(): calling ADF\n");
+        }
+#endif
+      rsbac_target_id.group = gid;
+      rsbac_attribute_value.dummy = 0;
+      if (!rsbac_adf_request(R_MODIFY_PERMISSIONS_DATA,
+                             task_pid(current),
+                             T_GROUP,
+                             rsbac_target_id,
+                             A_none,
+                             rsbac_attribute_value))
+        {
+          return -EPERM;
+        }
+
+      if(new_pass)
+        {
+          k_new_pass = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+          if(!k_new_pass)
+            return -RSBAC_ENOMEM;
+          err = strncpy_from_user(k_new_pass, new_pass, RSBAC_MAXNAMELEN);
+          if(unlikely(err < 0))
+            {
+              k_new_pass[RSBAC_MAXNAMELEN-1] = 0;
+              err = rsbac_um_set_group_pass(gid, k_new_pass);
+            }
+          rsbac_kfree(k_new_pass);
+        }
+      else
+        {
+          err = rsbac_um_set_group_pass(gid, NULL);
+        }
+      return err;
+    }
+
+int sys_rsbac_um_check_account(rsbac_uid_t uid)
+    { 
+      int err;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_check_account(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      err = rsbac_um_check_account(uid);
+      if(err == -RSBAC_ENOTFOUND)
+        err = -EPERM;
+      return err;
+    }
+
+int sys_rsbac_um_check_account_name(char __user * name)
+    { 
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char k_name[RSBAC_MAXNAMELEN];
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(!name)
+        return -RSBAC_EINVALIDPOINTER;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        return err;
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_check_account_name(): checking user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_check_account_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+          if(err == -RSBAC_ENOTFOUND)
+            err = -EPERM;
+          return err;
+        }
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_check_account_name(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      err = rsbac_um_check_account(uid);
+      if(err == -RSBAC_ENOTFOUND)
+        err = -EPERM;
+      return err;
+    }
+
+int sys_rsbac_um_get_max_history(rsbac_list_ta_number_t ta_number, rsbac_uid_t uid)
+    {
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+      int err;
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_max_history(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_READ,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      err = rsbac_um_get_max_history(ta_number, uid);
+      if(err == -RSBAC_ENOTFOUND)
+        err = -EPERM;
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif
+    }
+
+int sys_rsbac_um_get_max_history_name(rsbac_list_ta_number_t ta_number, char __user * name)
+    {
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char k_name[RSBAC_MAXNAMELEN];
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(!name)
+        return -RSBAC_EINVALIDPOINTER;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        return err;
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_max_history_name(): getting max_history of user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_max_history_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+          if(err == -RSBAC_ENOTFOUND)
+            err = -EPERM;
+          return err;
+        }
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_get_max_history_name(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_READ,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+      err = rsbac_um_get_max_history(ta_number, uid);
+      if(err == -RSBAC_ENOTFOUND)
+        err = -EPERM;
+      return err;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif
+    }
+
+int sys_rsbac_um_set_max_history(rsbac_list_ta_number_t ta_number, rsbac_uid_t uid, __u8 max_history)
+    {
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+      if (RSBAC_UID_SET(uid) == RSBAC_UM_VIRTUAL_KEEP)
+        uid = RSBAC_GEN_UID (rsbac_get_vset(), uid);
+      else
+        if (RSBAC_UID_SET(uid) > RSBAC_UM_VIRTUAL_MAX)
+          return -RSBAC_EINVALIDVALUE;
+#else
+      uid = RSBAC_UID_NUM(uid);
+#endif
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_max_history(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_WRITE,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    return rsbac_um_set_max_history(ta_number, uid, max_history);
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif
+    }
+
+int sys_rsbac_um_set_max_history_name(rsbac_list_ta_number_t ta_number, char __user * name, __u8 max_history)
+    {
+#ifdef CONFIG_RSBAC_UM_PWHISTORY
+      int err;
+      rsbac_uid_t uid = RSBAC_GEN_UID(RSBAC_UM_VIRTUAL_KEEP, RSBAC_NO_USER);
+      char k_name[RSBAC_MAXNAMELEN];
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if(!name)
+        return -RSBAC_EINVALIDPOINTER;
+      err = strncpy_from_user(k_name, name, RSBAC_MAXNAMELEN);
+      if(unlikely(err < 0))
+        return err;
+      k_name[RSBAC_MAXNAMELEN-1] = 0;
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef_um)
+        {
+          rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_max_history_name(): setting max_history of user %s\n",
+                       k_name);
+      }
+#endif
+      err = rsbac_um_get_uid(0, k_name, &uid);
+      if(err)
+        {
+#ifdef CONFIG_RSBAC_DEBUG
+          if (rsbac_debug_aef_um)
+            {
+              rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_max_history_name(): lookup of user %s failed\n",
+                           k_name);
+            }
+#endif
+          if(err == -RSBAC_ENOTFOUND)
+            err = -EPERM;
+          return err;
+        }
+
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_set_max_history_name(): calling ADF\n");
+      }
+#endif
+    rsbac_target_id.user = uid;
+    rsbac_attribute_value.dummy = 0;
+    if (!rsbac_adf_request(R_WRITE,
+                           task_pid(current),
+                           T_USER,
+                           rsbac_target_id,
+                           A_none,
+                           rsbac_attribute_value))
+      {
+        return -EPERM;
+      }
+
+    return rsbac_um_set_max_history(ta_number, uid, max_history);
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif
+    }
+
+int sys_rsbac_um_select_vset(rsbac_um_set_t vset)
+    { 
+#if defined(CONFIG_RSBAC_UM_VIRTUAL)
+      union rsbac_target_id_t       rsbac_target_id;
+      union rsbac_target_id_t       rsbac_new_target_id;
+      union rsbac_attribute_value_t rsbac_attribute_value;
+
+      if (vset > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+
+#ifdef CONFIG_RSBAC_DEBUG
+      if (rsbac_debug_aef)
+        rsbac_printk(KERN_DEBUG "sys_rsbac_um_select_vset(): calling ADF\n");
+#endif
+      rsbac_target_id.process = task_pid(current);
+      rsbac_attribute_value.owner = RSBAC_GEN_UID(vset, __kuid_val(current_uid()));
+      if (!rsbac_adf_request(R_CHANGE_OWNER,
+                             task_pid(current),
+                             T_PROCESS,
+                             rsbac_target_id,
+                             A_owner,
+                             rsbac_attribute_value))
+        {
+          return -EPERM;
+        }
+
+      rsbac_pr_debug(aef_um, "Switching process %u to vset %u\n",
+                     current->pid, vset);
+      rsbac_target_id.process = task_pid(current);
+      rsbac_attribute_value.vset = vset;
+      if (rsbac_set_attr(SW_GEN,
+                         T_PROCESS,
+                         rsbac_target_id,
+                         A_vset,
+                         rsbac_attribute_value))
+        {
+          rsbac_ds_set_error("sys_rsbac_um_select_vset()", A_vset);
+        }
+      else
+        {
+          rsbac_target_id.process = task_pid(current);
+          rsbac_attribute_value.owner = RSBAC_GEN_UID(vset, __kuid_val(current_uid()));
+          rsbac_new_target_id.dummy = 0;
+          if (rsbac_adf_set_attr(R_CHANGE_OWNER,
+                                 task_pid(current),
+                                 T_PROCESS,
+                                 rsbac_target_id,
+                                 T_NONE,
+                                 rsbac_new_target_id,
+                                 A_owner,
+                                 rsbac_attribute_value))
+            {
+              rsbac_printk(KERN_WARNING
+                           "sys_rsbac_um_select_vset(): rsbac_adf_set_attr() returned error\n");
+            }
+        }
+      return 0;
+#else
+    return -RSBAC_EINVALIDMODULE;
+#endif    
+    }
+#endif
+
+/************** UDF ***************/
+
+#ifdef CONFIG_RSBAC_UDF
+int sys_rsbac_udf_flush_cache(void)
+  {
+#ifndef CONFIG_RSBAC_UDF_CACHE
+    return 0;
+#else
+    union rsbac_target_id_t       i_tid;
+    union rsbac_attribute_value_t i_attr_val1;
+
+    /* Security Officer or admin? */
+    i_tid.user = __kuid_val(current_uid());
+    if (rsbac_get_attr(SW_UDF,
+                       T_USER,
+                       i_tid,
+                       A_udf_role,
+                       &i_attr_val1,
+                       TRUE))
+      {
+        rsbac_printk(KERN_WARNING
+                     "sys_rsbac_udf_flush_cache(): rsbac_get_attr() returned error!\n");
+        return -EPERM;
+      }
+    /* if not sec_officer or admin, deny */
+    if (   (i_attr_val1.system_role != SR_security_officer)
+        && (i_attr_val1.system_role != SR_administrator)
+       )
+      #ifdef CONFIG_RSBAC_SOFTMODE
+      if(   !rsbac_softmode
+      #ifdef CONFIG_RSBAC_SOFTMODE_IND
+         && !rsbac_ind_softmode[SW_UDF]
+      #endif
+        )
+      #endif
+      return -EPERM;
+
+    rsbac_printk(KERN_INFO
+           "sys_rsbac_udf_flush_cache(): flushing UDF result cache!\n");
+
+    return rsbac_udf_flush_cache();
+#endif
+  }
+#endif
+
+
+/************************************************* */
+/*             DEBUG/LOG functions                 */
+/************************************************* */
+
+int sys_rsbac_adf_log_switch(enum rsbac_adf_request_t request,
+                             enum rsbac_target_t      target,
+                             u_int                    value)
+  {
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+
+    if ((value != LL_none) && (value != LL_denied) && (value != LL_full))
+      return -RSBAC_EINVALIDVALUE;
+    if(request >= R_NONE)
+      return -RSBAC_EINVALIDREQUEST;
+    if(   (target == T_FD)
+       || (target > T_NONE)
+      )
+      return -RSBAC_EINVALIDTARGET;
+
+#ifdef CONFIG_RSBAC_FREEZE
+      if(rsbac_freeze)
+        {
+          rsbac_printk(KERN_WARNING
+                       "sys_rsbac_adf_log_switch(): RSBAC configuration frozen, no administration allowed!\n");
+          return -EPERM;
+        }
+#endif
+
+    /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      rsbac_printk(KERN_DEBUG "sys_rsbac_adf_log_switch(): calling ADF\n");
+#endif
+    rsbac_target_id.dummy = 0;
+    rsbac_attribute_value.request = target;
+    if (!rsbac_adf_request(R_SWITCH_LOG,
+                           task_pid(current),
+                           T_NONE,
+                           rsbac_target_id,
+                           A_request,
+                           rsbac_attribute_value))
+             {
+               return -EPERM;
+             }
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        char * request_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+        if(request_name)
+          {
+            get_request_name(request_name,target);
+            rsbac_printk(KERN_INFO "sys_rsbac_adf_log_switch(): switching RSBAC module logging for request %s (No. %i) to %i!\n",
+                   request_name, target, value);
+            rsbac_kfree(request_name);
+          }
+      }
+#endif
+    rsbac_adf_log_switch(request,target,value);
+    return 0;
+  }
+
+int sys_rsbac_get_adf_log(enum rsbac_adf_request_t   request,
+                          enum rsbac_target_t        target,
+                          u_int             __user * value_p)
+  {
+    union rsbac_target_id_t       rsbac_target_id;
+    union rsbac_attribute_value_t rsbac_attribute_value;
+    u_int k_value;
+    int err;
+
+    if(request >= R_NONE)
+      return -RSBAC_EINVALIDREQUEST;
+    if(   (target == T_FD)
+       || (target > T_NONE)
+      )
+      return -RSBAC_EINVALIDTARGET;
+    if(!value_p)
+      return -RSBAC_EINVALIDPOINTER;
+    /* call ADF */
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      rsbac_printk(KERN_DEBUG "sys_rsbac_get_adf_log(): calling ADF\n");
+#endif
+    rsbac_target_id.scd = ST_rsbac;
+    rsbac_attribute_value.request = request;
+    if (!rsbac_adf_request(R_GET_STATUS_DATA,
+                           task_pid(current),
+                           T_SCD,
+                           rsbac_target_id,
+                           A_request,
+                           rsbac_attribute_value))
+             {
+               return -EPERM;
+             }
+#ifdef CONFIG_RSBAC_DEBUG
+    if (rsbac_debug_aef)
+      {
+        char * request_name = rsbac_kmalloc_unlocked(RSBAC_MAXNAMELEN);
+        if(request_name)
+          {
+            get_request_name(request_name,target);
+            rsbac_printk(KERN_DEBUG "sys_rsbac_get_adf_log(): getting RSBAC module logging for request %s (No. %i)!\n",
+                   request_name, target);
+            rsbac_kfree(request_name);
+          }
+      }
+#endif
+    err = rsbac_get_adf_log(request, target, &k_value);
+    if(!err)
+      {
+        rsbac_put_user(&k_value,
+                       value_p,
+                       sizeof(k_value) );
+      }
+    return err;
+  }
+
+/*
+ * Commands to sys_rsbac_log:
+ *
+ * 	0 -- Close the log.  Currently a NOP.
+ * 	1 -- Open the log. Currently a NOP.
+ * 	2 -- Read from the log.
+ * 	3 -- Read up to the last 4k of messages in the ring buffer.
+ * 	4 -- Read and clear last 4k of messages in the ring buffer
+ * 	5 -- Clear ring buffer.
+ */
+int sys_rsbac_log(int type,
+                  char __user * buf,
+                  int len)
+  {
+#if defined(CONFIG_RSBAC_RMSG)
+    return rsbac_log(type,buf,len);
+#else
+    return 0;
+#endif /* RMSG */
+  }
+
+#if defined(CONFIG_RSBAC_INIT_DELAY)
+int sys_rsbac_init(char __user * path)
+  {
+    struct dentry * t_dentry = NULL;
+    rsbac_boolean_t need_put = FALSE;
+    int     err = 0;
+
+    struct path ppath;
+
+    if(!path)
+      return rsbac_init(ROOT_DEV);
+
+    if ((err = user_lpath(path, &ppath)))
+      {
+        goto out;
+      }
+      t_dentry = ppath.dentry;
+    need_put = TRUE;
+    if (!t_dentry->d_inode)
+      {
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    /* is inode of type file, symlink or block/char device? */
+    if(!S_ISBLK(t_dentry->d_inode->i_mode))
+      { /* This is no file or device */
+        err = -RSBAC_EINVALIDTARGET;
+        goto out_dput;
+      }
+    err = rsbac_init(t_dentry->d_sb->s_dev);
+
+out_dput:
+      if(need_put)
+        path_put(&ppath);
+out:
+      return err;
+  }
+#endif
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+int sys_rsbac_list_ta_begin_name(
+  rsbac_time_t ttl,
+  rsbac_list_ta_number_t __user * ta_number_p,
+  rsbac_uid_t commit_uid,
+  char __user * name,
+  char __user * password)
+  {
+    int err;
+    rsbac_list_ta_number_t k_ta_number = 0;
+    char * k_name = NULL;
+    char * k_password = NULL;
+
+#ifdef CONFIG_RSBAC_UM_VIRTUAL
+    if (RSBAC_UID_SET(commit_uid) == RSBAC_UM_VIRTUAL_KEEP)
+      commit_uid = RSBAC_GEN_UID (rsbac_get_vset(), RSBAC_UID_NUM(commit_uid));
+    else
+      if (RSBAC_UID_SET(commit_uid) > RSBAC_UM_VIRTUAL_MAX)
+        return -RSBAC_EINVALIDVALUE;
+#else
+    commit_uid = RSBAC_UID_NUM(commit_uid);
+#endif
+    if(name)
+      {
+        k_name = rsbac_kmalloc_unlocked(RSBAC_LIST_TA_MAX_NAMELEN);
+        if(!k_name)
+          return -ENOMEM;
+        err = strncpy_from_user(k_name, name, RSBAC_LIST_TA_MAX_NAMELEN);
+        if(unlikely(err < 0))
+          {
+            rsbac_kfree(k_name);
+            return err;
+          }
+        k_name[RSBAC_LIST_TA_MAX_NAMELEN - 1] = 0;
+      }
+    if(password)
+      {
+        k_password = rsbac_kmalloc_unlocked(RSBAC_LIST_TA_MAX_PASSLEN);
+        if(!k_password)
+          return -ENOMEM;
+        err = strncpy_from_user(k_password, password, RSBAC_LIST_TA_MAX_PASSLEN);
+        if(unlikely(err < 0))
+          {
+            rsbac_kfree(k_password);
+            return err;
+          }
+        k_password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
+      }
+    err = rsbac_list_ta_begin(ttl, &k_ta_number, commit_uid, k_name, k_password);
+    if(!err)
+      err = rsbac_put_user(&k_ta_number,
+                           ta_number_p,
+                           sizeof(k_ta_number) );
+    if(k_name)
+      rsbac_kfree(k_name);
+    if(k_password)
+      rsbac_kfree(k_password);
+    return err;
+  }
+
+int sys_rsbac_list_ta_begin(
+  rsbac_time_t ttl,
+  rsbac_list_ta_number_t __user * ta_number_p,
+  rsbac_uid_t commit_uid,
+  char __user * password)
+  {
+    return sys_rsbac_list_ta_begin_name(ttl, ta_number_p, commit_uid, NULL, password);
+  }
+
+int sys_rsbac_list_ta_refresh(
+  rsbac_time_t ttl,
+  rsbac_list_ta_number_t ta_number,
+  char __user * password)
+  {
+    int err;
+    char * k_password;
+
+    if(password)
+      {
+        k_password = rsbac_kmalloc_unlocked(RSBAC_LIST_TA_MAX_PASSLEN);
+        if(!k_password)
+          return -ENOMEM;
+        err = strncpy_from_user(k_password, password, RSBAC_LIST_TA_MAX_PASSLEN);
+        if(unlikely(err < 0))
+          {
+            rsbac_kfree(k_password);
+            return err;
+          }
+        k_password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
+      }
+    else
+      k_password = NULL;
+    err = rsbac_list_ta_refresh(ttl, ta_number, k_password);
+    if(k_password)
+      rsbac_kfree(k_password);
+    return err;
+  }
+
+int sys_rsbac_list_ta_commit(
+  rsbac_list_ta_number_t ta_number,
+  char __user * password)
+  {
+    int err;
+    char * k_password;
+
+    if(password)
+      {
+        k_password = rsbac_kmalloc_unlocked(RSBAC_LIST_TA_MAX_PASSLEN);
+        if(!k_password)
+          return -ENOMEM;
+        err = strncpy_from_user(k_password, password, RSBAC_LIST_TA_MAX_PASSLEN);
+        if(unlikely(err < 0))
+          {
+            rsbac_kfree(k_password);
+            return err;
+          }
+        k_password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
+      }
+    else
+      k_password = NULL;
+    err = rsbac_list_ta_commit(ta_number, k_password);
+    if(k_password)
+      rsbac_kfree(k_password);
+    return err;
+  }
+
+int sys_rsbac_list_ta_forget(
+  rsbac_list_ta_number_t ta_number,
+  char __user * password)
+  {
+    int err;
+    char * k_password;
+
+    if(password)
+      {
+        k_password = rsbac_kmalloc_unlocked(RSBAC_LIST_TA_MAX_PASSLEN);
+        if(!k_password)
+          return -ENOMEM;
+        err = strncpy_from_user(k_password, password, RSBAC_LIST_TA_MAX_PASSLEN);
+        if(unlikely(err < 0))
+          {
+            rsbac_kfree(k_password);
+            return err;
+          }
+        k_password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
+      }
+    else
+      k_password = NULL;
+    err = rsbac_list_ta_forget(ta_number, k_password);
+    if(k_password)
+      rsbac_kfree(k_password);
+    return err;
+  }
+#endif
+
+/* Big dispatcher for all syscalls */
+#ifdef rsbac_syscall4
+asmlinkage int sys_rsbac(int dummy,
+                         rsbac_version_t version,
+                         enum  rsbac_syscall_t call,
+                         union rsbac_syscall_arg_t __user * arg_p)
+#else
+asmlinkage int sys_rsbac(rsbac_version_t version,
+                         enum  rsbac_syscall_t call,
+                         union rsbac_syscall_arg_t __user * arg_p)
+#endif
+  {
+    int err;
+
+    if( (!rsbac_initialized) && (call != RSYS_init) ) {
+	    rsbac_printk(KERN_WARNING "sys_rsbac(): RSBAC not initialized\n");
+	    return -RSBAC_ENOTINITIALIZED;
+    }
+
+    if (   (   (version < RSBAC_VERSION_MAKE_NR(RSBAC_VERSION_MAJOR,RSBAC_VERSION_MID,0))
+            || (version >= RSBAC_VERSION_MAKE_NR(RSBAC_VERSION_MAJOR, (RSBAC_VERSION_MID + 1),0))
+           )
+        && (call != RSYS_version))
+      return -RSBAC_EINVALIDVERSION;
+
+    if(call >= RSYS_none)
+      return -RSBAC_EINVALIDREQUEST;
+
+#ifdef CONFIG_RSBAC_XSTATS
+    syscall_count[call]++;
+#endif
+
+#if defined(CONFIG_IA32_EMULATION) || defined(CONFIG_X86_X32)
+    if((task_thread_info(current)->status & TS_COMPAT) || test_thread_flag(TIF_IA32)) {
+      union rsbac_syscall_arg_ia32_t k_arg;
+
+      /* get values from user space */
+      if(arg_p)
+        {
+          err = rsbac_get_user(&k_arg, arg_p, sizeof(k_arg) );
+          if(unlikely(err < 0))
+            return err;
+        }
+      else
+        {
+          memset(&k_arg, 0, sizeof(k_arg));
+        }
+
+      switch(call)
+        {
+#ifdef CONFIG_RSBAC_UM
+          case RSYS_um_get_user_item:
+            return sys_rsbac_um_get_user_item(k_arg.um_get_user_item.ta_number,
+                                              k_arg.um_get_user_item.uid,
+                                              k_arg.um_get_user_item.mod,
+                                              (void __user *)(long)k_arg.um_get_user_item.data_p);
+          case RSYS_um_get_uid:
+            return sys_rsbac_um_get_uid(k_arg.um_get_uid.ta_number,
+                                        (void __user *)(long)k_arg.um_get_uid.name,
+                                        (void __user *)(long)k_arg.um_get_uid.uid_p);
+          case RSYS_um_get_group_item:
+            return sys_rsbac_um_get_group_item(k_arg.um_get_group_item.ta_number,
+                                               k_arg.um_get_group_item.gid,
+                                               k_arg.um_get_group_item.mod,
+                                               (void __user *)(long)k_arg.um_get_group_item.data_p);
+          case RSYS_um_get_gm_list:
+            return sys_rsbac_um_get_gm_list(k_arg.um_get_gm_list.ta_number,
+                                            k_arg.um_get_gm_list.user,
+                                            (void __user *)(long)k_arg.um_get_gm_list.group_array,
+                                            k_arg.um_get_gm_list.maxnum);
+          case RSYS_um_get_gm_user_list:
+            return sys_rsbac_um_get_gm_user_list(k_arg.um_get_gm_user_list.ta_number,
+                                                 k_arg.um_get_gm_user_list.group,
+                                                 (void __user *)(long)k_arg.um_get_gm_user_list.user_array,
+                                                 k_arg.um_get_gm_user_list.maxnum);
+          case RSYS_um_get_gid:
+            return sys_rsbac_um_get_gid(k_arg.um_get_gid.ta_number,
+                                        (void __user *)(long)k_arg.um_get_gid.name,
+                                        (void __user *)(long)k_arg.um_get_gid.gid_p);
+          case RSYS_um_get_user_list:
+            return sys_rsbac_um_get_user_list(k_arg.um_get_user_list.ta_number,
+                                              k_arg.um_get_user_list.vset,
+                                              (void __user *)(long)k_arg.um_get_user_list.user_array,
+                                              k_arg.um_get_user_list.maxnum);
+          case RSYS_um_check_account_name:
+            return sys_rsbac_um_check_account_name((void __user *)(long)k_arg.um_check_account_name.name);
+#endif
+          case RSYS_get_attr:
+            return sys_rsbac_get_attr(k_arg.get_attr.ta_number,
+                                      k_arg.get_attr.module,
+                                      k_arg.get_attr.target,
+                                      (void __user *)(long)k_arg.get_attr.tid,
+                                      k_arg.get_attr.attr,
+                                      (void __user *)(long)k_arg.get_attr.value,
+                                      k_arg.get_attr.inherit);
+          case RSYS_get_attr_n:
+            return sys_rsbac_get_attr_n(k_arg.get_attr_n.ta_number,
+                                        k_arg.get_attr_n.module,
+                                        k_arg.get_attr_n.target,
+                                        (void __user *)(long)k_arg.get_attr_n.t_name,
+                                        k_arg.get_attr_n.attr,
+                                        (void __user *)(long)k_arg.get_attr_n.value,
+                                        k_arg.get_attr_n.inherit);
+          case RSYS_set_attr:
+            return sys_rsbac_set_attr(k_arg.set_attr.ta_number,
+                                      k_arg.set_attr.module,
+                                      k_arg.set_attr.target,
+                                      (void __user *)(long)k_arg.set_attr.tid,
+                                      k_arg.set_attr.attr,
+                                      (void __user *)(long)k_arg.set_attr.value);
+          case RSYS_set_attr_n:
+            return sys_rsbac_set_attr_n(k_arg.set_attr_n.ta_number,
+                                        k_arg.set_attr_n.module,
+                                        k_arg.set_attr_n.target,
+                                        (void __user *)(long)k_arg.set_attr_n.t_name,
+                                        k_arg.set_attr_n.attr,
+                                        (void __user *)(long)k_arg.set_attr_n.value);
+#ifdef CONFIG_RSBAC_RC
+          case RSYS_rc_get_current_role:
+            return sys_rsbac_rc_get_current_role((void __user *)(long)k_arg.rc_get_current_role.role_p);
+          case RSYS_rc_get_item:
+            return sys_rsbac_rc_get_item(k_arg.rc_get_item.ta_number,
+                                         k_arg.rc_get_item.target,
+                                         (void __user *)(long)k_arg.rc_get_item.tid_p,
+                                         (void __user *)(long)k_arg.rc_get_item.subtid_p,
+                                         k_arg.rc_get_item.item,
+                                         (void __user *)(long)k_arg.rc_get_item.value_p,
+                                         (void __user *)(long)k_arg.rc_get_item.ttl_p);
+          case RSYS_rc_change_role:
+            return sys_rsbac_rc_change_role(k_arg.rc_change_role.role,
+                                            (void __user *)(long)k_arg.rc_change_role.pass);
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+          case RSYS_jail:
+            return rsbac_jail_sys_jail(k_arg.jail.version,
+                                       (void __user *)(long)k_arg.jail.path,
+                                       k_arg.jail.ip,
+                                       k_arg.jail.flags,
+                                       k_arg.jail.max_caps,
+                                       k_arg.jail.scd_get,
+                                       k_arg.jail.scd_modify);
+#endif
+
+          case RSYS_remove_target:
+            return sys_rsbac_remove_target(k_arg.remove_target.ta_number,
+                                           k_arg.remove_target.target,
+                                           (void __user *)(long)k_arg.remove_target.tid);
+          case RSYS_remove_target_n:
+            return sys_rsbac_remove_target_n(k_arg.remove_target_n.ta_number,
+                                             k_arg.remove_target_n.target,
+                                             (void __user *)(long)k_arg.remove_target_n.t_name);
+          case RSYS_net_list_all_netdev:
+            return sys_rsbac_net_list_all_netdev(k_arg.net_list_all_netdev.ta_number,
+                                                 (void __user *)(long)k_arg.net_list_all_netdev.id_p,
+                                                 k_arg.net_list_all_netdev.maxnum);
+          case RSYS_net_template:
+            return sys_rsbac_net_template(k_arg.net_template.ta_number,
+                                          k_arg.net_template.call,
+                                          k_arg.net_template.id,
+                                          (void __user *)(long)k_arg.net_template.data_p);
+          case RSYS_net_list_all_template:
+            return sys_rsbac_net_list_all_template(k_arg.net_list_all_template.ta_number,
+                                                   (void __user *)(long)k_arg.net_list_all_template.id_p,
+                                                   k_arg.net_list_all_template.maxnum);
+          case RSYS_switch:
+            return sys_rsbac_switch(k_arg.switch_module.module,
+                                    k_arg.switch_module.value);
+	case RSYS_get_switch:
+	  return sys_rsbac_get_switch(k_arg.get_switch_module.module,
+					(void __user *)(long)k_arg.get_switch_module.value_p,
+					(void __user *)(long)k_arg.get_switch_module.switchable_p);
+          case RSYS_adf_log_switch:
+            return sys_rsbac_adf_log_switch(k_arg.adf_log_switch.request,
+                                            k_arg.adf_log_switch.target,
+                                            k_arg.adf_log_switch.value);
+          case RSYS_get_adf_log:
+            return sys_rsbac_get_adf_log(k_arg.get_adf_log.request,
+                                         k_arg.get_adf_log.target,
+                                         (void __user *)(long)k_arg.get_adf_log.value_p);
+          case RSYS_write:
+            return sys_rsbac_write();
+          case RSYS_log:
+            return sys_rsbac_log(k_arg.log.type,
+                                 (void __user *)(long)k_arg.log.buf,
+                                 k_arg.log.len);
+#ifdef CONFIG_RSBAC_MAC
+          case RSYS_mac_set_curr_level:
+            return sys_rsbac_mac_set_curr_level(k_arg.mac_set_curr_level.level,
+                                                (void __user *)(long)k_arg.mac_set_curr_level.categories_p);
+          case RSYS_mac_get_curr_level:
+            return sys_rsbac_mac_get_curr_level((void __user *)(long)k_arg.mac_get_curr_level.level_p,
+                                                (void __user *)(long)k_arg.mac_get_curr_level.categories_p);
+          case RSYS_mac_get_max_level:
+            return sys_rsbac_mac_get_max_level((void __user *)(long)k_arg.mac_get_max_level.level_p,
+                                               (void __user *)(long)k_arg.mac_get_max_level.categories_p);
+          case RSYS_mac_get_min_level:
+            return sys_rsbac_mac_get_min_level((void __user *)(long)k_arg.mac_get_min_level.level_p,
+                                               (void __user *)(long)k_arg.mac_get_min_level.categories_p);
+          case RSYS_mac_add_p_tru:
+            return sys_rsbac_mac_add_p_tru(k_arg.mac_add_p_tru.ta_number,
+                                           k_arg.mac_add_p_tru.pid,
+                                           k_arg.mac_add_p_tru.uid,
+                                           k_arg.mac_add_p_tru.ttl);
+          case RSYS_mac_remove_p_tru:
+            return sys_rsbac_mac_remove_p_tru(k_arg.mac_remove_p_tru.ta_number,
+                                              k_arg.mac_remove_p_tru.pid,
+                                              k_arg.mac_add_p_tru.uid);
+          case RSYS_mac_add_f_tru:
+            return sys_rsbac_mac_add_f_tru(k_arg.mac_add_f_tru.ta_number,
+                                           (void __user *)(long)k_arg.mac_add_f_tru.filename,
+                                           k_arg.mac_add_p_tru.uid,
+                                           k_arg.mac_add_f_tru.ttl);
+          case RSYS_mac_remove_f_tru:
+            return sys_rsbac_mac_remove_f_tru(k_arg.mac_remove_f_tru.ta_number,
+                                            (void __user *)(long)k_arg.mac_remove_f_tru.filename,
+                                            k_arg.mac_remove_f_tru.uid);
+          case RSYS_mac_get_f_trulist:
+            return sys_rsbac_mac_get_f_trulist(k_arg.mac_get_f_trulist.ta_number,
+                                                (void __user *)(long)k_arg.mac_get_f_trulist.filename,
+                                                (void __user *)(long)k_arg.mac_get_f_trulist.trulist,
+                                                (void __user *)(long)k_arg.mac_get_f_trulist.ttllist,
+                                                k_arg.mac_get_f_trulist.maxnum);
+          case RSYS_mac_get_p_trulist:
+            return sys_rsbac_mac_get_p_trulist(k_arg.mac_get_p_trulist.ta_number,
+                                               k_arg.mac_get_p_trulist.pid,
+                                               (void __user *)(long)k_arg.mac_get_p_trulist.trulist,
+                                               (void __user *)(long)k_arg.mac_get_p_trulist.ttllist,
+                                               k_arg.mac_get_p_trulist.maxnum);
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+          case RSYS_daz_flush_cache:
+            return sys_rsbac_daz_flush_cache();
+#endif
+#ifdef CONFIG_RSBAC_RC
+          case RSYS_rc_copy_role:
+            return sys_rsbac_rc_copy_role(k_arg.rc_copy_role.ta_number,
+                                          k_arg.rc_copy_role.from_role,
+                                          k_arg.rc_copy_role.to_role);
+          case RSYS_rc_copy_type:
+            return sys_rsbac_rc_copy_type(k_arg.rc_copy_type.ta_number,
+                                          k_arg.rc_copy_type.target,
+                                          k_arg.rc_copy_type.from_type,
+                                          k_arg.rc_copy_type.to_type);
+          case RSYS_rc_set_item:
+            return sys_rsbac_rc_set_item(k_arg.rc_set_item.ta_number,
+                                         k_arg.rc_set_item.target,
+                                         (void __user *)(long)k_arg.rc_set_item.tid_p,
+                                         (void __user *)(long)k_arg.rc_set_item.subtid_p,
+                                         k_arg.rc_set_item.item,
+                                         (void __user *)(long)k_arg.rc_set_item.value_p,
+                                         k_arg.rc_set_item.ttl);
+          case RSYS_rc_get_eff_rights_n:
+            return sys_rsbac_rc_get_eff_rights_n(k_arg.rc_get_eff_rights_n.ta_number,
+                                                 k_arg.rc_get_eff_rights_n.target,
+                                                 (void __user *)(long)k_arg.rc_get_eff_rights_n.t_name,
+                                                 (void __user *)(long)k_arg.rc_get_eff_rights_n.request_vector_p,
+                                                 (void __user *)(long)k_arg.rc_get_eff_rights_n.ttl_p);
+          case RSYS_rc_get_list:
+            return sys_rsbac_rc_get_list(k_arg.rc_get_list.ta_number,
+                                         k_arg.rc_get_list.target,
+                                         (void __user *)(long)k_arg.rc_get_list.tid_p,
+                                         k_arg.rc_get_list.item,
+                                         k_arg.rc_get_list.maxnum,
+                                         (void __user *)(long)k_arg.rc_get_list.array_p,
+                                         (void __user *)(long)k_arg.rc_get_list.ttl_array_p);
+	case RSYS_rc_select_fd_create_type:
+		return sys_rsbac_rc_select_fd_create_type(k_arg.rc_select_fd_create_type.type);
+#endif
+#ifdef CONFIG_RSBAC_AUTH
+          case RSYS_auth_add_p_cap:
+            {
+              struct rsbac_auth_cap_range_t cap_range_64;
+
+              cap_range_64.first = k_arg.auth_add_p_cap.cap_range.first;
+              cap_range_64.last = k_arg.auth_add_p_cap.cap_range.last;
+              return sys_rsbac_auth_add_p_cap(k_arg.auth_add_p_cap.ta_number,
+                                            k_arg.auth_add_p_cap.pid,
+                                            k_arg.auth_add_p_cap.cap_type,
+                                            cap_range_64,
+                                            k_arg.auth_add_p_cap.ttl);
+            }
+          case RSYS_auth_remove_p_cap:
+            {
+              struct rsbac_auth_cap_range_t cap_range_64;
+
+              cap_range_64.first = k_arg.auth_add_p_cap.cap_range.first;
+              cap_range_64.last = k_arg.auth_add_p_cap.cap_range.last;
+              return sys_rsbac_auth_remove_p_cap(k_arg.auth_remove_p_cap.ta_number,
+                                               k_arg.auth_remove_p_cap.pid,
+                                               k_arg.auth_remove_p_cap.cap_type,
+                                               cap_range_64);
+            }
+          case RSYS_auth_add_f_cap:
+            {
+              struct rsbac_auth_cap_range_t cap_range_64;
+
+              cap_range_64.first = k_arg.auth_add_p_cap.cap_range.first;
+              cap_range_64.last = k_arg.auth_add_p_cap.cap_range.last;
+              return sys_rsbac_auth_add_f_cap(k_arg.auth_add_f_cap.ta_number,
+                                            (void __user *)(long)k_arg.auth_add_f_cap.filename,
+                                            k_arg.auth_add_f_cap.cap_type,
+                                            cap_range_64,
+                                            k_arg.auth_add_f_cap.ttl);
+            }
+          case RSYS_auth_remove_f_cap:
+            {
+              struct rsbac_auth_cap_range_t cap_range_64;
+
+              cap_range_64.first = k_arg.auth_add_p_cap.cap_range.first;
+              cap_range_64.last = k_arg.auth_add_p_cap.cap_range.last;
+              return sys_rsbac_auth_remove_f_cap(k_arg.auth_remove_f_cap.ta_number,
+                                               (void __user *)(long)k_arg.auth_remove_f_cap.filename,
+                                               k_arg.auth_remove_f_cap.cap_type,
+                                               cap_range_64);
+            }
+          case RSYS_auth_get_f_caplist:
+            return sys_rsbac_auth_get_f_caplist(k_arg.auth_get_f_caplist.ta_number,
+                                                (void __user *)(long)k_arg.auth_get_f_caplist.filename,
+                                                k_arg.auth_get_f_caplist.cap_type,
+                                                (void __user *)(long)k_arg.auth_get_f_caplist.caplist,
+                                                (void __user *)(long)k_arg.auth_get_f_caplist.ttllist,
+                                                k_arg.auth_get_f_caplist.maxnum);
+          case RSYS_auth_get_p_caplist:
+            return sys_rsbac_auth_get_p_caplist(k_arg.auth_get_p_caplist.ta_number,
+                                                k_arg.auth_get_p_caplist.pid,
+                                                k_arg.auth_get_p_caplist.cap_type,
+                                                (void __user *)(long)k_arg.auth_get_p_caplist.caplist,
+                                                (void __user *)(long)k_arg.auth_get_p_caplist.ttllist,
+                                                k_arg.auth_get_p_caplist.maxnum);
+#endif
+#ifdef CONFIG_RSBAC_ACL
+          case RSYS_acl:
+            return sys_rsbac_acl(k_arg.acl.ta_number,
+                                 k_arg.acl.call,
+                                 (void __user *)(long)k_arg.acl.arg);
+          case RSYS_acl_n:
+            return sys_rsbac_acl_n(k_arg.acl_n.ta_number,
+                                   k_arg.acl_n.call,
+                                   (void __user *)(long)k_arg.acl_n.arg);
+          case RSYS_acl_get_rights:
+            return sys_rsbac_acl_get_rights(k_arg.acl_get_rights.ta_number,
+                                            (void __user *)(long)k_arg.acl_get_rights.arg,
+                                            (void __user *)(long)k_arg.acl_get_rights.rights_p,
+                                            k_arg.acl_get_rights.effective);
+          case RSYS_acl_get_rights_n:
+            return sys_rsbac_acl_get_rights_n(k_arg.acl_get_rights_n.ta_number,
+                                              (void __user *)(long)k_arg.acl_get_rights_n.arg,
+                                              (void __user *)(long)k_arg.acl_get_rights_n.rights_p,
+                                              k_arg.acl_get_rights_n.effective);
+          case RSYS_acl_get_tlist:
+            return sys_rsbac_acl_get_tlist(k_arg.acl_get_tlist.ta_number,
+                                           k_arg.acl_get_tlist.target,
+                                           (void __user *)(long)k_arg.acl_get_tlist.tid,
+                                           (void __user *)(long)k_arg.acl_get_tlist.entry_array,
+                                           (void __user *)(long)k_arg.acl_get_tlist.ttl_array,
+                                           k_arg.acl_get_tlist.maxnum);
+          case RSYS_acl_get_tlist_n:
+            return sys_rsbac_acl_get_tlist_n(k_arg.acl_get_tlist_n.ta_number,
+                                             k_arg.acl_get_tlist_n.target,
+                                             (void __user *)(long)k_arg.acl_get_tlist_n.t_name,
+                                             (void __user *)(long)k_arg.acl_get_tlist_n.entry_array,
+                                             (void __user *)(long)k_arg.acl_get_tlist_n.ttl_array,
+                                             k_arg.acl_get_tlist_n.maxnum);
+          case RSYS_acl_get_mask:
+            return sys_rsbac_acl_get_mask(k_arg.acl_get_mask.ta_number,
+                                          k_arg.acl_get_mask.target,
+                                          (void __user *)(long)k_arg.acl_get_mask.tid,
+                                          (void __user *)(long)k_arg.acl_get_mask.mask_p);
+          case RSYS_acl_get_mask_n:
+            return sys_rsbac_acl_get_mask_n(k_arg.acl_get_mask_n.ta_number,
+                                            k_arg.acl_get_mask_n.target,
+                                            (void __user *)(long)k_arg.acl_get_mask_n.t_name,
+                                            (void __user *)(long)k_arg.acl_get_mask_n.mask_p);
+          case RSYS_acl_group:
+            return sys_rsbac_acl_group(k_arg.acl_group.ta_number,
+                                       k_arg.acl_group.call,
+                                       (void __user *)(long)k_arg.acl_group.arg_p);
+          case RSYS_acl_list_all_dev:
+            return sys_rsbac_acl_list_all_dev(k_arg.acl_list_all_dev.ta_number,
+                                              (void __user *)(long)k_arg.acl_list_all_dev.id_p,
+                                              k_arg.acl_list_all_dev.maxnum);
+          case RSYS_acl_list_all_user:
+            return sys_rsbac_acl_list_all_user(k_arg.acl_list_all_user.ta_number,
+                                               (void __user *)(long)k_arg.acl_list_all_user.id_p,
+                                               k_arg.acl_list_all_user.maxnum);
+          case RSYS_acl_list_all_group:
+            return sys_rsbac_acl_list_all_group(k_arg.acl_list_all_group.ta_number,
+                                                (void __user *)(long)k_arg.acl_list_all_group.id_p,
+                                                k_arg.acl_list_all_group.maxnum);
+#endif
+#ifdef CONFIG_RSBAC_REG
+          case RSYS_reg:
+            return sys_rsbac_reg(k_arg.reg.handle,
+                                 (void __user *)(long)k_arg.reg.arg);
+#endif
+#ifdef CONFIG_RSBAC_UM
+          case RSYS_um_auth_name:
+            return sys_rsbac_um_auth_name((void __user *)(long)k_arg.um_auth_name.name,
+                                          (void __user *)(long)k_arg.um_auth_name.pass);
+          case RSYS_um_auth_uid:
+            return sys_rsbac_um_auth_uid(k_arg.um_auth_uid.uid,
+                                         (void __user *)(long)k_arg.um_auth_uid.pass);
+          case RSYS_um_add_user:
+            return sys_rsbac_um_add_user(k_arg.um_add_user.ta_number,
+                                         k_arg.um_add_user.uid,
+                                         (void __user *)(long)k_arg.um_add_user.entry_p,
+                                         (void __user *)(long)k_arg.um_add_user.pass,
+                                         k_arg.um_add_user.ttl);
+          case RSYS_um_add_group:
+            return sys_rsbac_um_add_group(k_arg.um_add_group.ta_number,
+                                          k_arg.um_add_group.gid,
+                                          (void __user *)(long)k_arg.um_add_group.entry_p,
+                                          (void __user *)(long)k_arg.um_add_group.pass,
+                                          k_arg.um_add_group.ttl);
+          case RSYS_um_add_gm:
+            return sys_rsbac_um_add_gm(k_arg.um_add_gm.ta_number,
+                                       k_arg.um_add_gm.uid,
+                                       k_arg.um_add_gm.gid,
+                                       k_arg.um_add_gm.ttl);
+          case RSYS_um_mod_user:
+            return sys_rsbac_um_mod_user(k_arg.um_mod_user.ta_number,
+                                         k_arg.um_mod_user.uid,
+                                         k_arg.um_mod_user.mod,
+                                         (void __user *)(long)k_arg.um_mod_user.data_p);
+          case RSYS_um_mod_group:
+            return sys_rsbac_um_mod_group(k_arg.um_mod_group.ta_number,
+                                          k_arg.um_mod_group.gid,
+                                          k_arg.um_mod_group.mod,
+                                          (void __user *)(long)k_arg.um_mod_group.data_p);
+          case RSYS_um_remove_user:
+            return sys_rsbac_um_remove_user(k_arg.um_remove_user.ta_number,
+                                            k_arg.um_remove_user.uid);
+          case RSYS_um_remove_group:
+            return sys_rsbac_um_remove_group(k_arg.um_remove_group.ta_number,
+                                             k_arg.um_remove_group.gid);
+          case RSYS_um_remove_gm:
+            return sys_rsbac_um_remove_gm(k_arg.um_remove_gm.ta_number,
+                                          k_arg.um_remove_gm.uid,
+                                          k_arg.um_remove_gm.gid);
+          case RSYS_um_user_exists:
+            return sys_rsbac_um_user_exists(k_arg.um_user_exists.ta_number,
+                                            k_arg.um_user_exists.uid);
+          case RSYS_um_get_next_user:
+            return sys_rsbac_um_get_next_user(k_arg.um_get_next_user.ta_number,
+                                              k_arg.um_get_next_user.old_user,
+                                              (void __user *)(long)k_arg.um_get_next_user.next_user_p);
+          case RSYS_um_group_exists:
+            return sys_rsbac_um_group_exists(k_arg.um_group_exists.ta_number,
+                                            k_arg.um_group_exists.gid);
+          case RSYS_um_get_group_list:
+            return sys_rsbac_um_get_group_list(k_arg.um_get_group_list.ta_number,
+                                               k_arg.um_get_group_list.vset,
+                                               (void __user *)(long)k_arg.um_get_group_list.group_array,
+                                               k_arg.um_get_group_list.maxnum);
+          case RSYS_um_set_pass:
+            return sys_rsbac_um_set_pass(k_arg.um_set_pass.uid,
+                                         (void __user *)(long)k_arg.um_set_pass.old_pass,
+                                         (void __user *)(long)k_arg.um_set_pass.new_pass);
+          case RSYS_um_set_pass_name:
+            return sys_rsbac_um_set_pass_name((void __user *)(long)k_arg.um_set_pass_name.name,
+                                         (void __user *)(long)k_arg.um_set_pass_name.old_pass,
+                                         (void __user *)(long)k_arg.um_set_pass_name.new_pass);
+          case RSYS_um_add_onetime:
+            return sys_rsbac_um_add_onetime(k_arg.um_add_onetime.uid,
+                                         (void __user *)(long)k_arg.um_add_onetime.old_pass,
+                                         (void __user *)(long)k_arg.um_add_onetime.new_pass,
+                                         k_arg.um_add_onetime.ttl);
+          case RSYS_um_add_onetime_name:
+            return sys_rsbac_um_add_onetime_name((void __user *)(long)k_arg.um_add_onetime_name.name,
+                                         (void __user *)(long)k_arg.um_add_onetime_name.old_pass,
+                                         (void __user *)(long)k_arg.um_add_onetime_name.new_pass,
+                                         k_arg.um_add_onetime_name.ttl);
+          case RSYS_um_remove_all_onetime:
+            return sys_rsbac_um_remove_all_onetime(k_arg.um_remove_all_onetime.uid,
+                                         (void __user *)(long)k_arg.um_remove_all_onetime.old_pass);
+          case RSYS_um_remove_all_onetime_name:
+            return sys_rsbac_um_remove_all_onetime_name((void __user *)(long)k_arg.um_remove_all_onetime_name.name,
+                                         (void __user *)(long)k_arg.um_remove_all_onetime_name.old_pass);
+          case RSYS_um_count_onetime:
+            return sys_rsbac_um_count_onetime(k_arg.um_count_onetime.uid,
+                                         (void __user *)(long)k_arg.um_count_onetime.old_pass);
+          case RSYS_um_count_onetime_name:
+            return sys_rsbac_um_count_onetime_name((void __user *)(long)k_arg.um_count_onetime_name.name,
+                                         (void __user *)(long)k_arg.um_count_onetime_name.old_pass);
+          case RSYS_um_set_group_pass:
+            return sys_rsbac_um_set_group_pass(k_arg.um_set_group_pass.gid,
+                                               (void __user *)(long)k_arg.um_set_group_pass.new_pass);
+          case RSYS_um_check_account:
+            return sys_rsbac_um_check_account(k_arg.um_check_account.uid);
+          case RSYS_um_get_max_history:
+            return sys_rsbac_um_get_max_history(k_arg.um_get_max_history.ta_number,
+                                                k_arg.um_get_max_history.uid);
+          case RSYS_um_get_max_history_name:
+            return sys_rsbac_um_get_max_history_name(k_arg.um_get_max_history_name.ta_number,
+                                                     (void __user *)(long)k_arg.um_get_max_history_name.name);
+          case RSYS_um_set_max_history:
+            return sys_rsbac_um_set_max_history(k_arg.um_set_max_history.ta_number,
+                                                k_arg.um_set_max_history.uid,
+                                                k_arg.um_set_max_history.max_history);
+          case RSYS_um_set_max_history_name:
+            return sys_rsbac_um_set_max_history_name(k_arg.um_set_max_history_name.ta_number,
+                                                (void __user *)(long)k_arg.um_set_max_history_name.name,
+                                                k_arg.um_set_max_history_name.max_history);
+          case RSYS_um_select_vset:
+            return sys_rsbac_um_select_vset(k_arg.um_select_vset.vset);
+#endif
+#ifdef CONFIG_RSBAC_UDF
+          case RSYS_udf_flush_cache:
+            return sys_rsbac_udf_flush_cache();
+#endif
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+          case RSYS_list_ta_begin_name:
+            return sys_rsbac_list_ta_begin_name(k_arg.list_ta_begin.ttl,
+                                           (void __user *)(long)k_arg.list_ta_begin_name.ta_number_p,
+                                           k_arg.list_ta_begin_name.commit_uid,
+                                           (void __user *)(long)k_arg.list_ta_begin_name.name,
+                                           (void __user *)(long)k_arg.list_ta_begin_name.password);
+          case RSYS_list_ta_begin:
+            return sys_rsbac_list_ta_begin(k_arg.list_ta_begin.ttl,
+                                           (void __user *)(long)k_arg.list_ta_begin.ta_number_p,
+                                           k_arg.list_ta_begin.commit_uid,
+                                           (void __user *)(long)k_arg.list_ta_begin.password);
+          case RSYS_list_ta_refresh:
+            return sys_rsbac_list_ta_refresh(k_arg.list_ta_refresh.ttl,
+                                             k_arg.list_ta_refresh.ta_number,
+                                             (void __user *)(long)k_arg.list_ta_refresh.password);
+          case RSYS_list_ta_commit:
+            return sys_rsbac_list_ta_commit(k_arg.list_ta_commit.ta_number,
+                                            (void __user *)(long)k_arg.list_ta_commit.password);
+          case RSYS_list_ta_forget:
+            return sys_rsbac_list_ta_forget(k_arg.list_ta_forget.ta_number,
+                                            (void __user *)(long)k_arg.list_ta_forget.password);
+#endif
+
+          case RSYS_list_all_dev:
+            return sys_rsbac_list_all_dev(k_arg.list_all_dev.ta_number,
+                                          (void __user *)(long)k_arg.list_all_dev.id_p,
+                                          k_arg.list_all_dev.maxnum);
+          case RSYS_list_all_user:
+            return sys_rsbac_list_all_user(k_arg.list_all_user.ta_number,
+                                           (void __user *)(long)k_arg.list_all_user.id_p,
+                                           k_arg.list_all_user.maxnum);
+          case RSYS_list_all_group:
+            return sys_rsbac_list_all_group(k_arg.list_all_group.ta_number,
+                                            (void __user *)(long)k_arg.list_all_group.id_p,
+                                            k_arg.list_all_group.maxnum);
+	case RSYS_list_all_ipc:
+		return sys_rsbac_list_all_ipc(k_arg.list_all_ipc.ta_number,
+					       (void __user *)(long)k_arg.list_all_ipc.id_p,
+					       k_arg.list_all_ipc.maxnum);
+
+          case RSYS_version:
+            return RSBAC_VERSION_NR;
+          case RSYS_stats:
+            return sys_rsbac_stats();
+          case RSYS_check:
+            return sys_rsbac_check(k_arg.check.correct, k_arg.check.check_inode);
+#if defined(CONFIG_RSBAC_INIT_DELAY)
+          case RSYS_init:
+            return sys_rsbac_init((void __user *)(long)k_arg.init.root_dev);
+#endif
+
+          default:
+            return -RSBAC_EINVALIDREQUEST;
+        }
+    } else
+#endif
+    {
+      union rsbac_syscall_arg_t k_arg;
+
+      /* get values from user space */
+      if(arg_p)
+        {
+          err = rsbac_get_user(&k_arg, arg_p, sizeof(k_arg) );
+          if(unlikely(err < 0))
+            return err;
+        }
+      else
+        {
+          memset(&k_arg, 0, sizeof(k_arg));
+        }
+
+      switch(call)
+        {
+#ifdef CONFIG_RSBAC_UM
+          case RSYS_um_get_user_item:
+            return sys_rsbac_um_get_user_item(k_arg.um_get_user_item.ta_number,
+                                              k_arg.um_get_user_item.uid,
+                                              k_arg.um_get_user_item.mod,
+                                              k_arg.um_get_user_item.data_p);
+          case RSYS_um_get_uid:
+            return sys_rsbac_um_get_uid(k_arg.um_get_uid.ta_number,
+                                        k_arg.um_get_uid.name,
+                                        k_arg.um_get_uid.uid_p);
+          case RSYS_um_get_group_item:
+            return sys_rsbac_um_get_group_item(k_arg.um_get_group_item.ta_number,
+                                               k_arg.um_get_group_item.gid,
+                                               k_arg.um_get_group_item.mod,
+                                               k_arg.um_get_group_item.data_p);
+          case RSYS_um_get_gm_list:
+            return sys_rsbac_um_get_gm_list(k_arg.um_get_gm_list.ta_number,
+                                            k_arg.um_get_gm_list.user,
+                                            k_arg.um_get_gm_list.group_array,
+                                            k_arg.um_get_gm_list.maxnum);
+          case RSYS_um_get_gm_user_list:
+            return sys_rsbac_um_get_gm_user_list(k_arg.um_get_gm_user_list.ta_number,
+                                                 k_arg.um_get_gm_user_list.group,
+                                                 k_arg.um_get_gm_user_list.user_array,
+                                                 k_arg.um_get_gm_user_list.maxnum);
+          case RSYS_um_get_gid:
+            return sys_rsbac_um_get_gid(k_arg.um_get_gid.ta_number,
+                                        k_arg.um_get_gid.name,
+                                        k_arg.um_get_gid.gid_p);
+          case RSYS_um_get_user_list:
+            return sys_rsbac_um_get_user_list(k_arg.um_get_user_list.ta_number,
+                                              k_arg.um_get_user_list.vset,
+                                              k_arg.um_get_user_list.user_array,
+                                              k_arg.um_get_user_list.maxnum);
+          case RSYS_um_check_account_name:
+            return sys_rsbac_um_check_account_name(k_arg.um_check_account_name.name);
+#endif
+          case RSYS_get_attr:
+            return sys_rsbac_get_attr(k_arg.get_attr.ta_number,
+                                      k_arg.get_attr.module,
+                                      k_arg.get_attr.target,
+                                      k_arg.get_attr.tid,
+                                      k_arg.get_attr.attr,
+                                      k_arg.get_attr.value,
+                                      k_arg.get_attr.inherit);
+          case RSYS_get_attr_n:
+            return sys_rsbac_get_attr_n(k_arg.get_attr_n.ta_number,
+                                        k_arg.get_attr_n.module,
+                                        k_arg.get_attr_n.target,
+                                        k_arg.get_attr_n.t_name,
+                                        k_arg.get_attr_n.attr,
+                                        k_arg.get_attr_n.value,
+                                        k_arg.get_attr_n.inherit);
+          case RSYS_set_attr:
+            return sys_rsbac_set_attr(k_arg.set_attr.ta_number,
+                                      k_arg.set_attr.module,
+                                      k_arg.set_attr.target,
+                                      k_arg.set_attr.tid,
+                                      k_arg.set_attr.attr,
+                                      k_arg.set_attr.value);
+          case RSYS_set_attr_n:
+            return sys_rsbac_set_attr_n(k_arg.set_attr_n.ta_number,
+                                        k_arg.set_attr_n.module,
+                                        k_arg.set_attr_n.target,
+                                        k_arg.set_attr_n.t_name,
+                                        k_arg.set_attr_n.attr,
+                                        k_arg.set_attr_n.value);
+#ifdef CONFIG_RSBAC_RC
+          case RSYS_rc_get_current_role:
+            return sys_rsbac_rc_get_current_role(k_arg.rc_get_current_role.role_p);
+          case RSYS_rc_get_item:
+            return sys_rsbac_rc_get_item(k_arg.rc_get_item.ta_number,
+                                         k_arg.rc_get_item.target,
+                                         k_arg.rc_get_item.tid_p,
+                                         k_arg.rc_get_item.subtid_p,
+                                         k_arg.rc_get_item.item,
+                                         k_arg.rc_get_item.value_p,
+                                         k_arg.rc_get_item.ttl_p);
+          case RSYS_rc_change_role:
+            return sys_rsbac_rc_change_role(k_arg.rc_change_role.role, k_arg.rc_change_role.pass);
+#endif
+#ifdef CONFIG_RSBAC_JAIL
+          case RSYS_jail:
+            return rsbac_jail_sys_jail(k_arg.jail.version,
+                                       k_arg.jail.path,
+                                       k_arg.jail.ip,
+                                       k_arg.jail.flags,
+                                       k_arg.jail.max_caps,
+                                       k_arg.jail.scd_get,
+                                       k_arg.jail.scd_modify);
+#endif
+
+          case RSYS_remove_target:
+            return sys_rsbac_remove_target(k_arg.remove_target.ta_number,
+                                           k_arg.remove_target.target,
+                                           k_arg.remove_target.tid);
+          case RSYS_remove_target_n:
+            return sys_rsbac_remove_target_n(k_arg.remove_target_n.ta_number,
+                                             k_arg.remove_target_n.target,
+                                             k_arg.remove_target_n.t_name);
+          case RSYS_net_list_all_netdev:
+            return sys_rsbac_net_list_all_netdev(k_arg.net_list_all_netdev.ta_number,
+                                                 k_arg.net_list_all_netdev.id_p,
+                                                 k_arg.net_list_all_netdev.maxnum);
+          case RSYS_net_template:
+            return sys_rsbac_net_template(k_arg.net_template.ta_number,
+                                          k_arg.net_template.call,
+                                          k_arg.net_template.id,
+                                          k_arg.net_template.data_p);
+          case RSYS_net_list_all_template:
+            return sys_rsbac_net_list_all_template(k_arg.net_list_all_template.ta_number,
+                                                   k_arg.net_list_all_template.id_p,
+                                                   k_arg.net_list_all_template.maxnum);
+          case RSYS_switch:
+            return sys_rsbac_switch(k_arg.switch_module.module,
+                                    k_arg.switch_module.value);
+	case RSYS_get_switch:
+	  return sys_rsbac_get_switch(k_arg.get_switch_module.module,
+			  		k_arg.get_switch_module.value_p,
+					k_arg.get_switch_module.switchable_p);
+          case RSYS_adf_log_switch:
+            return sys_rsbac_adf_log_switch(k_arg.adf_log_switch.request,
+                                            k_arg.adf_log_switch.target,
+                                            k_arg.adf_log_switch.value);
+          case RSYS_get_adf_log:
+            return sys_rsbac_get_adf_log(k_arg.get_adf_log.request,
+                                         k_arg.get_adf_log.target,
+                                         k_arg.get_adf_log.value_p);
+          case RSYS_write:
+            return sys_rsbac_write();
+          case RSYS_log:
+            return sys_rsbac_log(k_arg.log.type,
+                                 k_arg.log.buf,
+                                 k_arg.log.len);
+#ifdef CONFIG_RSBAC_MAC
+          case RSYS_mac_set_curr_level:
+            return sys_rsbac_mac_set_curr_level(k_arg.mac_set_curr_level.level,
+                                                k_arg.mac_set_curr_level.categories_p);
+          case RSYS_mac_get_curr_level:
+            return sys_rsbac_mac_get_curr_level(k_arg.mac_get_curr_level.level_p,
+                                                k_arg.mac_get_curr_level.categories_p);
+          case RSYS_mac_get_max_level:
+            return sys_rsbac_mac_get_max_level(k_arg.mac_get_max_level.level_p,
+                                               k_arg.mac_get_max_level.categories_p);
+          case RSYS_mac_get_min_level:
+            return sys_rsbac_mac_get_min_level(k_arg.mac_get_min_level.level_p,
+                                               k_arg.mac_get_min_level.categories_p);
+          case RSYS_mac_add_p_tru:
+            return sys_rsbac_mac_add_p_tru(k_arg.mac_add_p_tru.ta_number,
+                                           k_arg.mac_add_p_tru.pid,
+                                           k_arg.mac_add_p_tru.uid,
+                                           k_arg.mac_add_p_tru.ttl);
+          case RSYS_mac_remove_p_tru:
+            return sys_rsbac_mac_remove_p_tru(k_arg.mac_remove_p_tru.ta_number,
+                                              k_arg.mac_remove_p_tru.pid,
+                                              k_arg.mac_add_p_tru.uid);
+          case RSYS_mac_add_f_tru:
+            return sys_rsbac_mac_add_f_tru(k_arg.mac_add_f_tru.ta_number,
+                                           k_arg.mac_add_f_tru.filename,
+                                           k_arg.mac_add_p_tru.uid,
+                                           k_arg.mac_add_f_tru.ttl);
+          case RSYS_mac_remove_f_tru:
+            return sys_rsbac_mac_remove_f_tru(k_arg.mac_remove_f_tru.ta_number,
+                                            k_arg.mac_remove_f_tru.filename,
+                                            k_arg.mac_remove_f_tru.uid);
+          case RSYS_mac_get_f_trulist:
+            return sys_rsbac_mac_get_f_trulist(k_arg.mac_get_f_trulist.ta_number,
+                                                k_arg.mac_get_f_trulist.filename,
+                                                k_arg.mac_get_f_trulist.trulist,
+                                                k_arg.mac_get_f_trulist.ttllist,
+                                                k_arg.mac_get_f_trulist.maxnum);
+          case RSYS_mac_get_p_trulist:
+            return sys_rsbac_mac_get_p_trulist(k_arg.mac_get_p_trulist.ta_number,
+                                               k_arg.mac_get_p_trulist.pid,
+                                               k_arg.mac_get_p_trulist.trulist,
+                                               k_arg.mac_get_p_trulist.ttllist,
+                                               k_arg.mac_get_p_trulist.maxnum);
+#endif
+#ifdef CONFIG_RSBAC_DAZ
+          case RSYS_daz_flush_cache:
+            return sys_rsbac_daz_flush_cache();
+#endif
+#ifdef CONFIG_RSBAC_RC
+          case RSYS_rc_copy_role:
+            return sys_rsbac_rc_copy_role(k_arg.rc_copy_role.ta_number,
+                                          k_arg.rc_copy_role.from_role,
+                                          k_arg.rc_copy_role.to_role);
+          case RSYS_rc_copy_type:
+            return sys_rsbac_rc_copy_type(k_arg.rc_copy_type.ta_number,
+                                          k_arg.rc_copy_type.target,
+                                          k_arg.rc_copy_type.from_type,
+                                          k_arg.rc_copy_type.to_type);
+          case RSYS_rc_set_item:
+            return sys_rsbac_rc_set_item(k_arg.rc_set_item.ta_number,
+                                         k_arg.rc_set_item.target,
+                                         k_arg.rc_set_item.tid_p,
+                                         k_arg.rc_set_item.subtid_p,
+                                         k_arg.rc_set_item.item,
+                                         k_arg.rc_set_item.value_p,
+                                         k_arg.rc_set_item.ttl);
+          case RSYS_rc_get_eff_rights_n:
+            return sys_rsbac_rc_get_eff_rights_n(k_arg.rc_get_eff_rights_n.ta_number,
+                                                 k_arg.rc_get_eff_rights_n.target,
+                                                 k_arg.rc_get_eff_rights_n.t_name,
+                                                 k_arg.rc_get_eff_rights_n.request_vector_p,
+                                                 k_arg.rc_get_eff_rights_n.ttl_p);
+          case RSYS_rc_get_list:
+            return sys_rsbac_rc_get_list(k_arg.rc_get_list.ta_number,
+                                         k_arg.rc_get_list.target,
+                                         k_arg.rc_get_list.tid_p,
+                                         k_arg.rc_get_list.item,
+                                         k_arg.rc_get_list.maxnum,
+                                         k_arg.rc_get_list.array_p,
+                                         k_arg.rc_get_list.ttl_array_p);
+	case RSYS_rc_select_fd_create_type:
+		return sys_rsbac_rc_select_fd_create_type(k_arg.rc_select_fd_create_type.type);
+#endif
+#ifdef CONFIG_RSBAC_AUTH
+          case RSYS_auth_add_p_cap:
+            return sys_rsbac_auth_add_p_cap(k_arg.auth_add_p_cap.ta_number,
+                                            k_arg.auth_add_p_cap.pid,
+                                            k_arg.auth_add_p_cap.cap_type,
+                                            k_arg.auth_add_p_cap.cap_range,
+                                            k_arg.auth_add_p_cap.ttl);
+          case RSYS_auth_remove_p_cap:
+            return sys_rsbac_auth_remove_p_cap(k_arg.auth_remove_p_cap.ta_number,
+                                               k_arg.auth_remove_p_cap.pid,
+                                               k_arg.auth_remove_p_cap.cap_type,
+                                               k_arg.auth_remove_p_cap.cap_range);
+          case RSYS_auth_add_f_cap:
+            return sys_rsbac_auth_add_f_cap(k_arg.auth_add_f_cap.ta_number,
+                                            k_arg.auth_add_f_cap.filename,
+                                            k_arg.auth_add_f_cap.cap_type,
+                                            k_arg.auth_add_f_cap.cap_range,
+                                            k_arg.auth_add_f_cap.ttl);
+          case RSYS_auth_remove_f_cap:
+            return sys_rsbac_auth_remove_f_cap(k_arg.auth_remove_f_cap.ta_number,
+                                               k_arg.auth_remove_f_cap.filename,
+                                               k_arg.auth_remove_f_cap.cap_type,
+                                               k_arg.auth_remove_f_cap.cap_range);
+          case RSYS_auth_get_f_caplist:
+            return sys_rsbac_auth_get_f_caplist(k_arg.auth_get_f_caplist.ta_number,
+                                                k_arg.auth_get_f_caplist.filename,
+                                                k_arg.auth_get_f_caplist.cap_type,
+                                                k_arg.auth_get_f_caplist.caplist,
+                                                k_arg.auth_get_f_caplist.ttllist,
+                                                k_arg.auth_get_f_caplist.maxnum);
+          case RSYS_auth_get_p_caplist:
+            return sys_rsbac_auth_get_p_caplist(k_arg.auth_get_p_caplist.ta_number,
+                                                k_arg.auth_get_p_caplist.pid,
+                                                k_arg.auth_get_p_caplist.cap_type,
+                                                k_arg.auth_get_p_caplist.caplist,
+                                                k_arg.auth_get_p_caplist.ttllist,
+                                                k_arg.auth_get_p_caplist.maxnum);
+#endif
+#ifdef CONFIG_RSBAC_ACL
+          case RSYS_acl:
+            return sys_rsbac_acl(k_arg.acl.ta_number,
+                                 k_arg.acl.call,
+                                 k_arg.acl.arg);
+          case RSYS_acl_n:
+            return sys_rsbac_acl_n(k_arg.acl_n.ta_number,
+                                   k_arg.acl_n.call,
+                                   k_arg.acl_n.arg);
+          case RSYS_acl_get_rights:
+            return sys_rsbac_acl_get_rights(k_arg.acl_get_rights.ta_number,
+                                            k_arg.acl_get_rights.arg,
+                                            k_arg.acl_get_rights.rights_p,
+                                            k_arg.acl_get_rights.effective);
+          case RSYS_acl_get_rights_n:
+            return sys_rsbac_acl_get_rights_n(k_arg.acl_get_rights_n.ta_number,
+                                              k_arg.acl_get_rights_n.arg,
+                                              k_arg.acl_get_rights_n.rights_p,
+                                              k_arg.acl_get_rights_n.effective);
+          case RSYS_acl_get_tlist:
+            return sys_rsbac_acl_get_tlist(k_arg.acl_get_tlist.ta_number,
+                                           k_arg.acl_get_tlist.target,
+                                           k_arg.acl_get_tlist.tid,
+                                           k_arg.acl_get_tlist.entry_array,
+                                           k_arg.acl_get_tlist.ttl_array,
+                                           k_arg.acl_get_tlist.maxnum);
+          case RSYS_acl_get_tlist_n:
+            return sys_rsbac_acl_get_tlist_n(k_arg.acl_get_tlist_n.ta_number,
+                                             k_arg.acl_get_tlist_n.target,
+                                             k_arg.acl_get_tlist_n.t_name,
+                                             k_arg.acl_get_tlist_n.entry_array,
+                                             k_arg.acl_get_tlist_n.ttl_array,
+                                             k_arg.acl_get_tlist_n.maxnum);
+          case RSYS_acl_get_mask:
+            return sys_rsbac_acl_get_mask(k_arg.acl_get_mask.ta_number,
+                                          k_arg.acl_get_mask.target,
+                                          k_arg.acl_get_mask.tid,
+                                          k_arg.acl_get_mask.mask_p);
+          case RSYS_acl_get_mask_n:
+            return sys_rsbac_acl_get_mask_n(k_arg.acl_get_mask_n.ta_number,
+                                            k_arg.acl_get_mask_n.target,
+                                            k_arg.acl_get_mask_n.t_name,
+                                            k_arg.acl_get_mask_n.mask_p);
+          case RSYS_acl_group:
+            return sys_rsbac_acl_group(k_arg.acl_group.ta_number,
+                                       k_arg.acl_group.call,
+                                       k_arg.acl_group.arg_p);
+          case RSYS_acl_list_all_dev:
+            return sys_rsbac_acl_list_all_dev(k_arg.acl_list_all_dev.ta_number,
+                                              k_arg.acl_list_all_dev.id_p,
+                                              k_arg.acl_list_all_dev.maxnum);
+          case RSYS_acl_list_all_user:
+            return sys_rsbac_acl_list_all_user(k_arg.acl_list_all_user.ta_number,
+                                               k_arg.acl_list_all_user.id_p,
+                                               k_arg.acl_list_all_user.maxnum);
+          case RSYS_acl_list_all_group:
+            return sys_rsbac_acl_list_all_group(k_arg.acl_list_all_group.ta_number,
+                                                k_arg.acl_list_all_group.id_p,
+                                                k_arg.acl_list_all_group.maxnum);
+#endif
+#ifdef CONFIG_RSBAC_REG
+          case RSYS_reg:
+            return sys_rsbac_reg(k_arg.reg.handle,
+                                 k_arg.reg.arg);
+#endif
+#ifdef CONFIG_RSBAC_UM
+          case RSYS_um_auth_name:
+            return sys_rsbac_um_auth_name(k_arg.um_auth_name.name,
+                                          k_arg.um_auth_name.pass);
+          case RSYS_um_auth_uid:
+            return sys_rsbac_um_auth_uid(k_arg.um_auth_uid.uid,
+                                         k_arg.um_auth_uid.pass);
+          case RSYS_um_add_user:
+            return sys_rsbac_um_add_user(k_arg.um_add_user.ta_number,
+                                         k_arg.um_add_user.uid,
+                                         k_arg.um_add_user.entry_p,
+                                         k_arg.um_add_user.pass,
+                                         k_arg.um_add_user.ttl);
+          case RSYS_um_add_group:
+            return sys_rsbac_um_add_group(k_arg.um_add_group.ta_number,
+                                          k_arg.um_add_group.gid,
+                                          k_arg.um_add_group.entry_p,
+                                          k_arg.um_add_group.pass,
+                                          k_arg.um_add_group.ttl);
+          case RSYS_um_add_gm:
+            return sys_rsbac_um_add_gm(k_arg.um_add_gm.ta_number,
+                                       k_arg.um_add_gm.uid,
+                                       k_arg.um_add_gm.gid,
+                                       k_arg.um_add_gm.ttl);
+          case RSYS_um_mod_user:
+            return sys_rsbac_um_mod_user(k_arg.um_mod_user.ta_number,
+                                         k_arg.um_mod_user.uid,
+                                         k_arg.um_mod_user.mod,
+                                         k_arg.um_mod_user.data_p);
+          case RSYS_um_mod_group:
+            return sys_rsbac_um_mod_group(k_arg.um_mod_group.ta_number,
+                                          k_arg.um_mod_group.gid,
+                                          k_arg.um_mod_group.mod,
+                                          k_arg.um_mod_group.data_p);
+          case RSYS_um_remove_user:
+            return sys_rsbac_um_remove_user(k_arg.um_remove_user.ta_number,
+                                            k_arg.um_remove_user.uid);
+          case RSYS_um_remove_group:
+            return sys_rsbac_um_remove_group(k_arg.um_remove_group.ta_number,
+                                             k_arg.um_remove_group.gid);
+          case RSYS_um_remove_gm:
+            return sys_rsbac_um_remove_gm(k_arg.um_remove_gm.ta_number,
+                                          k_arg.um_remove_gm.uid,
+                                          k_arg.um_remove_gm.gid);
+          case RSYS_um_user_exists:
+            return sys_rsbac_um_user_exists(k_arg.um_user_exists.ta_number,
+                                            k_arg.um_user_exists.uid);
+          case RSYS_um_get_next_user:
+            return sys_rsbac_um_get_next_user(k_arg.um_get_next_user.ta_number,
+                                              k_arg.um_get_next_user.old_user,
+                                              k_arg.um_get_next_user.next_user_p);
+          case RSYS_um_group_exists:
+            return sys_rsbac_um_group_exists(k_arg.um_group_exists.ta_number,
+                                            k_arg.um_group_exists.gid);
+          case RSYS_um_get_group_list:
+            return sys_rsbac_um_get_group_list(k_arg.um_get_group_list.ta_number,
+                                               k_arg.um_get_group_list.vset,
+                                               k_arg.um_get_group_list.group_array,
+                                               k_arg.um_get_group_list.maxnum);
+          case RSYS_um_set_pass:
+            return sys_rsbac_um_set_pass(k_arg.um_set_pass.uid,
+                                         k_arg.um_set_pass.old_pass,
+                                         k_arg.um_set_pass.new_pass);
+          case RSYS_um_set_pass_name:
+            return sys_rsbac_um_set_pass_name(k_arg.um_set_pass_name.name,
+                                         k_arg.um_set_pass_name.old_pass,
+                                         k_arg.um_set_pass_name.new_pass);
+          case RSYS_um_add_onetime:
+            return sys_rsbac_um_add_onetime(k_arg.um_add_onetime.uid,
+                                         k_arg.um_add_onetime.old_pass,
+                                         k_arg.um_add_onetime.new_pass,
+                                         k_arg.um_add_onetime.ttl);
+          case RSYS_um_add_onetime_name:
+            return sys_rsbac_um_add_onetime_name(k_arg.um_add_onetime_name.name,
+                                         k_arg.um_add_onetime_name.old_pass,
+                                         k_arg.um_add_onetime_name.new_pass,
+                                         k_arg.um_add_onetime_name.ttl);
+          case RSYS_um_remove_all_onetime:
+            return sys_rsbac_um_remove_all_onetime(k_arg.um_remove_all_onetime.uid,
+                                         k_arg.um_remove_all_onetime.old_pass);
+          case RSYS_um_remove_all_onetime_name:
+            return sys_rsbac_um_remove_all_onetime_name(k_arg.um_remove_all_onetime_name.name,
+                                         k_arg.um_remove_all_onetime_name.old_pass);
+          case RSYS_um_count_onetime:
+            return sys_rsbac_um_count_onetime(k_arg.um_count_onetime.uid,
+                                         k_arg.um_count_onetime.old_pass);
+          case RSYS_um_count_onetime_name:
+            return sys_rsbac_um_count_onetime_name(k_arg.um_count_onetime_name.name,
+                                         k_arg.um_count_onetime_name.old_pass);
+          case RSYS_um_set_group_pass:
+            return sys_rsbac_um_set_group_pass(k_arg.um_set_group_pass.gid,
+                                               k_arg.um_set_group_pass.new_pass);
+          case RSYS_um_check_account:
+            return sys_rsbac_um_check_account(k_arg.um_check_account.uid);
+          case RSYS_um_get_max_history:
+            return sys_rsbac_um_get_max_history(k_arg.um_get_max_history.ta_number,
+                                                k_arg.um_get_max_history.uid);
+          case RSYS_um_get_max_history_name:
+            return sys_rsbac_um_get_max_history_name(k_arg.um_get_max_history_name.ta_number,
+                                                     k_arg.um_get_max_history_name.name);
+          case RSYS_um_set_max_history:
+            return sys_rsbac_um_set_max_history(k_arg.um_set_max_history.ta_number,
+                                                k_arg.um_set_max_history.uid,
+                                                k_arg.um_set_max_history.max_history);
+          case RSYS_um_set_max_history_name:
+            return sys_rsbac_um_set_max_history_name(k_arg.um_set_max_history_name.ta_number,
+                                                k_arg.um_set_max_history_name.name,
+                                                k_arg.um_set_max_history_name.max_history);
+          case RSYS_um_select_vset:
+            return sys_rsbac_um_select_vset(k_arg.um_select_vset.vset);
+#endif
+#ifdef CONFIG_RSBAC_UDF
+          case RSYS_udf_flush_cache:
+            return sys_rsbac_udf_flush_cache();
+#endif
+
+#ifdef CONFIG_RSBAC_LIST_TRANS
+          case RSYS_list_ta_begin_name:
+            return sys_rsbac_list_ta_begin_name(k_arg.list_ta_begin.ttl,
+                                           k_arg.list_ta_begin_name.ta_number_p,
+                                           k_arg.list_ta_begin_name.commit_uid,
+                                           k_arg.list_ta_begin_name.name,
+                                           k_arg.list_ta_begin_name.password);
+          case RSYS_list_ta_begin:
+            return sys_rsbac_list_ta_begin(k_arg.list_ta_begin.ttl,
+                                           k_arg.list_ta_begin.ta_number_p,
+                                           k_arg.list_ta_begin.commit_uid,
+                                           k_arg.list_ta_begin.password);
+          case RSYS_list_ta_refresh:
+            return sys_rsbac_list_ta_refresh(k_arg.list_ta_refresh.ttl,
+                                             k_arg.list_ta_refresh.ta_number,
+                                             k_arg.list_ta_refresh.password);
+          case RSYS_list_ta_commit:
+            return sys_rsbac_list_ta_commit(k_arg.list_ta_commit.ta_number,
+                                            k_arg.list_ta_commit.password);
+          case RSYS_list_ta_forget:
+            return sys_rsbac_list_ta_forget(k_arg.list_ta_forget.ta_number,
+                                            k_arg.list_ta_forget.password);
+#endif
+
+          case RSYS_list_all_dev:
+            return sys_rsbac_list_all_dev(k_arg.list_all_dev.ta_number,
+                                          k_arg.list_all_dev.id_p,
+                                          k_arg.list_all_dev.maxnum);
+          case RSYS_list_all_user:
+            return sys_rsbac_list_all_user(k_arg.list_all_user.ta_number,
+                                           k_arg.list_all_user.id_p,
+                                           k_arg.list_all_user.maxnum);
+          case RSYS_list_all_group:
+            return sys_rsbac_list_all_group(k_arg.list_all_group.ta_number,
+                                            k_arg.list_all_group.id_p,
+                                            k_arg.list_all_group.maxnum);
+	case RSYS_list_all_ipc:
+		return sys_rsbac_list_all_ipc(k_arg.list_all_ipc.
+					       ta_number,
+					       k_arg.list_all_ipc.id_p,
+					       k_arg.list_all_ipc.maxnum);
+
+          case RSYS_version:
+            return RSBAC_VERSION_NR;
+          case RSYS_stats:
+            return sys_rsbac_stats();
+          case RSYS_check:
+            return sys_rsbac_check(k_arg.check.correct, k_arg.check.check_inode);
+#if defined(CONFIG_RSBAC_INIT_DELAY)
+          case RSYS_init:
+            return sys_rsbac_init(k_arg.init.root_dev);
+#endif
+
+          default:
+            return -RSBAC_EINVALIDREQUEST;
+        }
+      }
+    }
+
+/* end of syscalls.c */
diff --git a/security/Kconfig b/security/Kconfig
index bf4ec46..acfe7da 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -4,6 +4,8 @@
 
 menu "Security options"
 
+source "rsbac/Kconfig"
+
 source security/keys/Kconfig
 
 config SECURITY_DMESG_RESTRICT
