/************************************************* */
/* 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,2000: Amon Ott              */
/* Modifications by Stanislav Ievlev               */
/*                                                 */
/* Last modified: 03/Oct/2000                      */
/************************************************* */

#include <linux/string.h>
#include <rsbac/aci.h>
#include <rsbac/adf_main.h>
#include <rsbac/error.h>
#include <rsbac/helpers.h>
#include <rsbac/getname.h>

#ifndef NULL
#define NULL ((void *) 0)
#endif

/************************************************* */
/*           Global Variables                      */
/************************************************* */

/************************************************* */
/*          Internal Help functions                */
/************************************************* */

/* 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(     rsbac_pid_t             pid,
                           rsbac_security_level_t  target_sec_level,
                           rsbac_mac_category_vector_t target_categories,
                           boolean                 set_level)
  {
    union rsbac_target_id_t       i_tid;
    union rsbac_attribute_value_t attr_val_1;
    union rsbac_attribute_value_t attr_val_2;
    
    /* Access to security_level SL_rsbac_internal is never granted. */
    if (target_sec_level == SL_rsbac_internal)
      return(NOT_GRANTED);

    /* trusted process? */
    i_tid.process = pid;
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_mac_trusted,
                       &attr_val_2,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    if (attr_val_2.mac_trusted)
      return(GRANTED);

    /* Get current security level */
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_current_sec_level,
                       &attr_val_1,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* write-up is no problem, but what otherwise? -> auto-adjust */
    if (attr_val_1.current_sec_level > target_sec_level)
      {
        /* if not write up yet: change current_sec_level automatically? */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_auto,
                           &attr_val_1,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* Do not change -> do not grant */
        if (!attr_val_1.mac_auto)
          return(NOT_GRANTED);

        /* Get max. security_level of earlier reads */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_open,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is below that, *-property is violated -> do not grant */
        if (target_sec_level < attr_val_2.max_read_open)
          return(NOT_GRANTED);

        /* adjust current_sec_level, if set_level is true */
        attr_val_1.current_sec_level = target_sec_level;
        if (set_level && (rsbac_set_attr(T_PROCESS,
                                         i_tid,
                                         A_current_sec_level,
                                         attr_val_1)) )
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      } /* end of sec_level auto-section */
      
#ifdef CONFIG_RSBAC_MAC_LIGHT
      else{
        /* Get maximum sec_level for adjusting */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_security_level,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* don't write up */
        if (target_sec_level < attr_val_2.security_level)
          return(NOT_GRANTED);
      }
#endif

    /* Get current categories */
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_mac_curr_categories,
                       &attr_val_1,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* write-up is no problem, but what otherwise? -> auto-adjust */
    if (!( (attr_val_1.mac_categories & target_categories)
           == attr_val_1.mac_categories))
      {
        /* if not write up yet: change mac_curr_categories automatically? */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_auto,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* Do not change -> do not grant */
        if (!attr_val_2.mac_auto)
          return(NOT_GRANTED);

        /* Get max. read_categories of earlier reads */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_categories,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is below that, *-property is violated -> do not grant */
        if (!( (attr_val_2.mac_categories & target_categories)
               == attr_val_2.mac_categories))
          return(NOT_GRANTED);

        /* adjust mac_curr_categories, if set_level is true */
        attr_val_1.mac_categories |= target_categories;
        if (set_level && (rsbac_set_attr(T_PROCESS,
                                         i_tid,
                                         A_mac_curr_categories,
                                         attr_val_1)) )
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      } /* end of category auto-section */
      
#ifdef CONFIG_RSBAC_MAC_LIGHT
      else{
        /* Get maximum categories for adjusting */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_categories,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* don't write up */
        if (!( (attr_val_2.mac_categories & target_categories)
               == attr_val_2.mac_categories))
          return(NOT_GRANTED);
      }
#endif

    /* Get minimum sec_level of earlier writes */
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_min_write_open,
                       &attr_val_2,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* and adjust it, if necessary and set_level is TRUE */
    if (set_level && (attr_val_2.min_write_open > target_sec_level))
      {
        attr_val_2.min_write_open = target_sec_level;
        if (rsbac_set_attr(T_PROCESS,
                           i_tid,
                           A_min_write_open,
                           attr_val_2))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    /* Get minimum categories of earlier writes */
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_min_write_categories,
                       &attr_val_2,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* and adjust it, if necessary and set_level is TRUE */
    if (   set_level
        && !((attr_val_2.mac_categories & target_categories)
             == attr_val_2.mac_categories)
       )
      {
        attr_val_2.mac_categories &= target_categories;
        if (rsbac_set_attr(T_PROCESS,
                           i_tid,
                           A_min_write_categories,
                           attr_val_2))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    /* Everything done, so return */
    return(GRANTED);
  };


/* auto_read() */
/* This function works similar to auto_write() */

static enum rsbac_adf_req_ret_t
           auto_read (     rsbac_pid_t             pid,
                           rsbac_security_level_t  target_sec_level,
                           rsbac_mac_category_vector_t target_categories,
                           boolean                 set_level)
  {
    union rsbac_target_id_t       i_tid;
    union rsbac_attribute_value_t attr_val_1;
    union rsbac_attribute_value_t attr_val_2;
    
    /* Access to security_level SL_rsbac_internal is never granted. */
    if (target_sec_level == SL_rsbac_internal)
      return(NOT_GRANTED);

    /* Get process's current_sec_level */
    i_tid.process = pid;
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_current_sec_level,
                       &attr_val_1,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* read-up is no problem, but otherwise we can try auto-adjust */
    if (attr_val_1.current_sec_level < target_sec_level)
      {
        /* no read-up: Can we adjust current_sec_level? */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_auto,
                           &attr_val_1,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* no -> not granted */
        if (!attr_val_1.mac_auto)
          return(NOT_GRANTED);
      
        /* Get maximum sec_level for adjusting */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_security_level,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* our target is too high up -> not granted */
        if (target_sec_level > attr_val_2.security_level)
          return(NOT_GRANTED);

        /* how about our upper boundary by writes / *-property? */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_min_write_open,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* our target is too high up -> not granted */
        if (target_sec_level > attr_val_2.min_write_open)
          return(NOT_GRANTED);

        /* at last adjust current_sec_level, if set_level is on */
        attr_val_1.current_sec_level = target_sec_level;
        if (set_level && (rsbac_set_attr(T_PROCESS,
                                         i_tid,
                                         A_current_sec_level,
                                         attr_val_1)) )
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      } /* end of auto-section */

    /* Get process's mac_curr_categories */
    i_tid.process = pid;
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_mac_curr_categories,
                       &attr_val_1,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* read-up is no problem, but otherwise we can try auto-adjust */
    if (!( (attr_val_1.mac_categories & target_categories)
           == target_categories))
      {
        /* no read-up: Can we adjust mac_curr_categories? */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_auto,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* no -> not granted */
        if (!attr_val_2.mac_auto)
          return(NOT_GRANTED);
      
        /* Get maximum categories for adjusting */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_categories,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* our target is too high up -> not granted */
        if (!( (attr_val_2.mac_categories & target_categories)
               == target_categories))
          return(NOT_GRANTED);

        /* how about our upper boundary by writes / *-property? */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_min_write_categories,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* our target is too high up -> not granted */
        if (!( (attr_val_2.mac_categories & target_categories)
               == target_categories))
          return(NOT_GRANTED);

        /* at last adjust mac_curr_categories, if set_level is on */
        attr_val_1.mac_categories |= target_categories;
        if (set_level && (rsbac_set_attr(T_PROCESS,
                                         i_tid,
                                         A_mac_curr_categories,
                                         attr_val_1)) )
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      } /* end of auto-section */

    /* now we are in grant area -> adjust max_read_open, if set_level is on... */
    if (set_level)
      {
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_open,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* ...and it is necessary */
        if (attr_val_2.max_read_open < target_sec_level)
          {
            attr_val_2.max_read_open = target_sec_level;
            if (rsbac_set_attr(T_PROCESS,
                               i_tid,
                               A_max_read_open,
                               attr_val_2))
              { /* failed! */
                printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
                return(NOT_GRANTED);
              }
          }
        /* also adjust max_read_categories */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_categories,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* ...and it is necessary */
        if (!( (attr_val_2.mac_categories & target_categories)
               == target_categories))
          {
            attr_val_2.mac_categories |= target_categories;
            if (rsbac_set_attr(T_PROCESS,
                               i_tid,
                               A_max_read_categories,
                               attr_val_2))
              { /* failed! */
                printk(KERN_WARNING "auto_write(): rsbac_set_attr() returned error!\n");
                return(NOT_GRANTED);
              }
          }
      }
    /* ready and go */
    return(GRANTED);
  };


/* auto-read-write() */
/* combines auto-read and auto-write */

static enum rsbac_adf_req_ret_t
     auto_read_write (     rsbac_pid_t             pid,
                           rsbac_security_level_t  target_sec_level,
                           rsbac_mac_category_vector_t target_categories,
                           boolean                 set_level)
  {
    union rsbac_target_id_t       i_tid;
    union rsbac_attribute_value_t attr_val_1;
    union rsbac_attribute_value_t attr_val_2;
    union rsbac_attribute_value_t attr_val_3;
    union rsbac_attribute_value_t attr_val_4;
    union rsbac_attribute_value_t attr_val_5;

    /* Access to security_level SL_rsbac_internal is never granted. */
    if (target_sec_level == SL_rsbac_internal)
      return(NOT_GRANTED);

    /* is our process trusted? If yes -> no write check -> perform auto-read! */
    i_tid.process = pid;
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_mac_trusted,
                       &attr_val_2,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* if trusted -> no write-check -> auto-read */
    if (attr_val_2.mac_trusted)
      return(auto_read(pid, target_sec_level, target_categories, set_level));

    /* get current_sec_level */
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_current_sec_level,
                       &attr_val_1,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* if it equals our target_level, prepare adjusting of boundaries */
    if (attr_val_1.current_sec_level == target_sec_level)
      {
        /* Get max. security_level of earlier reads */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_open,
                           &attr_val_1,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* Get min. security_level of earlier writes */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_min_write_open,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    else
      {
        /* if not, try to adjust current_sec_level */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_auto,
                           &attr_val_1,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* not allowed -> do not grant */
        if (!attr_val_1.mac_auto)
          return(NOT_GRANTED);
      
        /* Get maximum sec_level for adjusting */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_security_level,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is too high up -> not granted */
        if (target_sec_level > attr_val_2.security_level)
          return(NOT_GRANTED);

        /* Get max. security_level of earlier reads */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_open,
                           &attr_val_1,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is below that, *-property is violated -> do not grant */
        if (target_sec_level < attr_val_1.max_read_open)
          return(NOT_GRANTED);

        /* Get min. security_level of earlier writes */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_min_write_open,
                           &attr_val_2,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is above that, *-property is violated -> do not grant */
        if (target_sec_level > attr_val_2.min_write_open)
          return(NOT_GRANTED);

        /* at last, adjust current_sec_level, if set_level is TRUE */
        attr_val_3.current_sec_level = target_sec_level;
        if (set_level && (rsbac_set_attr(T_PROCESS,
                                         i_tid,
                                         A_current_sec_level,
                                         attr_val_3)) )
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      } /* end of sec_level auto-section */

    /* get mac_curr_categories */
    if (rsbac_get_attr(T_PROCESS,
                       i_tid,
                       A_mac_curr_categories,
                       &attr_val_3,
                       FALSE))
      { /* failed! */
        printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
        return(NOT_GRANTED);
      }
    /* if it equals our target_categories, prepare adjusting of boundaries */
    if (attr_val_1.mac_categories == target_categories)
      {
        /* Get max_read_categories of earlier reads */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_categories,
                           &attr_val_3,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* Get min_write_categories of earlier writes */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_min_write_categories,
                           &attr_val_4,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    else
      {
        /* if not, try to adjust current_sec_level */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_auto,
                           &attr_val_3,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* not allowed -> do not grant */
        if (!attr_val_3.mac_auto)
          return(NOT_GRANTED);
      
        /* Get mac_categories for adjusting */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_mac_categories,
                           &attr_val_4,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is too high up -> not granted */
        if (!( (attr_val_4.mac_categories & target_categories)
               == target_categories))
          return(NOT_GRANTED);

        /* Get max. categories of earlier reads */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_max_read_categories,
                           &attr_val_3,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is below that, *-property is violated -> do not grant */
        if (!( (attr_val_3.mac_categories & target_categories)
               == attr_val_3.mac_categories))
          return(NOT_GRANTED);

        /* Get min. write categories of earlier writes */
        if (rsbac_get_attr(T_PROCESS,
                           i_tid,
                           A_min_write_categories,
                           &attr_val_4,
                           FALSE))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_get_attr() returned error!\n");
            return(NOT_GRANTED);
          }
        /* if our target is above that, *-property is violated -> do not grant */
        if (!( (attr_val_3.mac_categories & target_categories)
               == target_categories))
          return(NOT_GRANTED);

        /* at last, adjust current_sec_level, if set_level is TRUE */
        attr_val_5.mac_categories = target_categories;
        if (set_level && (rsbac_set_attr(T_PROCESS,
                                         i_tid,
                                         A_mac_curr_categories,
                                         attr_val_5)) )
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      } /* end of categories auto-section */


    /* We now enter grant area - only boundaries are still to be adjusted */
    /* adjust max_read_open, if necessary and set_level is TRUE */
    if (set_level && (attr_val_1.max_read_open < target_sec_level) )
      {
        attr_val_1.max_read_open = target_sec_level;
        if (rsbac_set_attr(T_PROCESS,
                           i_tid,
                           A_max_read_open,
                           attr_val_1))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    /* adjust min_write_open, if necessary and set_level is TRUE */
    if (set_level && (attr_val_2.min_write_open > target_sec_level))
      {
        attr_val_2.min_write_open = target_sec_level;
        if (rsbac_set_attr(T_PROCESS,
                           i_tid,
                           A_min_write_open,
                           attr_val_2))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    /* adjust max_read_categories, if necessary and set_level is TRUE */
    if (   set_level
        && !( (attr_val_3.mac_categories & target_categories)
              == target_categories)
       )
      {
        attr_val_3.mac_categories |= target_categories;
        if (rsbac_set_attr(T_PROCESS,
                           i_tid,
                           A_max_read_categories,
                           attr_val_3))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
    /* adjust min_write_categories, if necessary and set_level is TRUE */
    if (   set_level
        && !( (attr_val_4.mac_categories & target_categories)
              == attr_val_4.mac_categories)
       )
      {
        attr_val_4.mac_categories &= target_categories;
        if (rsbac_set_attr(T_PROCESS,
                           i_tid,
                           A_min_write_categories,
                           attr_val_4))
          { /* failed! */
            printk(KERN_WARNING "auto_read_write(): rsbac_set_attr() returned error!\n");
            return(NOT_GRANTED);
          }
      }
      
    /* ready and go */
    return(GRANTED);
  };

/************************************************* */
/*          Externally visible functions           */
/************************************************* */

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;
/*    enum  rsbac_target_t          i_target;
*/
    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;
    int err=0;
    boolean inherit;

    switch (request)
      {
        case R_ADD_TO_KERNEL:
            switch(target)
              {
                case T_FILE:
                case T_NONE:
                  /* test owner's system_role */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* only administrators are allowed to do this */
                  if (i_attr_val1.system_role != SR_administrator)
                    return(NOT_GRANTED);
                  /* That's it, if there's no target */
                  if (target == T_NONE)
                    return(GRANTED);

                  /* test read access to module file: get its sec_level and categories */
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read without setting attributes */
                  return(auto_read(caller_pid,
                                   i_attr_val1.security_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_ALTER:
            /* only for IPC */
            if (target == T_IPC)
              {
                  /* test write access to ipc: get its sec_level */
                  if (rsbac_get_attr(T_IPC,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_IPC,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                   i_attr_val1.security_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));
              }
            else
            /* all other targets are unknown */
              return (DO_NOT_CARE);
            break;

        case R_APPEND_OPEN:
            switch(target)
              {
                case T_FILE:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                case T_DEV:
                  /* Only check for devices with mac_check set */
                  if (rsbac_get_attr(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(DO_NOT_CARE);
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_CHANGE_GROUP:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  
                /* 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:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                  
                /*  processes may only be given to dominated user, */
                /*  if Role Protection is on, not between administrator */
                /*  and security officer. */
                case T_PROCESS:
                  /* For target process there MUST be a new owner specified */
                  if (attr != A_owner)
                    return(UNDEFINED);
		  /* Allow change owner for trusted processes*/
		  /* trusted process? */
                   i_tid.process = caller_pid;
                   if (rsbac_get_attr(T_PROCESS,
                                      i_tid,
                                      A_mac_trusted,
                                      &i_attr_val1,
                                      FALSE))
                    { /* failed! */
                      printk(KERN_WARNING "adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (i_attr_val1.mac_trusted)
                                  return(GRANTED);
    
                  /* Get security level for old and new owner */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  i_tid.user = attr_val.owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_security_level,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* if old user does not dominate new user -> do not grant */
                  if (i_attr_val1.security_level < i_attr_val2.security_level)
                    return(NOT_GRANTED);
                  /* else: go on (test roles only, if role protection) */

                  #ifdef CONFIG_RSBAC_MAC_ROLE_PROT
                  /* Administrator or secoff? */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* if general user, then grant */
                  if (i_attr_val1.system_role == SR_user)
                    return(GRANTED);
                  /* get target user's role */
                  i_tid.user = attr_val.owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* target is no general user and has different role -> deny */
                  if (   (i_attr_val2.system_role != SR_user)
                      && (i_attr_val1.system_role != i_attr_val2.system_role)
                     )
                    return(NOT_GRANTED);
                  #endif

                  return(GRANTED);

                /* Change-user without target is only for DAC -> who cares? */
                case T_NONE:
                  return(DO_NOT_CARE);
                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }

        case R_CHDIR:
        case R_READ:
        case R_SEARCH:
            switch(target)
              {
                case T_DIR:
                  /* test read access to dir: get its sec_level */
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read without setting attributes */
                  return(auto_read(caller_pid,
                                   i_attr_val1.security_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_CLONE:
            if (target == T_PROCESS)
              return(GRANTED);
            else
              return(DO_NOT_CARE);

        case R_CREATE:
            switch(target)
              {
                /* Creating dir or (pseudo) file IN target dir! */
                case T_DIR: 
                  /* Mode of created item is ignored! */
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
#ifdef CONFIG_RSBAC_MAC_LIGHT
                  return GRANTED;
#else		  
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
#endif
                  break;
                  
                /* IPC is always granted */
                case T_IPC:
                  return(GRANTED);
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_DELETE:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_EXECUTE:
            switch(target)
              {
                case T_FILE:
                  /* test read access to file: get its sec_level */
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read without setting attributes */
                  return(auto_read(caller_pid,
                                   i_attr_val1.security_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));

                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }

        case R_GET_PERMISSIONS_DATA:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                case T_IPC:
                case T_SCD:
                  return(DO_NOT_CARE);
                default:
                  return(DO_NOT_CARE);
               };

        case R_GET_STATUS_DATA:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                case T_IPC:
                  return(DO_NOT_CARE);
                case T_SCD:
                  /* target rsbaclog? only for secoff */
                  if (tid.scd != ST_rsbaclog)
                    return(GRANTED);
                  /* Secoff? */
                  i_tid.user = owner;
                  if ((err=rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE)))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error %i!\n",err);
                      return(NOT_GRANTED);
                    }
                  /* grant only for secoff */
                  if (i_attr_val1.system_role == SR_security_officer)
                    return(GRANTED);
                  else
                    return(NOT_GRANTED);
                default:
                  return(DO_NOT_CARE);
               };

        case R_LINK_HARD:
        case R_TRUNCATE:
            switch(target)
              {
                case T_FILE:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_MODIFY_ACCESS_DATA:
        case R_RENAME:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                /* 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_security_level:
                  if (attr_val.security_level == SL_rsbac_internal)
                    return(NOT_GRANTED);
                  /* fall through */
                case A_mac_categories:
                case A_pseudo:
                case A_system_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_auto:
                case A_mac_trusted:
                case A_mac_trusted_for_user:
                case A_mac_check:
                case A_log_array_low:
                case A_log_array_high:
                case A_log_program_based:
                case A_log_user_based:
                #ifdef CONFIG_RSBAC_MAC_AUTH_PROT
                case A_auth_may_setuid:
                case A_auth_may_set_cap:
                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(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): 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_PERMISSIONS_DATA:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    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(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): 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);
                  /* 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);
                  
                /* 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)
                    return(GRANTED);
                  /* Get role */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* if rsbaclog: grant only for secoff */
                  if(tid.scd == ST_rsbaclog)
                    {
                      if (i_attr_val1.system_role == SR_security_officer)
                        return(GRANTED);
                      else
                        return(NOT_GRANTED);
                    }
                  /* if administrator or (rsbaclog and secoff), then grant */
                  if (i_attr_val1.system_role == SR_administrator)
                    return(GRANTED);
                  else
                    return(NOT_GRANTED);
                  
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_MOUNT:
            switch(target)
              {
                case T_DIR:
                case T_DEV:
                  /* test owner's system_role: Administrator? */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
#ifndef CONFIG_RSBAC_MAC_LIGHT
                  if (i_attr_val1.system_role != SR_administrator)
                    return(NOT_GRANTED);
#endif
                  /* test read-write access to mount dir / dev: */
                  /* get its sec_level */
                  if(target == T_DIR)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* 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,
                                     i_attr_val1.security_level,
                                     i_attr_val2.mac_categories,
                                     FALSE));
                  else
                    return(auto_read_write(caller_pid,
                                           i_attr_val1.security_level,
                                           i_attr_val2.mac_categories,
                                           FALSE));

                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

/*      case R_READ: see R_CHDIR */

        case R_READ_ATTRIBUTE:
            switch(attr)
              {
                case A_owner:
                case A_security_level:
		case A_mac_categories:
                case A_pseudo:
                case A_system_role:
                case A_current_sec_level:
                case A_min_write_open:
                case A_max_read_open:
                case A_mac_auto:
                case A_mac_trusted:
                case A_mac_trusted_for_user:
                case A_mac_check:
                case A_log_array_low:
                case A_log_array_high:
                case A_log_program_based:
                case A_log_user_based:
                #ifdef CONFIG_RSBAC_MAC_AUTH_PROT
                case A_auth_may_setuid:
                case A_auth_may_set_cap:
                #endif
                  /* Security Officer? */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): 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_READ_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                case T_IPC:
                  /* test read access to target: get its sec_level */
                  if(target != T_IPC)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read without setting attributes */
                  return(auto_read(caller_pid,
                                   i_attr_val1.security_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));
                  break;
                case T_DEV:
                  /* Only check for devices with mac_check set */
                  if (rsbac_get_attr(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(DO_NOT_CARE);
                  /* test read access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read without setting attributes */
                  return(auto_read(caller_pid,
                                   i_attr_val1.security_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_READ_WRITE_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_IPC:
                  /* test read-write access to target: get its sec_level */
                  if(target == T_FILE)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read-write without setting attributes */
                  return(auto_read_write(caller_pid,
                                         i_attr_val1.security_level,
                                         i_attr_val2.mac_categories,
                                         FALSE));

                case T_DEV:
                  /* Only check for devices with mac_check set */
                  if (rsbac_get_attr(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(DO_NOT_CARE);
                  /* test read-write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read-write without setting attributes */
                  return(auto_read_write(caller_pid,
                                         i_attr_val1.security_level,
                                         i_attr_val2.mac_categories,
                                         FALSE));

                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_REMOVE_FROM_KERNEL:
        case R_SHUTDOWN:
            switch(target)
              {
                case T_NONE:
                  /* test owner's system_role */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (i_attr_val1.system_role == SR_administrator)
                    return(GRANTED);
                  else
                    return(NOT_GRANTED);

                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

/*      case R_RENAME: see R_MODIFY_ACCESS_DATA */

/*      case R_SEARCH: see R_CHDIR */

        case R_SEND_SIGNAL:
            switch(target)
              {
                case T_PROCESS:
                  /* test write access to process: get its sec_level */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_current_sec_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_curr_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                   i_attr_val1.current_sec_level,
                                   i_attr_val2.mac_categories,
                                   FALSE));

                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }

/*      case R_SHUTDOWN: see R_REMOVE_FROM_KERNEL */

        case R_SWITCH_LOG:
            switch(target)
              {
                case T_NONE:
                  /* test owner's system_role */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): 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 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(UNDEFINED);
                  /* do not care for other modules */
                  if(   (attr_val.switch_target != MAC)
                     #ifdef CONFIG_RSBAC_MAC_AUTH_PROT
                     && (attr_val.switch_target != AUTH)
                     #endif
                    )
                    return(DO_NOT_CARE);
                  /* test owner's system_role */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): 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 unknown */
                default: return(DO_NOT_CARE);
              }

        /* notify only, handled by adf-dispatcher */
        case R_TERMINATE:
            if (target == T_PROCESS)
              return(DO_NOT_CARE);
            else
              return(DO_NOT_CARE);

        case R_TRACE:
            switch(target)
              {
                case T_PROCESS:
                  /* test read-write access to process: get its sec_level */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_current_sec_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_curr_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read-write without setting attributes */
                  return(auto_read_write(caller_pid,
                                         i_attr_val1.current_sec_level,
                                         i_attr_val2.mac_categories,
                                         FALSE));

                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }

/*      case R_TRUNCATE: see R_LINK_HARD */

        case R_UMOUNT:
            switch(target)
              {
                case T_DIR:
                case T_DEV:
                case T_NONE:
                  /* test owner's system_role */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
#ifdef CONFIG_RSBAC_MAC_LIGHT
                  return(GRANTED);
#else
                  if (i_attr_val1.system_role == SR_administrator)
                    return(GRANTED);
                  else
                    return(NOT_GRANTED);
#endif
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        /* Moving to other dir only */
        case R_WRITE:
            switch(target)
              {
                case T_DIR: 
                  /* Mode of created item is ignored! */
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_WRITE_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                case T_DEV:
                  /* Only check for devices with mac_check set */
                  if (rsbac_get_attr(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(DO_NOT_CARE);
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write without setting attributes */
                  return(auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    FALSE));
                  break;
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

/*********************/
        default: return DO_NOT_CARE;
      }

    return(result);
  }; /* end of rsbac_adf_request_mac() */


/*****************************************************************************/
/* 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_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;
    boolean inherit;

    switch (request)
      {
        case R_APPEND_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_IPC:
                  /* test write access to target: get its sec_level */
                  if(target == T_FILE)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write with setting attributes */
                  result = auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    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(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(0);
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write with setting attributes */
                  result = auto_write(caller_pid,
                                    i_attr_val1.security_level,
                                    i_attr_val2.mac_categories,
                                    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(T_USER,
                                     i_tid,
                                     A_security_level,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_mac_categories,
                                     &i_attr_val3,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      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(T_PROCESS,
                                     tid,
                                     A_security_level,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  if (rsbac_set_attr(T_PROCESS,
                                     tid,
                                     A_mac_categories,
                                     i_attr_val3))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* OK, we are ready */
                  return(0);
                    
                /* We do not care about those cases here */
                case T_FILE:
                case T_DIR:
                case T_IPC:
                case T_NONE:
                  return(0);
                /* all other cases are unknown */
                default:
                  return(0);
              }

        case R_CHDIR:
            switch(target)
              {
                case T_DIR:
                  return(0);
                default:
                  return(0);
               };

        case R_CLONE:
            if (target == T_PROCESS)
              {
                  /* Get owner from first process (provided on call) */
                  i_attr_val1.owner = owner;
                  /* Get owner-sec-level from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_security_level,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get current-sec-level from first process... */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_current_sec_level,
                                     &i_attr_val3,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get min_write_open from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_min_write_open,
                                     &i_attr_val4,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get max_read_open from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_max_read_open,
                                     &i_attr_val5,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get mac_auto from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_auto,
                                     &i_attr_val6,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get mac_trusted from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_trusted,
                                     &i_attr_val7,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }

#ifdef CONFIG_RSBAC_USE_RSBAC_OWNER
                  /* Set owner for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_owner,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
#endif
                  /* Set owner_sec_level for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_security_level,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set current_sec_level for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_current_sec_level,
                                     i_attr_val3))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set min_write_open for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_min_write_open,
                                     i_attr_val4))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set max_read_open for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_max_read_open,
                                     i_attr_val5))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set mac_auto for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_mac_auto,
                                     i_attr_val6))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set mac_trusted for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_mac_trusted,
                                     i_attr_val7))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }

                  /* Get mac_categories from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get mac_curr_categories from first process... */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_curr_categories,
                                     &i_attr_val3,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get min_write_categories from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_min_write_categories,
                                     &i_attr_val4,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Get max_read_categories from first process */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_max_read_categories,
                                     &i_attr_val5,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Set mac_categories for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_mac_categories,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set mac_curr_categories for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_mac_curr_categories,
                                     i_attr_val3))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set min_write_categories for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_min_write_categories,
                                     i_attr_val4))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Set max_read_categories for new process */
                  if (rsbac_set_attr(T_PROCESS,
                                     new_tid,
                                     A_max_read_categories,
                                     i_attr_val5))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() 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! */
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-write with setting attributes */
#ifndef CONFIG_RSBAC_MAC_LIGHT
                  result = auto_write(caller_pid,
                                      i_attr_val1.security_level,
                                      i_attr_val2.mac_categories,
                                      TRUE);
                  if ((result != GRANTED) && (result != DO_NOT_CARE))
                    return(-RSBAC_EDECISIONMISMATCH);
#endif
                  /*Setting attrubutes to new file*/
		  /*Get system_role info for inheritance*/
		  i_tid.user=owner;
                  if(rsbac_get_attr(T_USER,
                                    i_tid,
				    A_system_role,
				    &i_attr_val7,
				    FALSE))
		    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }	
                  /* Get current-sec-level from process... */
                  i_tid.process = caller_pid;
                  if (rsbac_get_attr(T_PROCESS,
                                     i_tid,
                 ((i_attr_val7.system_role==SR_administrator)?A_current_sec_level:A_security_level),				     
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Set security-level for new item */
                  if (rsbac_set_attr(new_target,
                                     new_tid,
                                     A_security_level,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Get mac_curr_categories from process... */
                  if (rsbac_get_attr(T_PROCESS,
                                     i_tid,
                 ((i_attr_val7.system_role==SR_administrator)?A_mac_curr_categories:A_mac_categories),				    				     
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Set curr_categories for new item */
                  if (rsbac_set_attr(new_target,
                                     new_tid,
                                     A_mac_categories,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  return(0);
                  break;

                case T_IPC: 
                  i_tid.process = caller_pid;
                  /* Get current-sec-level from process... */
                  if (rsbac_get_attr(T_PROCESS,
                                     i_tid,
                                     A_current_sec_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Set security-level for this ipc item */
                  if (rsbac_set_attr(T_IPC,
                                     tid,
                                     A_security_level,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Get mac_curr_categories from process... */
                  if (rsbac_get_attr(T_PROCESS,
                                     i_tid,
                                     A_mac_curr_categories,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* Set curr_categories for new item */
                  if (rsbac_set_attr(T_IPC,
                                     tid,
                                     A_mac_categories,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  return(0);
                  break;
                  
                /* 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_IPC:
                  /* test write access to target: get its sec_level */
                  if(target != T_IPC)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-write with setting attributes */
                  result = auto_write(caller_pid,
                                      i_attr_val1.security_level,
                                      i_attr_val2.mac_categories,
                                      TRUE);
                  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:
                  /* test read access to file: get its sec_level */
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  /* and perform auto-read with setting attributes */
                  result = auto_read(caller_pid,
                                     i_attr_val1.security_level,
                                     i_attr_val2.mac_categories,
                                     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 */

                  /* First, set current_sec_level to program file's seclevel */
                  i_tid.process = caller_pid;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_current_sec_level,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* Next, set mac_curr_categories to program file's mac_categories */
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_mac_curr_categories,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* set mac_auto */
                  i_attr_val2.mac_auto = TRUE;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_mac_auto,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* reset sec_level boundaries */
                  i_attr_val2.min_write_open = SL_max;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_min_write_open,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  i_attr_val2.max_read_open = SL_unclassified;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_max_read_open,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* reset category boundaries */
                  i_attr_val2.mac_categories = RSBAC_MAC_MAX_CAT_VECTOR;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_min_write_categories,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  i_attr_val2.mac_categories = RSBAC_MAC_MIN_CAT_VECTOR;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_max_read_categories,
                                     i_attr_val2))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  /* set mac_trusted: get mac_trusted_for_user from FILE aci */
                  if (rsbac_get_attr(T_FILE,
                                     tid,
                                     A_mac_trusted_for_user,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(   i_attr_val1.mac_trusted_for_user == RSBAC_ALL_USERS
                     || i_attr_val1.mac_trusted_for_user == owner)
                      i_attr_val1.mac_trusted = TRUE;
                    else
                      i_attr_val1.mac_trusted = FALSE;
                  if (rsbac_set_attr(T_PROCESS,
                                     i_tid,
                                     A_mac_trusted,
                                     i_attr_val1))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_set_attr() returned error!\n");
                      return(-RSBAC_EWRITEFAILED);
                    }
                  return(0);

                /* all other cases are unknown */
                default:
                  return(0);
              }

        case R_MOUNT:
            switch(target)
              {
                case T_DIR:
                case T_DEV:
                  /* test owner's system_role: Administrator? */
                  i_tid.user = owner;
                  if (rsbac_get_attr(T_USER,
                                     i_tid,
                                     A_system_role,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (i_attr_val1.system_role != SR_administrator)
                    return(-RSBAC_EDECISIONMISMATCH);

                  /* test read-write access to mount dir/dev: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* 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,
                                       i_attr_val1.security_level,
                                       i_attr_val2.mac_categories,
                                       TRUE);
                  else
                    result = auto_read_write(caller_pid,
                                             i_attr_val1.security_level,
                                             i_attr_val2.mac_categories,
                                             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:
        case R_SEARCH:
            switch(target)
              {
                case T_DIR:
                  /* test read access to dir: get its sec_level */
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(T_DIR,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-read with setting attributes */
                  result = auto_read(caller_pid,
                                     i_attr_val1.security_level,
                                     i_attr_val2.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_READ_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                case T_IPC:
                  /* test read access to target: get its sec_level */
                  if(target != T_IPC)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-read with setting attributes */
                  result = auto_read(caller_pid,
                                     i_attr_val1.security_level,
                                     i_attr_val2.mac_categories,
                                     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(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(0);
                  /* test read access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-read with setting attributes */
                  result = auto_read(caller_pid,
                                     i_attr_val1.security_level,
                                     i_attr_val2.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_READ_WRITE_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_IPC:
                  /* test read-write access to target: get its sec_level */
                  if(target != T_IPC)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-read-write without setting attributes */
                  result = auto_read_write(caller_pid,
                                           i_attr_val1.security_level,
                                           i_attr_val2.mac_categories,
                                           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(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(0);
                  /* test read-write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-read-write with setting of attributes */
                  result = auto_read_write(caller_pid,
                                           i_attr_val1.security_level,
                                           i_attr_val2.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_SEARCH: see R_READ */

        case R_TRACE:
            switch(target)
              {
                case T_PROCESS:
                  /* test read-write access to process: get its sec_level */
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_current_sec_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(T_PROCESS,
                                     tid,
                                     A_mac_curr_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-read-write with setting attributes */
                  result = auto_read_write(caller_pid,
                                           i_attr_val1.current_sec_level,
                                           i_attr_val2.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_WRITE_OPEN:
            switch(target)
              {
                case T_FILE:
                case T_IPC:
                  /* test read-write access to target: get its sec_level */
                  if(target != T_IPC)
                    inherit = TRUE;
                  else
                    inherit = FALSE;
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     inherit))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     TRUE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-write with setting attributes */
                  result = auto_write(caller_pid,
                                      i_attr_val1.security_level,
                                      i_attr_val2.mac_categories,
                                      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(T_DEV,
                                     tid,
                                     A_mac_check,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING "rsbac_adf_request_mac(): rsbac_get_attr() returned error!\n");
                      return(NOT_GRANTED);
                    }
                  if(!i_attr_val1.mac_check)
                    return(0);
                  /* test write access to target: get its sec_level */
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_security_level,
                                     &i_attr_val1,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  if (rsbac_get_attr(target,
                                     tid,
                                     A_mac_categories,
                                     &i_attr_val2,
                                     FALSE))
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_set_attr_mac(): rsbac_get_attr() returned error!\n");
                      return(-RSBAC_EREADFAILED);
                    }
                  /* and perform auto-write with setting attributes */
                  result = auto_write(caller_pid,
                                      i_attr_val1.security_level,
                                      i_attr_val2.mac_categories,
                                      TRUE);
                  if ((result != GRANTED) && (result != DO_NOT_CARE))
                    return(-RSBAC_EDECISIONMISMATCH);
                  return(0);
                /* all other cases are unknown */
                default:
                  return(0);
              }


/*********************/
        default: return(0);
      }

    return(0);
  }; /* end of rsbac_adf_set_attr_mac() */

/* end of rsbac/adf/mac/main.c */
