/**************************************************** */
/* Rule Set Based Access Control                      */
/* Implementation of the Access Control Decision      */
/* Facility (ADF) - Authorization module              */
/* File: rsbac/adf/jail/main.c                        */
/*                                                    */
/* Author and (c) 1999-2002: Amon Ott <ao@rsbac.org>  */
/*                                                    */
/* Last modified: 21/Nov/2002                         */
/**************************************************** */

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

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

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

static rsbac_jail_id_t
  jail_get_id(enum  rsbac_target_t target,
              union rsbac_target_id_t tid)
  {
    int                           err;
    union rsbac_attribute_value_t i_attr_val1;

    if ((err=rsbac_get_attr(JAIL,
                            target,
                            tid,
                            A_jail_id,
                            &i_attr_val1,
                            TRUE)))
      {
        printk(KERN_WARNING "jail_get_id(): rsbac_get_attr() returned error %i!\n",err);
        return 0;
      }
    else
      return i_attr_val1.jail_id;
  }

static rsbac_jail_id_t
  jail_get_id_process(rsbac_pid_t pid)
  {
    int                           err;
    union rsbac_target_id_t      i_tid;
    union rsbac_attribute_value_t i_attr_val1;

    i_tid.process = pid;
    if ((err=rsbac_get_attr(JAIL,
                            T_PROCESS,
                            i_tid,
                            A_jail_id,
                            &i_attr_val1,
                            TRUE)))
      {
        printk(KERN_WARNING "jail_get_id_process(): rsbac_get_attr() returned error %i!\n",err);
        return 0;
      }
    else
      return i_attr_val1.jail_id;
  }

#if defined(CONFIG_RSBAC_NET_OBJ)
static rsbac_jail_ip_t
  jail_get_ip_process(rsbac_pid_t pid)
  {
    int                           err;
    union rsbac_target_id_t      i_tid;
    union rsbac_attribute_value_t i_attr_val1;

    i_tid.process = pid;
    if ((err=rsbac_get_attr(JAIL,
                            T_PROCESS,
                            i_tid,
                            A_jail_ip,
                            &i_attr_val1,
                            TRUE)))
      {
        printk(KERN_WARNING "jail_get_id_process(): rsbac_get_attr() returned error %i!\n",err);
        return 0;
      }
    else
      return i_attr_val1.jail_ip;
  }
#endif

static rsbac_jail_flags_t
  jail_get_flags_process(rsbac_pid_t pid)
  {
    int                           err;
    union rsbac_target_id_t      i_tid;
    union rsbac_attribute_value_t i_attr_val1;

    i_tid.process = pid;
    if ((err=rsbac_get_attr(JAIL,
                            T_PROCESS,
                            i_tid,
                            A_jail_flags,
                            &i_attr_val1,
                            TRUE)))
      {
        printk(KERN_WARNING "jail_get_flags_process(): rsbac_get_attr() returned error %i!\n",err);
        return 0;
      }
    else
      return i_attr_val1.jail_flags;
  }

static enum rsbac_adf_req_ret_t
  jail_check_sysrole(rsbac_uid_t owner, enum rsbac_system_role_t role)
  {
    union rsbac_target_id_t i_tid;
    union rsbac_attribute_value_t i_attr_val1;

    i_tid.user = owner;
    if (rsbac_get_attr(JAIL,
                       T_USER,
                       i_tid,
                       A_jail_role,
                       &i_attr_val1,
                       TRUE))
      {
        printk(KERN_WARNING
               "jail_check_sysrole(): rsbac_get_attr() returned error!\n");
               return(NOT_GRANTED);
      }
    /* if correct role, then grant */
    if (i_attr_val1.system_role == role)
      return(GRANTED);
    else
      return(NOT_GRANTED);
  }

#if defined(CONFIG_RSBAC_NET_OBJ)
enum rsbac_adf_req_ret_t
  jail_check_ip(rsbac_pid_t pid, union rsbac_target_id_t tid)
  {
    rsbac_jail_ip_t               jail_ip;
    rsbac_jail_flags_t            jail_flags;

    if(!tid.netobj.sock_p)
      {
        printk(KERN_WARNING
               "jail_check_ip(): NULL sock_p!\n");
        return NOT_GRANTED;
      }
    switch(tid.netobj.sock_p->ops->family)
      {
        case AF_UNIX:
          return(GRANTED);

        case AF_INET:
          switch(tid.netobj.sock_p->type)
            {
              case SOCK_STREAM:
              case SOCK_DGRAM:
              case SOCK_RDM:
                jail_ip = jail_get_ip_process(pid);
                if(jail_ip == INADDR_ANY)
                  return GRANTED;
                jail_flags = jail_get_flags_process(pid);
                if(tid.netobj.local_addr)
                  {
                    struct sockaddr_in * addr = tid.netobj.local_addr;

                    if(   (jail_ip == addr->sin_addr.s_addr)
                       || (   (jail_flags & JAIL_allow_inet_localhost)
                           && (addr->sin_addr.s_addr == RSBAC_JAIL_LOCALHOST)
                          )
#if defined(CONFIG_RSBAC_JAIL_NET_ADJUST)
                       || (   (jail_flags & JAIL_auto_adjust_inet_any)
                           && (addr->sin_addr.s_addr == INADDR_ANY)
                          )
#endif
                      )
                      return GRANTED;
                    else
                      {
#ifdef CONFIG_RSBAC_DEBUG
                        if(rsbac_debug_adf_jail)
                          {
                            printk(KERN_DEBUG
                                   "jail_check_ip(): local_addr does not match jail_ip -> NOT_GRANTED!\n");
                          }
#endif
                        return NOT_GRANTED;
                      }
                  }
                else
                if(   (tid.netobj.remote_addr)
                   && (jail_flags & JAIL_allow_inet_localhost)
                   && ( ((struct sockaddr_in *) tid.netobj.remote_addr)->sin_addr.s_addr
                        == RSBAC_JAIL_LOCALHOST)
                  )
                   return GRANTED;
                else
                  {
                    if(   (   (jail_ip == tid.netobj.sock_p->sk->rcv_saddr)
                           && (jail_ip == tid.netobj.sock_p->sk->saddr)
                          )
                       || (   (jail_flags & JAIL_allow_inet_localhost)
                           && (   (tid.netobj.sock_p->sk->saddr == RSBAC_JAIL_LOCALHOST)
                               || (tid.netobj.sock_p->sk->daddr == RSBAC_JAIL_LOCALHOST)
                              )
                          )
#if defined(CONFIG_RSBAC_JAIL_NET_ADJUST)
                       || (   (jail_flags & JAIL_auto_adjust_inet_any)
                           && (tid.netobj.sock_p->sk->rcv_saddr == INADDR_ANY)
                           && (tid.netobj.sock_p->sk->saddr == INADDR_ANY)
                          )
#endif
                      )
                      return GRANTED;
                    else
                      {
#ifdef CONFIG_RSBAC_DEBUG
                        if(rsbac_debug_adf_jail)
                          {
                            printk(KERN_DEBUG
                                   "jail_check_ip(): sk->rcv_saddr or sk->saddr does not match jail_ip -> NOT_GRANTED!\n");
                          }
#endif
                        return NOT_GRANTED;
                      }
                  }

              case SOCK_RAW:
                if(jail_get_flags_process(pid) & JAIL_allow_inet_raw)
                  return(GRANTED);
                else
                  {
#ifdef CONFIG_RSBAC_DEBUG
                    if(rsbac_debug_adf_jail)
                      {
                        printk(KERN_DEBUG
                               "jail_check_ip(): network type is raw  and allow_inet_raw is not set  -> NOT_GRANTED!\n");
                      }
#endif
                    return(NOT_GRANTED);
                  }

              default:
#ifdef CONFIG_RSBAC_DEBUG
                if(rsbac_debug_adf_jail)
                  {
                    printk(KERN_DEBUG
                           "jail_check_ip(): network type not STREAM, DGRAM, RDM or RAW -> NOT_GRANTED!\n");
                  }
#endif
                return(NOT_GRANTED);
            }

        default:
          if(jail_get_flags_process(pid) & JAIL_allow_all_net_family)
            return(GRANTED);
          else
            {
#ifdef CONFIG_RSBAC_DEBUG
              if(rsbac_debug_adf_jail)
                {
                  printk(KERN_DEBUG
                         "jail_check_ip(): network family not UNIX or INET and allow_all_net_family not set -> NOT_GRANTED!\n");
                }
#endif
              return NOT_GRANTED;
            }
      }
  }
#endif /* defined(CONFIG_RSBAC_NET_OBJ) */

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

enum rsbac_adf_req_ret_t
   rsbac_adf_request_jail (enum  rsbac_adf_request_t     request,
                                rsbac_pid_t             caller_pid,
                          enum  rsbac_target_t          target,
                          union rsbac_target_id_t       tid,
                          enum  rsbac_attribute_t       attr,
                          union rsbac_attribute_value_t attr_val,
                                rsbac_uid_t             owner)
  {
    rsbac_jail_id_t    jail_id;
#ifdef CONFIG_RSBAC_NET_OBJ
    rsbac_jail_flags_t jail_flags;
#endif

    switch (request)
      {
        case R_ADD_TO_KERNEL:
        case R_REMOVE_FROM_KERNEL:
        case R_SHUTDOWN:
            switch(target)
              {
                case T_NONE:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  else
                    return GRANTED;

                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }
        case R_MOUNT:
        case R_UMOUNT:
            switch(target)
              {
                case T_FILE:
                case T_DIR:
                case T_DEV:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  else
                    return GRANTED;

                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }
        case R_CREATE:
            switch(target)
              {
                case T_DIR:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  /* no mknod for devices */
                  if(   (attr == A_create_data)
                     && (   S_ISCHR(attr_val.create_data.mode)
                         || S_ISBLK(attr_val.create_data.mode)
                        )
                    )
                    return NOT_GRANTED;
                  else
                    return GRANTED;

                case T_IPC:
                  return GRANTED;

#ifdef CONFIG_RSBAC_NET_OBJ
                case T_NETTEMP:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  else
                    return NOT_GRANTED;

                case T_NETOBJ:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  if(!tid.netobj.sock_p)
                    {
                      printk(KERN_WARNING
                             "rsbac_adf_request_jail(): NULL sock_p on CREATE!\n");
                      return NOT_GRANTED;
                    }
                  switch(tid.netobj.sock_p->ops->family)
                    {
                      case AF_UNIX:
                        return(GRANTED);

                      case AF_INET:
                        switch(tid.netobj.sock_p->type)
                          {
                            case SOCK_STREAM:
                            case SOCK_DGRAM:
                            case SOCK_RDM:
                              if(   tid.netobj.sock_p->sk
                                 && (tid.netobj.sock_p->sk->protocol == IPPROTO_RAW)
                                )
                                {
                                  jail_flags = jail_get_flags_process(caller_pid);
                                  if(jail_flags & JAIL_allow_inet_raw)
                                    return(GRANTED);
                                  else
                                    return NOT_GRANTED;
                                }
                              else
                                return GRANTED;

                            case SOCK_RAW:
                              jail_flags = jail_get_flags_process(caller_pid);
                              if(jail_flags & JAIL_allow_inet_raw)
                                return(GRANTED);
                              else
                                return NOT_GRANTED;

                            default:
                              return(NOT_GRANTED);
                          }

                      default:
                        jail_flags = jail_get_flags_process(caller_pid);
                        if(jail_flags & JAIL_allow_all_net_family)
                          return(GRANTED);
                        else
                          return(NOT_GRANTED);
                    }
#endif

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

        case R_DELETE:
            switch(target)
              {
                case T_IPC:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                     || (jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;

#ifdef CONFIG_RSBAC_NET_OBJ
                case T_NETTEMP:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  else
                    return NOT_GRANTED;
#endif
                /* all other cases are unknown */
                default: return(DO_NOT_CARE);
              }

        case R_MODIFY_ATTRIBUTE:
            switch(attr)
              {
                case A_system_role:
                case A_jail_role:
                case A_jail_id:
                case A_jail_ip:
                case A_jail_flags:
                /* All attributes (remove target!) */
                case A_none:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;

                  /* Security Officer? */
                  return jail_check_sysrole(owner, SR_security_officer);

                default:
                  return(DO_NOT_CARE);
              }

        case R_READ_ATTRIBUTE:
            switch(attr)
              {
                case A_system_role:
                case A_jail_role:
                case A_jail_id:
                case A_jail_ip:
                case A_jail_flags:
                /* All attributes (remove target!) */
                case A_none:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;

                  /* Security Officer? */
                  if(jail_check_sysrole(owner, SR_administrator) == NOT_GRANTED)
                    return jail_check_sysrole(owner, SR_security_officer);
                  else
                    return GRANTED;

                default:
                  return(DO_NOT_CARE);
              }

        case R_SEND_SIGNAL:
        case R_TRACE:
            if (target == T_PROCESS)
              {
                jail_id = jail_get_id_process(caller_pid);
                if(   !jail_id
                   || (jail_id == jail_get_id(target,tid))
                  )
                  return GRANTED;
                else
                  return NOT_GRANTED;
              }
            else
              return(DO_NOT_CARE);

        case R_MODIFY_PERMISSIONS_DATA:
            switch(target)
              {
                /* no setting of suid/sgid flags for jailed processes */
                case T_FILE:
                  if(   jail_get_id_process(caller_pid)
                     && (attr == A_mode)
                     && (attr_val.mode & (S_ISUID | S_ISGID))
                    )
                    return NOT_GRANTED;
                  else
                    return GRANTED;

                case T_IPC:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                     || (jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;

                case T_SCD:
#ifdef CONFIG_RSBAC_ALLOW_DAC_DISABLE
                /* switching Linux DAC */
                case T_NONE:
#endif
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  else
                    return GRANTED;

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

        case R_GET_STATUS_DATA:
            switch(target)
              {
                case T_PROCESS:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;

                case T_IPC:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                     || (jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;

                case T_SCD:
                  if(jail_get_id_process(caller_pid))
                    {
                      /* target rlimit? grant */
                      if (tid.scd == ST_rlimit)
                        return(GRANTED);
                      else
                        return NOT_GRANTED;
                    }
                  else
                    return GRANTED;

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

        case R_MODIFY_SYSTEM_DATA:
            switch(target)
              {
                case T_SCD:
                  if(jail_get_id_process(caller_pid))
                    {
                      /* target rlimit? grant, if allowed */
                      if (   (tid.scd == ST_rlimit)
                          && (jail_get_flags_process(caller_pid) & JAIL_allow_rlimit)
                         )
                        return(GRANTED);
                      else
                        return NOT_GRANTED;
                    }
                  else
                    return GRANTED;

#ifdef CONFIG_RSBAC_JAIL_NET_DEV_PROT
                case T_NETDEV:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  else
                    return GRANTED;
#endif

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

        case R_READ:
            switch(target)
              {
#ifdef CONFIG_RSBAC_RW
                case T_IPC:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                     || (jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;
#endif
#if defined(CONFIG_RSBAC_NET_OBJ)
                case T_NETTEMP:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  if(jail_check_sysrole(owner, SR_security_officer) == GRANTED)
                    return GRANTED;
                  return jail_check_sysrole(owner, SR_administrator);

                case T_NETOBJ:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  return(jail_check_ip(caller_pid, tid));
#endif

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

        case R_SWITCH_LOG:
            switch(target)
              {
                case T_NONE:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  /* test owner's fc_role */
                  return jail_check_sysrole(owner, SR_security_officer);

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

        case R_SWITCH_MODULE:
            switch(target)
              {
                case T_NONE:
                  /* we need the switch_target */
                  if(attr != A_switch_target)
                    return(UNDEFINED);
                  /* do not care for other modules */
                  if(   (attr_val.switch_target != JAIL)
                     #ifdef CONFIG_RSBAC_SOFTMODE
                     && (attr_val.switch_target != SOFTMODE)
                     #endif
                    )
                    return(DO_NOT_CARE);
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  /* test owner's fc_role */
                  return jail_check_sysrole(owner, SR_security_officer);

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

        case R_WRITE:
            switch(target)
              {
#ifdef CONFIG_RSBAC_RW
                case T_IPC:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                     || (jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;
#endif

#if defined(CONFIG_RSBAC_NET_OBJ)
                case T_NETTEMP:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  return jail_check_sysrole(owner, SR_security_officer);

                case T_NETOBJ:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  return(jail_check_ip(caller_pid, tid));
#endif

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

#ifdef CONFIG_RSBAC_NET
        case R_BIND:
            switch(target)
              {
#ifdef CONFIG_RSBAC_JAIL_NET_DEV_PROT
                case T_NETDEV:
                  if(jail_get_id_process(caller_pid))
                    return NOT_GRANTED;
                  else
                    return GRANTED;
#endif
#ifdef CONFIG_RSBAC_NET_OBJ
                case T_NETOBJ:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  return(jail_check_ip(caller_pid, tid));
#endif
                /* all other cases are unknown */
                default:
                  return(DO_NOT_CARE);
              }
#endif
#ifdef CONFIG_RSBAC_NET_OBJ
        case R_LISTEN:
        case R_ACCEPT:
        case R_CONNECT:
        case R_SEND:
        case R_RECEIVE:
            switch(target)
              {
                case T_NETOBJ:
                  if(!jail_get_id_process(caller_pid))
                    return GRANTED;
                  return(jail_check_ip(caller_pid, tid));

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

        default:
            /* only for IPC */
            switch(target)
              {
                case T_IPC:
                  jail_id = jail_get_id_process(caller_pid);
                  if(   !jail_id
                     || (jail_id == jail_get_id(target,tid))
                     || (jail_get_flags_process(caller_pid) & JAIL_allow_external_ipc)
                    )
                    return GRANTED;
                  else
                    return NOT_GRANTED;

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


/*****************************************************************************/
/* If the request returned granted and the operation is performed,           */
/* the following function can be called by the AEF to get all aci set        */
/* correctly. For write accesses that are performed fully within the kernel, */
/* this is usually not done to prevent extra calls, including R_CLOSE for    */
/* cleaning up.                                                              */
/* The second instance of target specification is the new target, if one has */
/* been created, otherwise its values are ignored.                           */
/* On success, 0 is returned, and an error from rsbac/error.h otherwise.     */

int  rsbac_adf_set_attr_jail(
                      enum  rsbac_adf_request_t     request,
                            rsbac_pid_t             caller_pid,
                      enum  rsbac_target_t          target,
                      union rsbac_target_id_t       tid,
                      enum  rsbac_target_t          new_target,
                      union rsbac_target_id_t       new_tid,
                      enum  rsbac_attribute_t       attr,
                      union rsbac_attribute_value_t attr_val,
                            rsbac_uid_t             owner)
  {
#ifdef CONFIG_RSBAC_JAIL_NET_ADJUST
    int err;
#endif
    union rsbac_target_id_t      i_tid;
    union rsbac_attribute_value_t i_attr_val1;
    union rsbac_attribute_value_t i_attr_val2;
    union rsbac_attribute_value_t i_attr_val3;

    switch (request)
      {
        case R_CLONE:
            if (target == T_PROCESS)
              {
                /* Get jail_id from first process */
                if (rsbac_get_attr(JAIL,
                                   T_PROCESS,
                                   tid,
                                   A_jail_id,
                                   &i_attr_val1,
                                   FALSE))
                  {
                    printk(KERN_WARNING
                           "rsbac_adf_set_attr_jail(): rsbac_get_attr() returned error!\n");
                    return(-RSBAC_EREADFAILED);
                  }
                /* Get jail_ip from first process */
                if (rsbac_get_attr(JAIL,
                                   T_PROCESS,
                                   tid,
                                   A_jail_ip,
                                   &i_attr_val2,
                                   FALSE))
                  {
                    printk(KERN_WARNING
                           "rsbac_adf_set_attr_jail(): rsbac_get_attr() returned error!\n");
                    return(-RSBAC_EREADFAILED);
                  }
                /* Get jail_flags from first process */
                if (rsbac_get_attr(JAIL,
                                   T_PROCESS,
                                   tid,
                                   A_jail_flags,
                                   &i_attr_val3,
                                   FALSE))
                  {
                    printk(KERN_WARNING
                           "rsbac_adf_set_attr_jail(): rsbac_get_attr() returned error!\n");
                    return(-RSBAC_EREADFAILED);
                  }
                /* Set jail_id for new process */
                if (rsbac_set_attr(JAIL,
                                   T_PROCESS,
                                   new_tid,
                                   A_jail_id,
                                   i_attr_val1))
                  {
                    printk(KERN_WARNING "rsbac_adf_set_attr_jail(): rsbac_set_attr() returned error!\n");
                    return(-RSBAC_EWRITEFAILED);
                  }
                /* Set jail_ip for new process */
                if (rsbac_set_attr(JAIL,
                                   T_PROCESS,
                                   new_tid,
                                   A_jail_ip,
                                   i_attr_val2))
                  {
                    printk(KERN_WARNING "rsbac_adf_set_attr_jail(): rsbac_set_attr() returned error!\n");
                    return(-RSBAC_EWRITEFAILED);
                  }
                /* Set jail_flags for new process */
                if (rsbac_set_attr(JAIL,
                                   T_PROCESS,
                                   new_tid,
                                   A_jail_flags,
                                   i_attr_val3))
                  {
                    printk(KERN_WARNING "rsbac_adf_set_attr_jail(): rsbac_set_attr() returned error!\n");
                    return(-RSBAC_EWRITEFAILED);
                  }
                return(0);
              }
            else
              return(0);

        case R_CREATE:
            if (target == T_IPC)
              {
                /* Get jail_id from process */
                i_tid.process = caller_pid;
                if (rsbac_get_attr(JAIL,
                                   T_PROCESS,
                                   i_tid,
                                   A_jail_id,
                                   &i_attr_val1,
                                   FALSE))
                  {
                    printk(KERN_WARNING
                           "rsbac_adf_set_attr_jail(): rsbac_get_attr() returned error!\n");
                    return(-RSBAC_EREADFAILED);
                  }
                /* Set jail_id for new IPC */
                if (rsbac_set_attr(JAIL,
                                   T_IPC,
                                   tid,
                                   A_jail_id,
                                   i_attr_val1))
                  {
                    printk(KERN_WARNING "rsbac_adf_set_attr_jail(): rsbac_set_attr() returned error!\n");
                    return(-RSBAC_EWRITEFAILED);
                  }
                return(0);
              }
            /* fall through */

#ifdef CONFIG_RSBAC_JAIL_NET_ADJUST
          case R_BIND:
            if(target != T_NETOBJ)
              return 0;
            if(!tid.netobj.sock_p)
              {
                printk(KERN_WARNING
                       "rsbac_adf_set_attr_jail(): NULL sock_p!\n");
                       return 0;
              }
            switch(tid.netobj.sock_p->ops->family)
              {
                case AF_INET:
                  i_tid.process = caller_pid;
                  if ((err=rsbac_get_attr(JAIL,
                                          T_PROCESS,
                                          i_tid,
                                          A_jail_ip,
                                          &i_attr_val1,
                                          TRUE)))
                    {
                      printk(KERN_WARNING "jail_get_id_process(): rsbac_get_attr() returned error %i!\n",err);
                      return -RSBAC_EREADFAILED;
                    }
                  if(i_attr_val1.jail_ip == INADDR_ANY)
                    return 0;
                  if ((err=rsbac_get_attr(JAIL,
                                          T_PROCESS,
                                          i_tid,
                                          A_jail_flags,
                                          &i_attr_val2,
                                          TRUE)))
                    {
                      printk(KERN_WARNING "jail_get_id_process(): rsbac_get_attr() returned error %i!\n",err);
                      return -RSBAC_EREADFAILED;
                    }
                  if(i_attr_val2.jail_flags & JAIL_auto_adjust_inet_any)
                    {
                      tid.netobj.sock_p->sk->rcv_saddr = i_attr_val1.jail_ip;
                      tid.netobj.sock_p->sk->saddr = i_attr_val1.jail_ip;
                    }
                  return 0;

                default:
                  break;
              }
#endif
            return 0;

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

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

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