]> Git Repo - linux.git/commitdiff
Merge tag 'selinux-pr-20210322' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <[email protected]>
Mon, 22 Mar 2021 18:34:31 +0000 (11:34 -0700)
committerLinus Torvalds <[email protected]>
Mon, 22 Mar 2021 18:34:31 +0000 (11:34 -0700)
Pull selinux fixes from Paul Moore:
 "Three SELinux patches:

   - Fix a problem where a local variable is used outside its associated
     function. Thankfully this can only be triggered by reloading the
     SELinux policy, which is a restricted operation for other obvious
     reasons.

   - Fix some incorrect, and inconsistent, audit and printk messages
     when loading the SELinux policy.

  All three patches are relatively minor and have been through our
  testing with no failures"

* tag 'selinux-pr-20210322' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinuxfs: unify policy load error reporting
  selinux: fix variable scope issue in live sidtab conversion
  selinux: don't log MAC_POLICY_LOAD record on failed policy load

1  2 
security/selinux/include/security.h
security/selinux/ss/services.c

index 6fe25300b89dc5b7aa40e55c0a525d691fe3f364,25db66e0ac5109150a224fc0a11824f06f8a1f1e..7650de0485700d4dd32d83e9e02d884b316fdc2e
@@@ -219,18 -219,24 +219,25 @@@ static inline bool selinux_policycap_ge
        return READ_ONCE(state->policycap[POLICYDB_CAPABILITY_GENFS_SECLABEL_SYMLINKS]);
  }
  
+ struct selinux_policy_convert_data;
+ struct selinux_load_state {
+       struct selinux_policy *policy;
+       struct selinux_policy_convert_data *convert_data;
+ };
  int security_mls_enabled(struct selinux_state *state);
  int security_load_policy(struct selinux_state *state,
-                       void *data, size_t len,
-                       struct selinux_policy **newpolicyp);
+                        void *data, size_t len,
+                        struct selinux_load_state *load_state);
  void selinux_policy_commit(struct selinux_state *state,
-                       struct selinux_policy *newpolicy);
+                          struct selinux_load_state *load_state);
  void selinux_policy_cancel(struct selinux_state *state,
-                       struct selinux_policy *policy);
+                          struct selinux_load_state *load_state);
  int security_read_policy(struct selinux_state *state,
                         void **data, size_t *len);
 -
 +int security_read_state_kernel(struct selinux_state *state,
 +                             void **data, size_t *len);
  int security_policycap_supported(struct selinux_state *state,
                                 unsigned int req_cap);
  
index 3438d0130378610132edaf6a1c8e846076f6b8fb,4a907e008a980d22cbb33f30f4ddfcb0bb4cd12b..d91e41d47777b26390b626fd38897548724c4b58
  #include "ebitmap.h"
  #include "audit.h"
  #include "policycap_names.h"
 +#include "ima.h"
  
+ struct convert_context_args {
+       struct selinux_state *state;
+       struct policydb *oldp;
+       struct policydb *newp;
+ };
+ struct selinux_policy_convert_data {
+       struct convert_context_args args;
+       struct sidtab_convert_params sidtab_params;
+ };
  /* Forward declaration. */
  static int context_struct_to_string(struct policydb *policydb,
                                    struct context *context,
@@@ -1974,12 -1984,6 +1985,6 @@@ static inline int convert_context_handl
        return 0;
  }
  
- struct convert_context_args {
-       struct selinux_state *state;
-       struct policydb *oldp;
-       struct policydb *newp;
- };
  /*
   * Convert the values in the security context
   * structure `oldc' from the values specified
@@@ -2159,7 -2163,7 +2164,7 @@@ static void selinux_policy_cond_free(st
  }
  
  void selinux_policy_cancel(struct selinux_state *state,
-                       struct selinux_policy *policy)
+                          struct selinux_load_state *load_state)
  {
        struct selinux_policy *oldpolicy;
  
                                        lockdep_is_held(&state->policy_mutex));
  
        sidtab_cancel_convert(oldpolicy->sidtab);
-       selinux_policy_free(policy);
+       selinux_policy_free(load_state->policy);
+       kfree(load_state->convert_data);
  }
  
  static void selinux_notify_policy_change(struct selinux_state *state,
        selinux_status_update_policyload(state, seqno);
        selinux_netlbl_cache_invalidate();
        selinux_xfrm_notify_policyload();
 +      selinux_ima_measure_state(state);
  }
  
  void selinux_policy_commit(struct selinux_state *state,
-                       struct selinux_policy *newpolicy)
+                          struct selinux_load_state *load_state)
  {
-       struct selinux_policy *oldpolicy;
+       struct selinux_policy *oldpolicy, *newpolicy = load_state->policy;
        u32 seqno;
  
        oldpolicy = rcu_dereference_protected(state->policy,
        /* Free the old policy */
        synchronize_rcu();
        selinux_policy_free(oldpolicy);
+       kfree(load_state->convert_data);
  
        /* Notify others of the policy change */
        selinux_notify_policy_change(state, seqno);
   * loading the new policy.
   */
  int security_load_policy(struct selinux_state *state, void *data, size_t len,
-                       struct selinux_policy **newpolicyp)
+                        struct selinux_load_state *load_state)
  {
        struct selinux_policy *newpolicy, *oldpolicy;
-       struct sidtab_convert_params convert_params;
-       struct convert_context_args args;
+       struct selinux_policy_convert_data *convert_data;
        int rc = 0;
        struct policy_file file = { data, len }, *fp = &file;
  
                goto err_mapping;
        }
  
        if (!selinux_initialized(state)) {
                /* First policy load, so no need to preserve state from old policy */
-               *newpolicyp = newpolicy;
+               load_state->policy = newpolicy;
+               load_state->convert_data = NULL;
                return 0;
        }
  
                goto err_free_isids;
        }
  
+       convert_data = kmalloc(sizeof(*convert_data), GFP_KERNEL);
+       if (!convert_data) {
+               rc = -ENOMEM;
+               goto err_free_isids;
+       }
        /*
         * Convert the internal representations of contexts
         * in the new SID table.
         */
-       args.state = state;
-       args.oldp = &oldpolicy->policydb;
-       args.newp = &newpolicy->policydb;
+       convert_data->args.state = state;
+       convert_data->args.oldp = &oldpolicy->policydb;
+       convert_data->args.newp = &newpolicy->policydb;
  
-       convert_params.func = convert_context;
-       convert_params.args = &args;
-       convert_params.target = newpolicy->sidtab;
+       convert_data->sidtab_params.func = convert_context;
+       convert_data->sidtab_params.args = &convert_data->args;
+       convert_data->sidtab_params.target = newpolicy->sidtab;
  
-       rc = sidtab_convert(oldpolicy->sidtab, &convert_params);
+       rc = sidtab_convert(oldpolicy->sidtab, &convert_data->sidtab_params);
        if (rc) {
                pr_err("SELinux:  unable to convert the internal"
                        " representation of contexts in the new SID"
                        " table\n");
-               goto err_free_isids;
+               goto err_free_convert_data;
        }
  
-       *newpolicyp = newpolicy;
+       load_state->policy = newpolicy;
+       load_state->convert_data = convert_data;
        return 0;
  
+ err_free_convert_data:
+       kfree(convert_data);
  err_free_isids:
        sidtab_destroy(newpolicy->sidtab);
  err_mapping:
  }
  #endif /* CONFIG_NETLABEL */
  
 +/**
 + * __security_read_policy - read the policy.
 + * @policy: SELinux policy
 + * @data: binary policy data
 + * @len: length of data in bytes
 + *
 + */
 +static int __security_read_policy(struct selinux_policy *policy,
 +                                void *data, size_t *len)
 +{
 +      int rc;
 +      struct policy_file fp;
 +
 +      fp.data = data;
 +      fp.len = *len;
 +
 +      rc = policydb_write(&policy->policydb, &fp);
 +      if (rc)
 +              return rc;
 +
 +      *len = (unsigned long)fp.data - (unsigned long)data;
 +      return 0;
 +}
 +
  /**
   * security_read_policy - read the policy.
 + * @state: selinux_state
   * @data: binary policy data
   * @len: length of data in bytes
   *
@@@ -3906,6 -3894,8 +3921,6 @@@ int security_read_policy(struct selinux
                         void **data, size_t *len)
  {
        struct selinux_policy *policy;
 -      int rc;
 -      struct policy_file fp;
  
        policy = rcu_dereference_protected(
                        state->policy, lockdep_is_held(&state->policy_mutex));
        if (!*data)
                return -ENOMEM;
  
 -      fp.data = *data;
 -      fp.len = *len;
 +      return __security_read_policy(policy, *data, len);
 +}
  
 -      rc = policydb_write(&policy->policydb, &fp);
 -      if (rc)
 -              return rc;
 +/**
 + * security_read_state_kernel - read the policy.
 + * @state: selinux_state
 + * @data: binary policy data
 + * @len: length of data in bytes
 + *
 + * Allocates kernel memory for reading SELinux policy.
 + * This function is for internal use only and should not
 + * be used for returning data to user space.
 + *
 + * This function must be called with policy_mutex held.
 + */
 +int security_read_state_kernel(struct selinux_state *state,
 +                             void **data, size_t *len)
 +{
 +      struct selinux_policy *policy;
  
 -      *len = (unsigned long)fp.data - (unsigned long)*data;
 -      return 0;
 +      policy = rcu_dereference_protected(
 +                      state->policy, lockdep_is_held(&state->policy_mutex));
 +      if (!policy)
 +              return -EINVAL;
 +
 +      *len = policy->policydb.len;
 +      *data = vmalloc(*len);
 +      if (!*data)
 +              return -ENOMEM;
  
 +      return __security_read_policy(policy, *data, len);
  }
This page took 0.064378 seconds and 4 git commands to generate.