/**************************************/
/* Rule Set Based Access Control      */
/* Author and (c) 1999,2000: Amon Ott */
/* Data structures                    */
/* Last modified: 29/Feb/2000         */
/**************************************/

#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 <asm/semaphore.h>
#include <rsbac/types.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
#include <asm/spinlock.h>
#else
#include <linux/spinlock.h>
#endif
#include <rsbac/pm_types.h>
#include <rsbac/rc_types.h>
#include <rsbac/aci.h>
#include <rsbac/debug.h>
#endif /* __KERNEL__ */

#include <rsbac/ms_strings.h>

/* 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 FD filename gets a suffix for the list number (see RSBAC_NR_FD_LISTS),*/
/* so we have RSBAC_NR_FD_LISTS files for file/dir ACI and one for user ACI. */
/* The dynamic data structures for PM, RC and ACL are kept in their own files.*/
/* All user access to these files will be denied.                            */
/* Backups are kept in FILENAMEb.                                            */

#ifdef __KERNEL__
#define RSBAC_LOG_BUF_LEN (16384)

#define RSBAC_ACI_PATH          "rsbac"
#define RSBAC_ACI_FD_NAME       "fd_aci."
#define RSBAC_ACI_USER_NAME     "useraci"
#define RSBAC_ACI_DEV_NAME      "devaci"
/* dir creation mode for discretionary access control: rwx for user only*/
#define RSBAC_ACI_DIR_MODE       (S_IFDIR | S_IRWXU)
/* 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
/* maximum to get by kmalloc, if more, vmalloc is used */
#define RSBAC_MAX_KMALLOC (1 << 16)
/* max size for write_chunks */
#define RSBAC_MAX_WRITE_CHUNK ((1 << 15) - 1)

/* Since we will use a simple hash function for file/dir aci, we define   */
/* the table size here. WARNING: If this value is changed, aci data on    */
/* disk may become invalid and should be converted explicitly!            */
/* To remain compliant with all file systems, this value should not       */
/* exceed 100 (8.3 convention: 0-99 + b). */

#define RSBAC_NR_FD_LISTS 30

#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 RSBAC_FD_ACI_VERSION 4

struct rsbac_file_dir_aci_t            
  {
    u_long                      id;               /* file system inode number */
    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 */
    __u8                        object_category;  /* FC (enum rsbac_object_category_t) */
    __u8                        data_type;        /* SIM (enum rsbac_data_type_t) */
    rsbac_pm_object_class_id_t  pm_object_class;  /* PM  */
    rsbac_pm_tp_id_t            pm_tp;            /* PM (for FILE only) */
    __u8                        pm_object_type;   /* PM (enum rsbac_pm_object_type_t) */
    rsbac_ms_scanned_t          ms_scanned;       /* MS (for FILE only) */
    __u8                        ms_trusted;       /* MS (for FILE only) (boolean) */
    __u8                        ms_sock_trusted_tcp; /* MS (for FILE only) (enum rsbac_ms_sock_trusted_t) */
    __u8                        ms_sock_trusted_udp; /* MS (for FILE only) (enum rsbac_ms_sock_trusted_t) */
    rsbac_ff_flags_t            ff_flags;         /* FF */
    rsbac_rc_type_id_t          rc_type_fd;       /* RC */
    rsbac_rc_role_id_t          rc_force_role;    /* RC */
    __u8                        auth_may_setuid;  /* AUTH (boolean) */
    __u8                        auth_may_set_cap; /* AUTH (boolean) */
    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 */
    };

#define RSBAC_FD_NR_ATTRIBUTES 20
#define RSBAC_FD_ATTR_LIST { \
      A_security_level, \
      A_mac_trusted_for_user, \
      A_mac_categories, \
      A_object_category, \
      A_data_type, \
      A_pm_object_class, \
      A_pm_tp, \
      A_pm_object_type, \
      A_ms_scanned, \
      A_ms_trusted, \
      A_ms_sock_trusted_tcp, \
      A_ms_sock_trusted_udp, \
      A_ff_flags, \
      A_rc_type_fd, \
      A_rc_force_role, \
      A_auth_may_setuid, \
      A_auth_may_set_cap, \
      A_log_array_low, \
      A_log_array_high, \
      A_log_program_based \
      }

#define RSBAC_FD_OLD_ACI_VERSION 3

struct rsbac_file_dir_old_aci_t            
  {
    u_long                      id;               /* file system inode number */
    __u8                        sec_level;        /* MAC (enum rsbac_security_level_t) */
    rsbac_old_uid_t             mac_trusted_for_user; /* MAC (for FILE only) */
    rsbac_mac_category_vector_t mac_categories;   /* MAC category set */
    __u8                        object_category;  /* FC (enum rsbac_object_category_t) */
    __u8                        data_type;        /* SIM (enum rsbac_data_type_t) */
    rsbac_pm_object_class_id_t  pm_object_class;  /* PM  */
    rsbac_pm_tp_id_t            pm_tp;            /* PM (for FILE only) */
    __u8                        pm_object_type;   /* PM (enum rsbac_pm_object_type_t) */
    rsbac_ms_scanned_t          ms_scanned;       /* MS (for FILE only) */
    __u8                        ms_trusted;       /* MS (for FILE only) (boolean) */
    __u8                        ms_sock_trusted_tcp; /* MS (for FILE only) (enum rsbac_ms_sock_trusted_t) */
    __u8                        ms_sock_trusted_udp; /* MS (for FILE only) (enum rsbac_ms_sock_trusted_t) */
    rsbac_ff_flags_t            ff_flags;         /* FF */
    rsbac_rc_type_id_t          rc_type_fd;       /* RC */
    rsbac_rc_role_id_t          rc_force_role;    /* RC */
    __u8                        auth_may_setuid;  /* AUTH (boolean) */
    __u8                        auth_may_set_cap; /* AUTH (boolean) */
    rsbac_log_array_t           log_array_low;    /* file/dir based logging, */
    rsbac_log_array_t           log_array_high;   /* high and low bits */
    };

#define RSBAC_FD_OLD_OLD_ACI_VERSION 2

struct rsbac_file_dir_old_old_aci_t            
    {
             u_long                     id;     /* file system inode number */
      enum   rsbac_old_security_level_t sec_level;       /* MAC */
             rsbac_old_uid_t            mac_trusted_for_user; /* MAC (for FILE only) */
      enum   rsbac_object_category_t    object_category; /* FC */
      enum   rsbac_data_type_t          data_type;       /* SIM */
             rsbac_program_type_t       program_type;    /* CWI */
             rsbac_pm_object_class_id_t pm_object_class; /* PM  */
             rsbac_pm_tp_id_t           pm_tp;           /* PM (for FILE only) */
      enum   rsbac_pm_object_type_t     pm_object_type;  /* PM */
             rsbac_ms_scanned_t         ms_scanned;      /* MS (for FILE only) */
             boolean                    ms_trusted;      /* MS (for FILE only) */
      enum   rsbac_ms_sock_trusted_t    ms_sock_trusted_tcp; /* MS (for FILE only) */
      enum   rsbac_ms_sock_trusted_t    ms_sock_trusted_udp; /* MS (for FILE only) */
             rsbac_ff_flags_t           ff_flags;        /* FF */
             rsbac_log_array_t          log_array_low;   /* file/dir based logging, */
             rsbac_log_array_t          log_array_high;  /* high and low bits */
    };

#ifdef __KERNEL__

/* Since all files/dirs will be organized in double linked lists, we must  */
/* have list items and a list head.                                        */

struct rsbac_file_dir_list_item_t
    {
      struct rsbac_file_dir_aci_t         aci;
      struct rsbac_file_dir_list_item_t * prev;
      struct rsbac_file_dir_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_file_dir_list_head_t
    {
      struct rsbac_file_dir_list_item_t * head;
      struct rsbac_file_dir_list_item_t * tail;
      struct rsbac_file_dir_list_item_t * curr;
      rwlock_t                            lock;
      boolean                             dirty;
      u_long                              count;
    };

/* As there will be a separate table of file/dir lists for each mounted   */
/* device, we need a type for these tables and a list of devices.         */

typedef struct rsbac_file_dir_list_head_t
        rsbac_fd_list_head_table_t [RSBAC_NR_FD_LISTS];

/* The list of devices is also a double linked list, so we define list    */
/* items and a list head.                                                 */

struct rsbac_device_list_item_t
    {
      kdev_t                              id;  /* set to 0 before deletion */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
      struct dentry                     * d_covers;
#endif
      rsbac_fd_list_head_table_t          head_table;
      struct dentry                     * rsbac_dir_dentry_p;
      struct rsbac_device_list_item_t   * prev;
      struct rsbac_device_list_item_t   * next;
      boolean                             no_write;
    };
    
/* 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;
      rwlock_t                          lock;
      u_int                             count;
    };

#endif /* __KERNEL__ */

/* OK, now we define the block/char device ACI, holding all dev information */
/* the ADF needs for decisions.                                           */

/* Caution: whenever ACI changes, version should be increased!            */

#define RSBAC_DEV_ACI_VERSION 3

struct rsbac_dev_aci_t            
  {                                
#ifdef __KERNEL__
    struct rsbac_dev_t                id;     /* dev type and number */
#endif /* __KERNEL__ */
           rsbac_security_level_t     sec_level;       /* MAC */
           rsbac_mac_category_vector_t mac_categories;   /* MAC category set */
           __u8                       object_category; /* FC (enum rsbac_object_category_t) */
           __u8                       data_type;       /* SIM (enum rsbac_data_type_t) */
           __u8                       mac_check;       /* MAC (boolean) */
           __u8                       pm_object_type;  /* PM (enum rsbac_pm_object_type_t) */
           rsbac_pm_object_class_id_t pm_object_class; /* dev only */
           rsbac_rc_type_id_t         rc_type;          /* RC */
           rsbac_log_array_t          log_array_low;   /* dev based logging, */
           rsbac_log_array_t          log_array_high;  /* high and low bits */
  };

#define RSBAC_DEV_NR_ATTRIBUTES 10
#define RSBAC_DEV_ATTR_LIST { \
      A_security_level, \
      A_mac_categories, \
      A_object_category, \
      A_data_type, \
      A_mac_check, \
      A_pm_object_type, \
      A_pm_object_class, \
      A_rc_type, \
      A_log_array_low, \
      A_log_array_high \
      }

#define RSBAC_DEV_OLD_ACI_VERSION 2

struct rsbac_dev_old_aci_t            
  {                                
#ifdef __KERNEL__
    struct rsbac_dev_t                id;     /* dev type and number */
#endif /* __KERNEL__ */
           __u8                       sec_level;       /* MAC */
           rsbac_mac_category_vector_t mac_categories;   /* MAC category set */
           __u8                       object_category; /* FC (enum rsbac_object_category_t) */
           __u8                       data_type;       /* SIM (enum rsbac_data_type_t) */
           __u8                       mac_check;       /* MAC (boolean) */
           __u8                       pm_object_type;  /* PM (enum rsbac_pm_object_type_t) */
           rsbac_pm_object_class_id_t pm_object_class; /* dev only */
           rsbac_rc_type_id_t         rc_type;          /* RC */
           rsbac_log_array_t          log_array_low;   /* dev based logging, */
           rsbac_log_array_t          log_array_high;  /* high and low bits */
  };

#define RSBAC_DEV_OLD_OLD_ACI_VERSION 1

struct rsbac_dev_old_old_aci_t
    {
#ifdef __KERNEL__
      struct rsbac_dev_t                id;     /* dev type and number */
#endif /* __KERNEL__ */
      enum   rsbac_old_security_level_t sec_level;       /* MAC */
      enum   rsbac_object_category_t    object_category; /* FC */
      enum   rsbac_data_type_t          data_type;       /* SIM */
             boolean                    mac_check;       /* MAC */
      enum   rsbac_pm_object_type_t     pm_object_type;  /* PM */
             rsbac_pm_object_class_id_t pm_object_class; /* dev only */
             rsbac_log_array_t          log_array_low;   /* dev based logging, */
             rsbac_log_array_t          log_array_high;  /* high and low bits */
    };

#ifdef __KERNEL__

/* Since all devs will be organized in double linked lists, we must  */
/* have list items and a list head.                                        */

struct rsbac_dev_list_item_t
    {
      struct rsbac_dev_aci_t         aci;
      struct rsbac_dev_list_item_t * prev;
      struct rsbac_dev_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_dev_list_head_t
    {
      struct rsbac_dev_list_item_t * head;
      struct rsbac_dev_list_item_t * tail;
      struct rsbac_dev_list_item_t * curr;
      rwlock_t                       lock;
      boolean                        dirty;
      u_int                          count;
      boolean                        no_write;
    };

#endif /* __KERNEL__ */

/**************************************************************************/
/* Next we define the ipc ACI, holding all ipc information                */
/* the ADF needs for decisions.                                           */

struct rsbac_ipc_aci_t            
    {                                
      struct rsbac_ipc_t                id;
             rsbac_security_level_t     sec_level; /* enum rsbac_security_level_t */
             rsbac_mac_category_vector_t mac_categories;   /* MAC category set */
             __u8                       object_category; /* enum rsbac_object_category_t */
             __u8                       data_type; /* enum rsbac_data_type_t */
             rsbac_pm_object_class_id_t pm_object_class; /* ipc only */
             rsbac_pm_purpose_id_t      pm_ipc_purpose;
             __u8                       pm_object_type; /* enum rsbac_pm_object_type_t */
             char                       ms_backbuf[RSBAC_MS_MAX_STR_LEN];
             int                        ms_buflen;
             int                        ms_str_nr[RSBAC_MS_NR_MALWARE];
             int                        ms_str_offset[RSBAC_MS_NR_MALWARE];
             rsbac_ms_scanned_t         ms_scanned;
             rsbac_rc_type_id_t         rc_type;          /* RC */
    };

#define RSBAC_IPC_NR_ATTRIBUTES 13
#define RSBAC_IPC_ATTR_LIST { \
      A_security_level, \
      A_mac_categories, \
      A_object_category, \
      A_data_type, \
      A_pm_object_class, \
      A_pm_ipc_purpose, \
      A_pm_object_type, \
      A_ms_backbuf, \
      A_ms_buflen, \
      A_ms_str_nr, \
      A_ms_str_offset, \
      A_ms_scanned, \
      A_rc_type \
      }

#ifdef __KERNEL__

/* Since all ipcs will be organized in a double linked list, we must */
/* have list items and a list head.                                       */

struct rsbac_ipc_list_item_t
    {
      struct rsbac_ipc_aci_t         aci;
      struct rsbac_ipc_list_item_t * prev;
      struct rsbac_ipc_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_ipc_list_head_t
    {
      struct rsbac_ipc_list_item_t  * head;
      struct rsbac_ipc_list_item_t  * tail;
      struct rsbac_ipc_list_item_t  * curr;
      rwlock_t                        lock;
      u_long                          count;
    };

#endif /* __KERNEL__ */

/* The user ACI holds all user information the ADF needs. */

/* Caution: whenever ACI changes, version should be increased!            */

#define RSBAC_USER_ACI_VERSION 3

struct rsbac_user_aci_t
    {
      rsbac_uid_t              id;
      rsbac_pseudo_t           pseudo;
      rsbac_security_level_t   access_appr;    /* enum rsbac_security_level_t */
      rsbac_mac_category_vector_t mac_categories;   /* MAC category set */
      __u8                     system_role;    /* enum rsbac_system_role_t */
      rsbac_pm_task_set_id_t   pm_task_set;
      __u8                     pm_role;        /* enum rsbac_pm_role_t */
      rsbac_rc_role_id_t       rc_def_role;    /* RC */
      rsbac_request_vector_t   log_user_based; /* User based logging */
    };

#define RSBAC_USER_OLD_ACI_VERSION 2

struct rsbac_user_old_aci_t
    {
      rsbac_old_uid_t          id;
      rsbac_pseudo_t           pseudo;
      __u8                     access_appr;    /* enum rsbac_security_level_t */
      rsbac_mac_category_vector_t mac_categories;   /* MAC category set */
      __u8                     system_role;    /* enum rsbac_system_role_t */
      rsbac_pm_task_set_id_t   pm_task_set;
      __u8                     pm_role;        /* enum rsbac_pm_role_t */
      rsbac_rc_role_id_t       rc_def_role;    /* RC */
    };

#define RSBAC_USER_OLD_OLD_ACI_VERSION 1

struct rsbac_user_old_old_aci_t
    {
             rsbac_old_uid_t              id;
             rsbac_pseudo_t               pseudo;
      enum   rsbac_old_security_level_t   access_appr;
      enum   rsbac_system_role_t          system_role;
      enum   rsbac_integrity_role_t       integrity_role;
             rsbac_cwi_relation_id_t      cwi_rel_id;
             rsbac_pm_task_set_id_t       pm_task_set;
      enum   rsbac_pm_role_t              pm_role;
    };

#define RSBAC_USER_NR_ATTRIBUTES 8
#define RSBAC_USER_ATTR_LIST { \
      A_pseudo, \
      A_security_level, \
      A_mac_categories, \
      A_system_role, \
      A_pm_task_set, \
      A_pm_role, \
      A_rc_def_role, \
      A_log_user_based \
      }

#ifdef __KERNEL__

/* Like our objects the users will be held in a double linked list, */
/* so we need items and a head.                                     */

struct rsbac_user_list_item_t
    {
      struct rsbac_user_aci_t         aci;
      struct rsbac_user_list_item_t * prev;
      struct rsbac_user_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_user_list_head_t
    {
      struct rsbac_user_list_item_t * head;
      struct rsbac_user_list_item_t * tail;
      struct rsbac_user_list_item_t * curr;
      rwlock_t                        lock;
      boolean                         dirty;
      u_int                           count;
      boolean                         no_write;
    };
    
/* The last component for ADF decisions is the process ACI. */
    
struct rsbac_process_aci_t
    {
      rsbac_pid_t                 id;
#ifdef CONFIG_RSBAC_USE_RSBAC_OWNER
      rsbac_uid_t                 owner;
#endif
      rsbac_security_level_t      owner_sec_level;     /* enum rsbac_security_level_t */
      rsbac_mac_category_vector_t mac_owner_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 */
      __u8                        mac_auto;            /* auto-curr-sec-level?, boolean */
      __u8                        mac_trusted;         /* trusted process?, boolean */
      rsbac_pm_tp_id_t            pm_tp;
      rsbac_pm_task_id_t          pm_current_task;
      __u8                        pm_process_type;     /* enum rsbac_pm_process_type_t */
      __u8                        ms_trusted;          /* MS, boolean */
      __u8                        ms_sock_trusted_tcp; /* MS, enum rsbac_ms_sock_trusted_t */
      __u8                        ms_sock_trusted_udp; /* MS, enum rsbac_ms_sock_trusted_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 */
      __u8                        auth_may_setuid;     /* AUTH (boolean) */
      __u8                        auth_may_set_cap;    /* AUTH (boolean) */
      rsbac_request_vector_t      log_program_based;   /* Program / process based logging */
    };
    
#endif /* __KERNEL__ */

#define RSBAC_PROCESS_NR_ATTRIBUTES 23
#define RSBAC_PROCESS_ATTR_LIST { \
      A_owner, \
      A_security_level, \
      A_mac_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_auto, \
      A_mac_trusted, \
      A_pm_tp, \
      A_pm_current_task, \
      A_pm_process_type, \
      A_ms_trusted, \
      A_ms_sock_trusted_tcp, \
      A_ms_sock_trusted_udp, \
      A_rc_role, \
      A_rc_type, \
      A_rc_force_role, \
      A_auth_may_setuid, \
      A_auth_may_set_cap, \
      A_log_program_based \
      }

#ifdef __KERNEL__

/* The processes are also kept in a list, although there is a limited  */
/* number, because this will probably change in future Linux versions. */
    
struct rsbac_process_list_item_t
    {
      struct rsbac_process_aci_t         aci;
      struct rsbac_process_list_item_t * prev;
      struct rsbac_process_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_process_list_head_t
    {
      struct rsbac_process_list_item_t * head;
      struct rsbac_process_list_item_t * tail;
      struct rsbac_process_list_item_t * curr;
      rwlock_t                           lock;
      u_long                             count;
    };
    
#endif /* __KERNEL__ */

/**********************************************/
/*              Default values                */
/**********************************************/

#ifdef CONFIG_RSBAC_DEF_INHERIT
#define DEFAULT_FD_ACI \
    { \
      0,                    /* id */ \
      SL_inherit,           /* security_level (MAC) */ \
      RSBAC_NO_USER,        /* mac_trusted_for_user (MAC) */ \
      RSBAC_MAC_INHERIT_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_inherit,           /* object_category (FC) */ \
      DT_inherit,           /* data_type      (SIM) */ \
      0,                    /* pm_tp_id       (PM) */ \
      0,                    /* pm_object_class_id (PM) */ \
      PO_none,              /* pm_object_type  (PM) */ \
      MS_unscanned,         /* ms_scanned      (MS) */ \
      FALSE,                /* ms_trusted      (MS) */ \
      MS_not_trusted,       /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,       /* ms_sock_trusted_udp (MS) */ \
      FF_add_inherited,     /* ff_flags (FF): inherit only */ \
      RC_type_inherit_parent, /* rc_type (RC): inherit from parent dir */ \
      RC_default_force_role, /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,                /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,                /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                  /* capabilities for other processes */ \
      -1,                   /* log_array_low  (adf) (log request based) */ \
      -1,                   /* log_array_high (adf) (log request based) */ \
      0                     /* log_program_based (adf) (don't log specially) */ \
    }
#else
#define DEFAULT_FD_ACI \
    { \
      0,                  /* id */ \
      SL_unclassified,    /* security_level (MAC) */ \
      RSBAC_NO_USER,      /* mac_trusted_for_user (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_general,         /* object_category (FC) */ \
      DT_none,            /* data_type      (SIM) */ \
      0,                  /* pm_tp_id       (PM) */ \
      0,                  /* pm_object_class_id (PM) */ \
      PO_none,            /* pm_object_type  (PM) */ \
      MS_unscanned,       /* ms_scanned      (MS) */ \
      FALSE,              /* ms_trusted      (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      0,                  /* ff_flags (FF) */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general fd type */ \
      RC_default_force_role,  /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,                 /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,                 /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      -1,                 /* log_array_low  (adf) (log request based) */ \
      -1,                 /* log_array_high (adf) (log request based) */ \
      0                   /* log_program_based (adf) (don't log specially) */ \
    }
#endif /* DEF_INHERIT */

#define DEFAULT_ROOT_DIR_ACI \
    { \
      0,                  /* id */ \
      SL_unclassified,    /* security_level (MAC) */ \
      RSBAC_NO_USER,      /* mac_trusted_for_user (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_general,         /* object_category (FC) */ \
      DT_none,            /* data_type      (SIM) */ \
      0,                  /* pm_tp_id       (PM) */ \
      0,                  /* pm_object_class_id (PM) */ \
      PO_none,            /* pm_object_type  (PM) */ \
      MS_unscanned,       /* ms_scanned      (MS) */ \
      FALSE,              /* ms_trusted      (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      0,                  /* ff_flags (FF) */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general fd type */ \
      RC_default_root_dir_force_role,  /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,                 /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,                 /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      -1,                 /* log_array_low  (adf) (log request based) */ \
      -1,                 /* log_array_high (adf) (log request based) */ \
      0                   /* log_program_based (adf) (don't log specially) */ \
    }

/* When adding an rsbac-internal file item, we need another default aci    */
#define DEFAULT_RSBAC_ACI \
    { /* see above */ \
      0, \
      SL_max, \
      RSBAC_NO_USER,      /* mac_trusted_for_user (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_security, \
      DT_SI, \
      0, \
      0, \
      PO_none, \
      MS_unscanned,       /* ms_scanned      (MS) */ \
      FALSE,              /* ms_trusted      (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      FF_read_only,       /* ff_flags (FF) */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general fd type */ \
      RC_default_force_role,  /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,                 /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,                 /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      -1,                 /* log_array_low  (adf) (log request based) */ \
      -1,                 /* log_array_high (adf) (log request based) */ \
      0                   /* log_program_based (adf) (don't log specially) */ \
    }

/* And then there are rsbac-internal dir items    */
#define DEFAULT_RSBAC_DIR_ACI \
    { /* see above */ \
      0, \
      SL_rsbac_internal, \
      RSBAC_NO_USER,      /* mac_trusted_for_user (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_security, \
      DT_SI, \
      0, \
      0, \
      PO_none, \
      MS_unscanned,       /* ms_scanned      (MS) */ \
      FALSE,              /* ms_trusted      (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      FF_read_only,       /* ff_flags (FF) */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general fd type */ \
      RC_default_force_role,  /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,                 /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,                 /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      -1,                 /* log_array_low  (adf) (log request based) */ \
      -1,                 /* log_array_high (adf) (log request based) */ \
      0                   /* log_program_based (adf) (don't log specially) */ \
    }

/* default for new dev items */

#ifdef __KERNEL__
#define DEFAULT_DEV_ACI \
    { \
      {D_none,0},                  /* id */ \
      SL_unclassified,    /* security_level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_general,         /* object_category (FC) */ \
      DT_none,            /* data_type      (SIM) */ \
      FALSE,              /* mac_check      (MAC) */ \
      PO_none,            /* pm_object_type  (PM) */ \
      0,                  /* pm_object_class_id (PM) */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general fd type */ \
      -1,                 /* log_array_low  (adf) (log request based) */ \
      -1                  /* log_array_high (adf) (log request based) */ \
    }
#else
#define DEFAULT_DEV_ACI \
    { \
      SL_unclassified,    /* security_level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_general,         /* object_category (FC) */ \
      DT_none,            /* data_type      (SIM) */ \
      FALSE,              /* mac_check      (MAC) */ \
      PO_none,            /* pm_object_type  (PM) */ \
      0,                  /* pm_object_class_id (PM) */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general fd type */ \
      -1,                 /* log_array_low  (adf) (log request based) */ \
      -1                  /* log_array_high (adf) (log request based) */ \
    }
#endif /* __KERNEL__ */

/* default for new IPC items */

#define DEFAULT_IPC_ACI \
    { \
      {I_none,{0}},       /* id */ \
      SL_unclassified,  /* security_level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      OC_general,       /* object_category (FC) */ \
      DT_none,          /* data_type      (SIM) */ \
      RSBAC_PM_IPC_OBJECT_CLASS_ID, /* pm_object_class_id (PM) */ \
      0,                /* pm_ipc_purpose  (PM) */ \
      PO_ipc,           /* pm_object_type  (PM) */ \
      "",               /* ms_backbuf */ \
      0,                /* ms_buflen */ \
      {0,0,0,0,0,0,0},  /* ms_str_nr */ \
      {0,0,0,0,0,0,0},  /* ms_offset */ \
      MS_unscanned,     /* ms_scanned */ \
      RSBAC_RC_GENERAL_TYPE /* rc_type (RC): general fd type */ \
    }

/* default for new user items */

#define DEFAULT_U_ACI \
    { \
      RSBAC_NO_USER,      /* id */ \
      (rsbac_pseudo_t) 0, /* pseudo        (logging/PM) */ \
      SL_unclassified,    /* security_level       (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      SR_user,            /* system_role (MAC, FC, SIM) */ \
      0,                  /* pm_task_set_id       (PM) */ \
      PR_user,            /* pm_role               (PM) */ \
      RSBAC_RC_GENERAL_ROLE, /* rc_def_role (RC): default to general role */ \
      0	                  /* log_user_based (adf): no logging */ \
    }

#define DEFAULT_U_SYSADM_ACI \
    { \
      RSBAC_SYSADM_UID,      /* id */ \
      (rsbac_pseudo_t) 0, /* pseudo        (logging/PM) */ \
      SL_unclassified,             /* security_level       (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      SR_administrator,   /* system_role (MAC, FC, SIM) */ \
      0,                  /* pm_task_set_id       (PM) */ \
      PR_system_admin,    /* pm_role               (PM) */ \
      RSBAC_RC_SYSTEM_ADMIN_ROLE, /* rc_def_role (RC): default to sysadm role */ \
      0	                  /* log_user_based (adf): no logging */ \
    }

#define DEFAULT_U_BIN_ACI \
    { \
      RSBAC_BIN_UID,      /* id */ \
      (rsbac_pseudo_t) 0, /* pseudo        (logging/PM) */ \
      SL_unclassified,    /* security_level       (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      SR_administrator,   /* system_role (MAC, FC, SIM) */ \
      0,                  /* pm_task_set_id       (PM) */ \
      PR_user,            /* pm_role               (PM) */ \
      RSBAC_RC_GENERAL_ROLE, /* rc_def_role (RC): default to general role */ \
      0	                  /* log_user_based (adf): no logging */ \
    }

#define DEFAULT_U_SECOFF_ACI \
    { \
      RSBAC_SECOFF_UID,      /* id */ \
      (rsbac_pseudo_t) 0, /* pseudo        (logging/PM) */ \
      SL_unclassified,      /* security_level       (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      SR_security_officer,    /* system_role (MAC, FC, SIM) */ \
      0,                  /* pm_task_set_id       (PM) */ \
      PR_security_officer,    /* pm_role               (PM) */ \
      RSBAC_RC_ROLE_ADMIN_ROLE, /* rc_def_role (RC): default to sysadm role */ \
      0	                  /* log_user_based (adf): no logging */ \
    }

#define DEFAULT_U_DATAPROT_ACI \
    { \
      RSBAC_DATAPROT_UID,      /* id */ \
      (rsbac_pseudo_t) 0, /* pseudo        (logging/PM) */ \
      SL_unclassified,      /* security_level       (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_categories (MAC) */ \
      SR_user,    /* system_role (MAC, FC, SIM) */ \
      0,                  /* pm_task_set_id       (PM) */ \
      PR_data_protection_officer,    /* pm_role               (PM) */ \
      RSBAC_RC_GENERAL_ROLE, /* rc_def_role (RC): default to sysadm role */ \
      0	                  /* log_user_based (adf): no logging */ \
    }

/* default for new process items */

#ifdef CONFIG_RSBAC_USE_RSBAC_OWNER
#define DEFAULT_P_ACI \
    { \
      (rsbac_pid_t) -1,   /* process id */ \
      RSBAC_NO_USER,      /* owner      */ \
      SL_unclassified,    /* owner-sec-level   (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* owner_categories (MAC) */ \
      SL_unclassified,    /* current-sec-level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_curr_categories (MAC) */ \
      SL_max,             /* min-write-open    (MAC) */ \
      RSBAC_MAC_MAX_CAT_VECTOR, /* min_write_categories (MAC) */ \
      SL_unclassified,    /* max-read-open     (MAC) */ \
      RSBAC_MAC_MIN_CAT_VECTOR, /* max_read_categories (MAC) */ \
      TRUE,               /* auto-mac?         (MAC) */ \
      FALSE,              /* trusted?          (MAC) */ \
      0,                  /* PM-TP              (PM) */ \
      0,                  /* PM-current-task    (PM) */ \
      PP_none,            /* PM-proc-type       (PM) */ \
      FALSE,              /* ms_trusted         (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      RSBAC_RC_GENERAL_ROLE, /* rc_role (RC): general role */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general process type */ \
      RC_default_force_role, /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,              /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,              /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      0                   /* log_program_based (adf) (don't log specially) */
    }
#else
#define DEFAULT_P_ACI \
    { \
      (rsbac_pid_t) -1,   /* process id */ \
      SL_unclassified,    /* owner-sec-level   (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* owner_categories (MAC) */ \
      SL_unclassified,    /* current-sec-level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_curr_categories (MAC) */ \
      SL_max,             /* min-write-open    (MAC) */ \
      RSBAC_MAC_MAX_CAT_VECTOR, /* min_write_categories (MAC) */ \
      SL_unclassified,    /* max-read-open     (MAC) */ \
      RSBAC_MAC_MIN_CAT_VECTOR, /* max_read_categories (MAC) */ \
      TRUE,               /* auto-mac?         (MAC) */ \
      FALSE,              /* trusted?          (MAC) */ \
      0,                  /* PM-TP              (PM) */ \
      0,                  /* PM-current-task    (PM) */ \
      PP_none,            /* PM-proc-type       (PM) */ \
      FALSE,              /* ms_trusted         (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      RSBAC_RC_GENERAL_ROLE, /* rc_role (RC): general role */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general process type */ \
      RC_default_force_role, /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,              /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,              /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      0                   /* log_program_based (adf) (don't log specially) */ \
    }
#endif

/* default for init process item */

#ifdef CONFIG_RSBAC_USE_RSBAC_OWNER
#define DEFAULT_INIT_P_ACI \
    { \
      (rsbac_pid_t) 1,    /* process id */ \
      0,    /* owner      */ \
      SL_unclassified,             /* owner-sec-level   (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* owner_categories (MAC) */ \
      SL_unclassified,    /* current-sec-level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_curr_categories (MAC) */ \
      SL_max,             /* min-write-open    (MAC) */ \
      RSBAC_MAC_MAX_CAT_VECTOR, /* min_write_categories (MAC) */ \
      SL_unclassified,    /* max-read-open     (MAC) */ \
      RSBAC_MAC_MIN_CAT_VECTOR, /* max_read_categories (MAC) */ \
      TRUE,               /* auto-mac?         (MAC) */ \
      TRUE,               /* trusted?          (MAC) */ \
      0,                  /* PM-TP              (PM) */ \
      0,                  /* PM-current-task    (PM) */ \
      PP_none,            /* PM-proc-type       (PM) */ \
      FALSE,              /* ms_trusted         (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      RSBAC_RC_SYSTEM_ADMIN_ROLE, /* rc_role (RC): system admin role */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general process type */ \
      RC_default_init_force_role, /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,              /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,              /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      0                   /* log_program_based (adf) (don't log specially) */
    }
#else
#define DEFAULT_INIT_P_ACI \
    { \
      (rsbac_pid_t) 1,    /* process id */ \
      SL_unclassified,             /* owner-sec-level   (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* owner_categories (MAC) */ \
      SL_unclassified,    /* current-sec-level (MAC) */ \
      RSBAC_MAC_DEF_CAT_VECTOR, /* mac_curr_categories (MAC) */ \
      SL_max,             /* min-write-open    (MAC) */ \
      RSBAC_MAC_MAX_CAT_VECTOR, /* min_write_categories (MAC) */ \
      SL_unclassified,    /* max-read-open     (MAC) */ \
      RSBAC_MAC_MIN_CAT_VECTOR, /* max_read_categories (MAC) */ \
      TRUE,               /* auto-mac?         (MAC) */ \
      TRUE,               /* trusted?          (MAC) */ \
      0,                  /* PM-TP              (PM) */ \
      0,                  /* PM-current-task    (PM) */ \
      PP_none,            /* PM-proc-type       (PM) */ \
      FALSE,              /* ms_trusted         (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_tcp (MS) */ \
      MS_not_trusted,     /* ms_sock_trusted_udp (MS) */ \
      RSBAC_RC_SYSTEM_ADMIN_ROLE, /* rc_role (RC): system admin role */ \
      RSBAC_RC_GENERAL_TYPE, /* rc_type (RC): general process type */ \
      RC_default_init_force_role, /* rc_force_role (RC): (see rc_types.h) */ \
      FALSE,              /* auth_may_setuid (AUTH): program may not setuid to any */ \
      FALSE,              /* auth_may_set_cap (AUTH): program may not set setuid */ \
                                   /* capabilities for other processes */ \
      0                   /* log_program_based (adf) (don't log specially) */ \
    }
#endif

/**********************************************/
/*              Declarations                  */
/**********************************************/

#ifdef __KERNEL__
#ifdef CONFIG_RSBAC_REG
extern kdev_t rsbac_root_dev;
#endif

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;

/**********************************************/
/*              Locks                         */
/**********************************************/

extern inline void rsbac_read_lock(rwlock_t * lock_p, u_long * flags_p)
  {
    read_lock(lock_p);
  };

extern inline void rsbac_read_unlock(rwlock_t * lock_p, u_long * flags_p)
  {
    read_unlock(lock_p);
  };

extern inline void rsbac_write_lock(rwlock_t * lock_p, u_long * flags_p)
  {
    write_lock(lock_p);
  };

extern inline void rsbac_write_unlock(rwlock_t * lock_p, u_long * flags_p)
  {
    write_unlock(lock_p);
  };

#endif /* __KERNEL__ */

/**********************************************/
/*          External Declarations             */
/**********************************************/

#ifdef __KERNEL__

extern inline struct dentry *lock_parent(struct dentry *dentry);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,42)
extern inline struct dentry *unlock_dir(struct dentry *dentry);

extern inline void double_lock(struct dentry *d1, struct dentry *d2)
{
	struct semaphore *s1 = &d1->d_inode->i_sem;
	struct semaphore *s2 = &d2->d_inode->i_sem;

	if (s1 != s2) {
		if ((unsigned long) s1 < (unsigned long) s2) {
			struct semaphore *tmp = s2;
			s2 = s1; s1 = tmp;
		}
		down(s1);
	}
	down(s2);
}

extern inline void double_unlock(struct dentry *d1, struct dentry *d2)
{
	struct semaphore *s1 = &d1->d_inode->i_sem;
	struct semaphore *s2 = &d2->d_inode->i_sem;

	up(s1);
	if (s1 != s2)
		up(s2);
	dput(d1);
	dput(d2);
}
#endif

#endif /* __KERNEL__ */

#endif
