Merge branch 'master' into next
authorJames Morris <jmorris@namei.org>
Thu, 18 Jun 2009 22:20:55 +0000 (08:20 +1000)
committerJames Morris <jmorris@namei.org>
Thu, 18 Jun 2009 22:20:55 +0000 (08:20 +1000)
1  2 
security/selinux/avc.c
security/selinux/ss/services.c

diff --combined security/selinux/avc.c
@@@ -137,7 -137,7 +137,7 @@@ static inline int avc_hash(u32 ssid, u3
   * @tclass: target security class
   * @av: access vector
   */
 -void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
 +static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
  {
        const char **common_pts = NULL;
        u32 common_base = 0;
@@@ -927,7 -927,7 +927,7 @@@ int avc_has_perm_noaudit(u32 ssid, u32 
        if (denied) {
                if (flags & AVC_STRICT)
                        rc = -EACCES;
-               else if (!selinux_enforcing || security_permissive_sid(ssid))
+               else if (!selinux_enforcing || (avd->flags & AVD_FLAGS_PERMISSIVE))
                        avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
                                        tsid, tclass, avd->seqno);
                else
   *
   *  Added validation of kernel classes and permissions
   *
 + * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
 + *
 + *  Added support for bounds domain and audit messaged on masked permissions
 + *
 + * Copyright (C) 2008, 2009 NEC Corporation
   * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
   * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
   * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
@@@ -284,95 -279,6 +284,95 @@@ mls_ops
  }
  
  /*
 + * security_dump_masked_av - dumps masked permissions during
 + * security_compute_av due to RBAC, MLS/Constraint and Type bounds.
 + */
 +static int dump_masked_av_helper(void *k, void *d, void *args)
 +{
 +      struct perm_datum *pdatum = d;
 +      char **permission_names = args;
 +
 +      BUG_ON(pdatum->value < 1 || pdatum->value > 32);
 +
 +      permission_names[pdatum->value - 1] = (char *)k;
 +
 +      return 0;
 +}
 +
 +static void security_dump_masked_av(struct context *scontext,
 +                                  struct context *tcontext,
 +                                  u16 tclass,
 +                                  u32 permissions,
 +                                  const char *reason)
 +{
 +      struct common_datum *common_dat;
 +      struct class_datum *tclass_dat;
 +      struct audit_buffer *ab;
 +      char *tclass_name;
 +      char *scontext_name = NULL;
 +      char *tcontext_name = NULL;
 +      char *permission_names[32];
 +      int index, length;
 +      bool need_comma = false;
 +
 +      if (!permissions)
 +              return;
 +
 +      tclass_name = policydb.p_class_val_to_name[tclass - 1];
 +      tclass_dat = policydb.class_val_to_struct[tclass - 1];
 +      common_dat = tclass_dat->comdatum;
 +
 +      /* init permission_names */
 +      if (common_dat &&
 +          hashtab_map(common_dat->permissions.table,
 +                      dump_masked_av_helper, permission_names) < 0)
 +              goto out;
 +
 +      if (hashtab_map(tclass_dat->permissions.table,
 +                      dump_masked_av_helper, permission_names) < 0)
 +              goto out;
 +
 +      /* get scontext/tcontext in text form */
 +      if (context_struct_to_string(scontext,
 +                                   &scontext_name, &length) < 0)
 +              goto out;
 +
 +      if (context_struct_to_string(tcontext,
 +                                   &tcontext_name, &length) < 0)
 +              goto out;
 +
 +      /* audit a message */
 +      ab = audit_log_start(current->audit_context,
 +                           GFP_ATOMIC, AUDIT_SELINUX_ERR);
 +      if (!ab)
 +              goto out;
 +
 +      audit_log_format(ab, "op=security_compute_av reason=%s "
 +                       "scontext=%s tcontext=%s tclass=%s perms=",
 +                       reason, scontext_name, tcontext_name, tclass_name);
 +
 +      for (index = 0; index < 32; index++) {
 +              u32 mask = (1 << index);
 +
 +              if ((mask & permissions) == 0)
 +                      continue;
 +
 +              audit_log_format(ab, "%s%s",
 +                               need_comma ? "," : "",
 +                               permission_names[index]
 +                               ? permission_names[index] : "????");
 +              need_comma = true;
 +      }
 +      audit_log_end(ab);
 +out:
 +      /* release scontext/tcontext */
 +      kfree(tcontext_name);
 +      kfree(scontext_name);
 +
 +      return;
 +}
 +
 +/*
   * security_boundary_permission - drops violated permissions
   * on boundary constraint.
   */
@@@ -441,12 -347,28 +441,12 @@@ static void type_attribute_bounds_av(st
        }
  
        if (masked) {
                /* mask violated permissions */
                avd->allowed &= ~masked;
  
 -              /* notice to userspace via audit message */
 -              ab = audit_log_start(current->audit_context,
 -                                   GFP_ATOMIC, AUDIT_SELINUX_ERR);
 -              if (!ab)
 -                      return;
 -
 -              audit_log_format(ab, "av boundary violation: "
 -                               "source=%s target=%s tclass=%s",
 -                               stype_name, ttype_name, tclass_name);
 -              avc_dump_av(ab, tclass, masked);
 -              audit_log_end(ab);
 +              /* audit masked permissions */
 +              security_dump_masked_av(scontext, tcontext,
 +                                      tclass, masked, "bounds");
        }
  }
  
@@@ -488,6 -410,7 +488,7 @@@ static int context_struct_compute_av(st
        avd->auditallow = 0;
        avd->auditdeny = 0xffffffff;
        avd->seqno = latest_granting;
+       avd->flags = 0;
  
        /*
         * Check for all the invalid cases.
                if ((constraint->permissions & (avd->allowed)) &&
                    !constraint_expr_eval(scontext, tcontext, NULL,
                                          constraint->expr)) {
 -                      avd->allowed = (avd->allowed) & ~(constraint->permissions);
 +                      avd->allowed &= ~(constraint->permissions);
                }
                constraint = constraint->next;
        }
                                break;
                }
                if (!ra)
 -                      avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
 -                                                      PROCESS__DYNTRANSITION);
 +                      avd->allowed &= ~(PROCESS__TRANSITION |
 +                                        PROCESS__DYNTRANSITION);
        }
  
        /*
@@@ -606,31 -529,6 +607,6 @@@ inval_class
        return 0;
  }
  
- /*
-  * Given a sid find if the type has the permissive flag set
-  */
- int security_permissive_sid(u32 sid)
- {
-       struct context *context;
-       u32 type;
-       int rc;
-       read_lock(&policy_rwlock);
-       context = sidtab_search(&sidtab, sid);
-       BUG_ON(!context);
-       type = context->type;
-       /*
-        * we are intentionally using type here, not type-1, the 0th bit may
-        * someday indicate that we are globally setting permissive in policy.
-        */
-       rc = ebitmap_get_bit(&policydb.permissive_map, type);
-       read_unlock(&policy_rwlock);
-       return rc;
- }
  static int security_validtrans_handle_fail(struct context *ocontext,
                                           struct context *ncontext,
                                           struct context *tcontext,
@@@ -789,26 -687,6 +765,26 @@@ int security_bounded_transition(u32 old
                }
                index = type->bounds;
        }
 +
 +      if (rc) {
 +              char *old_name = NULL;
 +              char *new_name = NULL;
 +              int length;
 +
 +              if (!context_struct_to_string(old_context,
 +                                            &old_name, &length) &&
 +                  !context_struct_to_string(new_context,
 +                                            &new_name, &length)) {
 +                      audit_log(current->audit_context,
 +                                GFP_ATOMIC, AUDIT_SELINUX_ERR,
 +                                "op=security_bounded_transition "
 +                                "result=denied "
 +                                "oldcontext=%s newcontext=%s",
 +                                old_name, new_name);
 +              }
 +              kfree(new_name);
 +              kfree(old_name);
 +      }
  out:
        read_unlock(&policy_rwlock);
  
@@@ -865,6 -743,10 +841,10 @@@ int security_compute_av(u32 ssid
  
        rc = context_struct_compute_av(scontext, tcontext, tclass,
                                       requested, avd);
+       /* permissive domain? */
+       if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+           avd->flags |= AVD_FLAGS_PERMISSIVE;
  out:
        read_unlock(&policy_rwlock);
        return rc;