]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 May 2017 15:50:52 +0000 (08:50 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 May 2017 15:50:52 +0000 (08:50 -0700)
Pull security subsystem updates from James Morris:
 "Highlights:

  IMA:
   - provide ">" and "<" operators for fowner/uid/euid rules

  KEYS:
   - add a system blacklist keyring

   - add KEYCTL_RESTRICT_KEYRING, exposes keyring link restriction
     functionality to userland via keyctl()

  LSM:
   - harden LSM API with __ro_after_init

   - add prlmit security hook, implement for SELinux

   - revive security_task_alloc hook

  TPM:
   - implement contextual TPM command 'spaces'"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (98 commits)
  tpm: Fix reference count to main device
  tpm_tis: convert to using locality callbacks
  tpm: fix handling of the TPM 2.0 event logs
  tpm_crb: remove a cruft constant
  keys: select CONFIG_CRYPTO when selecting DH / KDF
  apparmor: Make path_max parameter readonly
  apparmor: fix parameters so that the permission test is bypassed at boot
  apparmor: fix invalid reference to index variable of iterator line 836
  apparmor: use SHASH_DESC_ON_STACK
  security/apparmor/lsm.c: set debug messages
  apparmor: fix boolreturn.cocci warnings
  Smack: Use GFP_KERNEL for smk_netlbl_mls().
  smack: fix double free in smack_parse_opts_str()
  KEYS: add SP800-56A KDF support for DH
  KEYS: Keyring asymmetric key restrict method with chaining
  KEYS: Restrict asymmetric key linkage using a specific keychain
  KEYS: Add a lookup_restriction function for the asymmetric key type
  KEYS: Add KEYCTL_RESTRICT_KEYRING
  KEYS: Consistent ordering for __key_link_begin and restrict check
  KEYS: Add an optional lookup_restriction hook to key_type
  ...

1  2 
fs/namei.c
include/linux/compat.h
include/linux/init_task.h
include/linux/sched.h
kernel/fork.c
security/Kconfig
security/keys/gc.c
security/keys/keyctl.c
security/keys/process_keys.c
security/security.c
security/selinux/nlmsgtab.c

diff --combined fs/namei.c
index 19dcf62133cc95162d364f7ef43c17d280ee6448,482414aa558b172de0a5d395d55ece7cc385dd7c..9a7f8bd748d817b29901e82943e06ae05811f73b
@@@ -340,22 -340,14 +340,14 @@@ int generic_permission(struct inode *in
  
        if (S_ISDIR(inode->i_mode)) {
                /* DACs are overridable for directories */
-               if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
-                       return 0;
                if (!(mask & MAY_WRITE))
                        if (capable_wrt_inode_uidgid(inode,
                                                     CAP_DAC_READ_SEARCH))
                                return 0;
-               return -EACCES;
-       }
-       /*
-        * Read/write DACs are always overridable.
-        * Executable DACs are overridable when there is
-        * at least one exec bit set.
-        */
-       if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
                if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
                        return 0;
+               return -EACCES;
+       }
  
        /*
         * Searching includes executable on directories, else just read.
        if (mask == MAY_READ)
                if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH))
                        return 0;
+       /*
+        * Read/write DACs are always overridable.
+        * Executable DACs are overridable when there is
+        * at least one exec bit set.
+        */
+       if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
+               if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
+                       return 0;
  
        return -EACCES;
  }
@@@ -2145,9 -2145,6 +2145,9 @@@ static const char *path_init(struct nam
        int retval = 0;
        const char *s = nd->name->name;
  
 +      if (!*s)
 +              flags &= ~LOOKUP_RCU;
 +
        nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags | LOOKUP_JUMPED | LOOKUP_PARENT;
        nd->depth = 0;
diff --combined include/linux/compat.h
index 8172b03685f9651045521f9f3d1a7f0ac0ba68b6,993c87182e02d23ae0d5951911e700a4b0c447d7..1c5f3152cbb57796caf1a587103ed3d092324a04
@@@ -295,6 -295,13 +295,13 @@@ struct compat_old_sigaction 
  };
  #endif
  
+ struct compat_keyctl_kdf_params {
+       compat_uptr_t hashname;
+       compat_uptr_t otherinfo;
+       __u32 otherinfolen;
+       __u32 __spare[8];
+ };
  struct compat_statfs;
  struct compat_statfs64;
  struct compat_old_linux_dirent;
@@@ -528,6 -535,11 +535,6 @@@ asmlinkage long compat_sys_old_readdir(
  asmlinkage long compat_sys_getdents(unsigned int fd,
                                    struct compat_linux_dirent __user *dirent,
                                    unsigned int count);
 -#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
 -asmlinkage long compat_sys_getdents64(unsigned int fd,
 -                                    struct linux_dirent64 __user *dirent,
 -                                    unsigned int count);
 -#endif
  asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *,
                                    unsigned int nr_segs, unsigned int flags);
  asmlinkage long compat_sys_open(const char __user *filename, int flags,
@@@ -718,8 -730,6 +725,8 @@@ asmlinkage long compat_sys_sched_rr_get
  asmlinkage long compat_sys_fanotify_mark(int, unsigned int, __u32, __u32,
                                            int, const char __user *);
  
 +asmlinkage long compat_sys_arch_prctl(int option, unsigned long arg2);
 +
  /*
   * For most but not all architectures, "am I in a compat syscall?" and
   * "am I a compat task?" are the same question.  For architectures on which
index 82be96564266ca80647a06833e386162b7537b81,926f2f553cc5bcf930a5bf1a9d6977b433d2069f..e049526bc188f765c7521653cf6fb90a574bc673
@@@ -15,7 -15,6 +15,7 @@@
  #include <linux/sched/autogroup.h>
  #include <net/net_namespace.h>
  #include <linux/sched/rt.h>
 +#include <linux/livepatch.h>
  #include <linux/mm_types.h>
  
  #include <asm/thread_info.h>
@@@ -182,7 -181,6 +182,7 @@@ extern struct cred init_cred
  #ifdef CONFIG_RT_MUTEXES
  # define INIT_RT_MUTEXES(tsk)                                         \
        .pi_waiters = RB_ROOT,                                          \
 +      .pi_top_task = NULL,                                            \
        .pi_waiters_leftmost = NULL,
  #else
  # define INIT_RT_MUTEXES(tsk)
  # define INIT_KASAN(tsk)
  #endif
  
 +#ifdef CONFIG_LIVEPATCH
 +# define INIT_LIVEPATCH(tsk)                                          \
 +      .patch_state = KLP_UNDEFINED,
 +#else
 +# define INIT_LIVEPATCH(tsk)
 +#endif
 +
  #ifdef CONFIG_THREAD_INFO_IN_TASK
  # define INIT_TASK_TI(tsk)                    \
        .thread_info = INIT_THREAD_INFO(tsk),   \
  # define INIT_TASK_TI(tsk)
  #endif
  
+ #ifdef CONFIG_SECURITY
+ #define INIT_TASK_SECURITY .security = NULL,
+ #else
+ #define INIT_TASK_SECURITY
+ #endif
  /*
   *  INIT_TASK is used to set up the first task table, touch at
   * your own risk!. Base=0, limit=0x1fffff (=2MB)
        INIT_VTIME(tsk)                                                 \
        INIT_NUMA_BALANCING(tsk)                                        \
        INIT_KASAN(tsk)                                                 \
 +      INIT_LIVEPATCH(tsk)                                             \
+       INIT_TASK_SECURITY                                              \
  }
  
  
diff --combined include/linux/sched.h
index 1e590c3bd5815a798b6ede321e738fca4437e474,71b8df306bb04f66229fc7f3e287d643f5174b26..3d4fa448223fd60f0af37f3b6b274483593af468
@@@ -186,7 -186,7 +186,7 @@@ extern long io_schedule_timeout(long ti
  extern void io_schedule(void);
  
  /**
 - * struct prev_cputime - snaphsot of system and user cputime
 + * struct prev_cputime - snapshot of system and user cputime
   * @utime: time spent in user mode
   * @stime: time spent in system mode
   * @lock: protects the above two fields
@@@ -604,10 -604,6 +604,10 @@@ struct task_struct 
  #ifdef CONFIG_COMPAT_BRK
        unsigned                        brk_randomized:1;
  #endif
 +#ifdef CONFIG_CGROUPS
 +      /* disallow userland-initiated cgroup migration */
 +      unsigned                        no_cgroup_migration:1;
 +#endif
  
        unsigned long                   atomic_flags; /* Flags requiring atomic access. */
  
        /* PI waiters blocked on a rt_mutex held by this task: */
        struct rb_root                  pi_waiters;
        struct rb_node                  *pi_waiters_leftmost;
 +      /* Updated under owner's pi_lock and rq lock */
 +      struct task_struct              *pi_top_task;
        /* Deadlock detection and priority inheritance handling: */
        struct rt_mutex_waiter          *pi_blocked_on;
  #endif
        /* A live task holds one reference: */
        atomic_t                        stack_refcount;
  #endif
 +#ifdef CONFIG_LIVEPATCH
 +      int patch_state;
++#endif
+ #ifdef CONFIG_SECURITY
+       /* Used by LSM modules for access restriction: */
+       void                            *security;
  #endif
        /* CPU-specific state of this task: */
        struct thread_struct            thread;
@@@ -1295,10 -1290,10 +1299,10 @@@ TASK_PFA_TEST(LMK_WAITING, lmk_waiting
  TASK_PFA_SET(LMK_WAITING, lmk_waiting)
  
  static inline void
 -tsk_restore_flags(struct task_struct *task, unsigned long orig_flags, unsigned long flags)
 +current_restore_flags(unsigned long orig_flags, unsigned long flags)
  {
 -      task->flags &= ~flags;
 -      task->flags |= orig_flags & flags;
 +      current->flags &= ~flags;
 +      current->flags |= orig_flags & flags;
  }
  
  extern int cpuset_cpumask_can_shrink(const struct cpumask *cur, const struct cpumask *trial);
diff --combined kernel/fork.c
index 56d85fd81411a1a2746a053c7729df56985f9c3f,3d32513d6c7308c295d62617c267ff74d5e7052b..dd5a371c392a7fab7330dbe456a48296b4614b98
@@@ -87,7 -87,6 +87,7 @@@
  #include <linux/compiler.h>
  #include <linux/sysctl.h>
  #include <linux/kcov.h>
 +#include <linux/livepatch.h>
  
  #include <asm/pgtable.h>
  #include <asm/pgalloc.h>
@@@ -1439,7 -1438,6 +1439,7 @@@ static void rt_mutex_init_task(struct t
  #ifdef CONFIG_RT_MUTEXES
        p->pi_waiters = RB_ROOT;
        p->pi_waiters_leftmost = NULL;
 +      p->pi_top_task = NULL;
        p->pi_blocked_on = NULL;
  #endif
  }
@@@ -1681,9 -1679,12 +1681,12 @@@ static __latent_entropy struct task_str
                goto bad_fork_cleanup_perf;
        /* copy all the process information */
        shm_init_task(p);
-       retval = copy_semundo(clone_flags, p);
+       retval = security_task_alloc(p, clone_flags);
        if (retval)
                goto bad_fork_cleanup_audit;
+       retval = copy_semundo(clone_flags, p);
+       if (retval)
+               goto bad_fork_cleanup_security;
        retval = copy_files(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_semundo;
                p->parent_exec_id = current->self_exec_id;
        }
  
 +      klp_copy_process(p);
 +
        spin_lock(&current->sighand->siglock);
  
        /*
@@@ -1907,6 -1906,8 +1910,8 @@@ bad_fork_cleanup_files
        exit_files(p); /* blocking */
  bad_fork_cleanup_semundo:
        exit_sem(p);
+ bad_fork_cleanup_security:
+       security_task_free(p);
  bad_fork_cleanup_audit:
        audit_free(p);
  bad_fork_cleanup_perf:
@@@ -2356,8 -2357,6 +2361,8 @@@ SYSCALL_DEFINE1(unshare, unsigned long
                }
        }
  
 +      perf_event_namespaces(current);
 +
  bad_unshare_cleanup_cred:
        if (new_cred)
                put_cred(new_cred);
diff --combined security/Kconfig
index 213df4d4f2c1527adcae47fa6bd9da0f0956e5f3,3ff1bf91080eb5c3b1c207c51645fe91027f4cd5..93027fdf47d1c7b610a4c7e15996bc288ceaba48
@@@ -31,6 -31,11 +31,11 @@@ config SECURIT
  
          If you are unsure how to answer this question, answer N.
  
+ config SECURITY_WRITABLE_HOOKS
+       depends on SECURITY
+       bool
+       default n
  config SECURITYFS
        bool "Enable the securityfs filesystem"
        help
@@@ -125,8 -130,17 +130,8 @@@ config HAVE_HARDENED_USERCOPY_ALLOCATO
          validating memory ranges against heap object sizes in
          support of CONFIG_HARDENED_USERCOPY.
  
 -config HAVE_ARCH_HARDENED_USERCOPY
 -      bool
 -      help
 -        The architecture supports CONFIG_HARDENED_USERCOPY by
 -        calling check_object_size() just before performing the
 -        userspace copies in the low level implementation of
 -        copy_to_user() and copy_from_user().
 -
  config HARDENED_USERCOPY
        bool "Harden memory copies between kernel and userspace"
 -      depends on HAVE_ARCH_HARDENED_USERCOPY
        depends on HAVE_HARDENED_USERCOPY_ALLOCATOR
        select BUG
        help
diff --combined security/keys/gc.c
index 9cb4fe4478a137e7bb3352ae958830657f6b5b7c,15b9ddf510e4eaccf0b7c56aa4c99f1e099a4731..595becc6d0d259a017be1305842f6208562324bb
@@@ -46,7 -46,7 +46,7 @@@ static unsigned long key_gc_flags
   * immediately unlinked.
   */
  struct key_type key_type_dead = {
 -      .name = "dead",
 +      .name = ".dead",
  };
  
  /*
@@@ -220,7 -220,7 +220,7 @@@ continue_scanning
                key = rb_entry(cursor, struct key, serial_node);
                cursor = rb_next(cursor);
  
-               if (atomic_read(&key->usage) == 0)
+               if (refcount_read(&key->usage) == 0)
                        goto found_unreferenced_key;
  
                if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) {
                                set_bit(KEY_FLAG_DEAD, &key->flags);
                                key->perm = 0;
                                goto skip_dead_key;
+                       } else if (key->type == &key_type_keyring &&
+                                  key->restrict_link) {
+                               goto found_restricted_keyring;
                        }
                }
  
@@@ -334,6 -337,14 +337,14 @@@ found_unreferenced_key
        gc_state |= KEY_GC_REAP_AGAIN;
        goto maybe_resched;
  
+       /* We found a restricted keyring and need to update the restriction if
+        * it is associated with the dead key type.
+        */
+ found_restricted_keyring:
+       spin_unlock(&key_serial_lock);
+       keyring_restriction_gc(key, key_gc_dead_keytype);
+       goto maybe_resched;
        /* We found a keyring and we need to check the payload for links to
         * dead or expired keys.  We don't flag another reap immediately as we
         * have to wait for the old payload to be destroyed by RCU before we
diff --combined security/keys/keyctl.c
index 4ad3212adebe8becc152f22d2448f8db4716146b,10fcea154c0f660591f86226465b44674c14d272..82a9e18511089d12d0bf674b63d57f9aa6363ef5
@@@ -273,8 -273,7 +273,8 @@@ error
   * Create and join an anonymous session keyring or join a named session
   * keyring, creating it if necessary.  A named session keyring must have Search
   * permission for it to be joined.  Session keyrings without this permit will
 - * be skipped over.
 + * be skipped over.  It is not permitted for userspace to create or join
 + * keyrings whose name begin with a dot.
   *
   * If successful, the ID of the joined session keyring will be returned.
   */
@@@ -291,16 -290,12 +291,16 @@@ long keyctl_join_session_keyring(const 
                        ret = PTR_ERR(name);
                        goto error;
                }
 +
 +              ret = -EPERM;
 +              if (name[0] == '.')
 +                      goto error_name;
        }
  
        /* join the session */
        ret = join_session_keyring(name);
 +error_name:
        kfree(name);
 -
  error:
        return ret;
  }
@@@ -1258,8 -1253,8 +1258,8 @@@ error
   * Read or set the default keyring in which request_key() will cache keys and
   * return the old setting.
   *
 - * If a process keyring is specified then this will be created if it doesn't
 - * yet exist.  The old setting will be returned if successful.
 + * If a thread or process keyring is specified then it will be created if it
 + * doesn't yet exist.  The old setting will be returned if successful.
   */
  long keyctl_set_reqkey_keyring(int reqkey_defl)
  {
  
        case KEY_REQKEY_DEFL_PROCESS_KEYRING:
                ret = install_process_keyring_to_cred(new);
 -              if (ret < 0) {
 -                      if (ret != -EEXIST)
 -                              goto error;
 -                      ret = 0;
 -              }
 +              if (ret < 0)
 +                      goto error;
                goto set;
  
        case KEY_REQKEY_DEFL_DEFAULT:
@@@ -1584,6 -1582,59 +1584,59 @@@ error_keyring
        return ret;
  }
  
+ /*
+  * Apply a restriction to a given keyring.
+  *
+  * The caller must have Setattr permission to change keyring restrictions.
+  *
+  * The requested type name may be a NULL pointer to reject all attempts
+  * to link to the keyring. If _type is non-NULL, _restriction can be
+  * NULL or a pointer to a string describing the restriction. If _type is
+  * NULL, _restriction must also be NULL.
+  *
+  * Returns 0 if successful.
+  */
+ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
+                            const char __user *_restriction)
+ {
+       key_ref_t key_ref;
+       bool link_reject = !_type;
+       char type[32];
+       char *restriction = NULL;
+       long ret;
+       key_ref = lookup_user_key(id, 0, KEY_NEED_SETATTR);
+       if (IS_ERR(key_ref))
+               return PTR_ERR(key_ref);
+       if (_type) {
+               ret = key_get_type_from_user(type, _type, sizeof(type));
+               if (ret < 0)
+                       goto error;
+       }
+       if (_restriction) {
+               if (!_type) {
+                       ret = -EINVAL;
+                       goto error;
+               }
+               restriction = strndup_user(_restriction, PAGE_SIZE);
+               if (IS_ERR(restriction)) {
+                       ret = PTR_ERR(restriction);
+                       goto error;
+               }
+       }
+       ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction);
+       kfree(restriction);
+ error:
+       key_ref_put(key_ref);
+       return ret;
+ }
  /*
   * The key control system call
   */
@@@ -1693,7 -1744,12 +1746,12 @@@ SYSCALL_DEFINE5(keyctl, int, option, un
        case KEYCTL_DH_COMPUTE:
                return keyctl_dh_compute((struct keyctl_dh_params __user *) arg2,
                                         (char __user *) arg3, (size_t) arg4,
-                                        (void __user *) arg5);
+                                        (struct keyctl_kdf_params __user *) arg5);
+       case KEYCTL_RESTRICT_KEYRING:
+               return keyctl_restrict_keyring((key_serial_t) arg2,
+                                              (const char __user *) arg3,
+                                              (const char __user *) arg4);
  
        default:
                return -EOPNOTSUPP;
index 9139b18fc863eb36d62d7777f1553dda63236dfe,44451af828c0df0bee4fb52453000514113d0109..2217dfec7996159797abce9d2480fa249691cf28
@@@ -30,7 -30,7 +30,7 @@@ static DEFINE_MUTEX(key_user_keyring_mu
  
  /* The root user's tracking struct */
  struct key_user root_key_user = {
-       .usage          = ATOMIC_INIT(3),
+       .usage          = REFCOUNT_INIT(3),
        .cons_lock      = __MUTEX_INITIALIZER(root_key_user.cons_lock),
        .lock           = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
        .nkeys          = ATOMIC_INIT(2),
@@@ -128,18 -128,13 +128,18 @@@ error
  }
  
  /*
 - * Install a fresh thread keyring directly to new credentials.  This keyring is
 - * allowed to overrun the quota.
 + * Install a thread keyring to the given credentials struct if it didn't have
 + * one already.  This is allowed to overrun the quota.
 + *
 + * Return: 0 if a thread keyring is now present; -errno on failure.
   */
  int install_thread_keyring_to_cred(struct cred *new)
  {
        struct key *keyring;
  
 +      if (new->thread_keyring)
 +              return 0;
 +
        keyring = keyring_alloc("_tid", new->uid, new->gid, new,
                                KEY_POS_ALL | KEY_USR_VIEW,
                                KEY_ALLOC_QUOTA_OVERRUN,
  }
  
  /*
 - * Install a fresh thread keyring, discarding the old one.
 + * Install a thread keyring to the current task if it didn't have one already.
 + *
 + * Return: 0 if a thread keyring is now present; -errno on failure.
   */
  static int install_thread_keyring(void)
  {
        if (!new)
                return -ENOMEM;
  
 -      BUG_ON(new->thread_keyring);
 -
        ret = install_thread_keyring_to_cred(new);
        if (ret < 0) {
                abort_creds(new);
  }
  
  /*
 - * Install a process keyring directly to a credentials struct.
 + * Install a process keyring to the given credentials struct if it didn't have
 + * one already.  This is allowed to overrun the quota.
   *
 - * Returns -EEXIST if there was already a process keyring, 0 if one installed,
 - * and other value on any other error
 + * Return: 0 if a process keyring is now present; -errno on failure.
   */
  int install_process_keyring_to_cred(struct cred *new)
  {
        struct key *keyring;
  
        if (new->process_keyring)
 -              return -EEXIST;
 +              return 0;
  
        keyring = keyring_alloc("_pid", new->uid, new->gid, new,
                                KEY_POS_ALL | KEY_USR_VIEW,
  }
  
  /*
 - * Make sure a process keyring is installed for the current process.  The
 - * existing process keyring is not replaced.
 + * Install a process keyring to the current task if it didn't have one already.
   *
 - * Returns 0 if there is a process keyring by the end of this function, some
 - * error otherwise.
 + * Return: 0 if a process keyring is now present; -errno on failure.
   */
  static int install_process_keyring(void)
  {
        ret = install_process_keyring_to_cred(new);
        if (ret < 0) {
                abort_creds(new);
 -              return ret != -EEXIST ? ret : 0;
 +              return ret;
        }
  
        return commit_creds(new);
  }
  
  /*
 - * Install a session keyring directly to a credentials struct.
 + * Install the given keyring as the session keyring of the given credentials
 + * struct, replacing the existing one if any.  If the given keyring is NULL,
 + * then install a new anonymous session keyring.
 + *
 + * Return: 0 on success; -errno on failure.
   */
  int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
  {
  }
  
  /*
 - * Install a session keyring, discarding the old one.  If a keyring is not
 - * supplied, an empty one is invented.
 + * Install the given keyring as the session keyring of the current task,
 + * replacing the existing one if any.  If the given keyring is NULL, then
 + * install a new anonymous session keyring.
 + *
 + * Return: 0 on success; -errno on failure.
   */
  static int install_session_keyring(struct key *keyring)
  {
diff --combined security/security.c
index 23555c5504f6cd541b07a1c3954b317e73ee0061,549bddcc21164e2952b7c7b65b81e9ded525dd11..b9fea3999cf85f7181eceb5041468117f1376f32
@@@ -32,6 -32,7 +32,7 @@@
  /* Maximum number of letters for an LSM name string */
  #define SECURITY_NAME_MAX     10
  
+ struct security_hook_heads security_hook_heads __lsm_ro_after_init;
  char *lsm_names;
  /* Boot-time LSM user choice */
  static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
@@@ -54,6 -55,12 +55,12 @@@ static void __init do_security_initcall
   */
  int __init security_init(void)
  {
+       int i;
+       struct list_head *list = (struct list_head *) &security_hook_heads;
+       for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct list_head);
+            i++)
+               INIT_LIST_HEAD(&list[i]);
        pr_info("Security Framework initialized\n");
  
        /*
@@@ -103,14 -110,10 +110,14 @@@ static int lsm_append(char *new, char *
   * to avoid security registration races. This method may also be used
   * to check if your LSM is currently loaded during kernel initialization.
   *
 - * Return true if:
 - *    -The passed LSM is the one chosen by user at boot time,
 - *    -or the passed LSM is configured as the default and the user did not
 - *     choose an alternate LSM at boot time.
 + * Returns:
 + *
 + * true if:
 + *
 + * - The passed LSM is the one chosen by user at boot time,
 + * - or the passed LSM is configured as the default and the user did not
 + *   choose an alternate LSM at boot time.
 + *
   * Otherwise, return false.
   */
  int __init security_module_enable(const char *module)
@@@ -934,6 -937,11 +941,11 @@@ int security_task_create(unsigned long 
        return call_int_hook(task_create, 0, clone_flags);
  }
  
+ int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
+ {
+       return call_int_hook(task_alloc, 0, task, clone_flags);
+ }
  void security_task_free(struct task_struct *task)
  {
        call_void_hook(task_free, task);
@@@ -1040,6 -1048,12 +1052,12 @@@ int security_task_getioprio(struct task
        return call_int_hook(task_getioprio, 0, p);
  }
  
+ int security_task_prlimit(const struct cred *cred, const struct cred *tcred,
+                         unsigned int flags)
+ {
+       return call_int_hook(task_prlimit, 0, cred, tcred, flags);
+ }
  int security_task_setrlimit(struct task_struct *p, unsigned int resource,
                struct rlimit *new_rlim)
  {
@@@ -1625,355 -1639,3 +1643,3 @@@ int security_audit_rule_match(u32 secid
                                actx);
  }
  #endif /* CONFIG_AUDIT */
- struct security_hook_heads security_hook_heads = {
-       .binder_set_context_mgr =
-               LIST_HEAD_INIT(security_hook_heads.binder_set_context_mgr),
-       .binder_transaction =
-               LIST_HEAD_INIT(security_hook_heads.binder_transaction),
-       .binder_transfer_binder =
-               LIST_HEAD_INIT(security_hook_heads.binder_transfer_binder),
-       .binder_transfer_file =
-               LIST_HEAD_INIT(security_hook_heads.binder_transfer_file),
-       .ptrace_access_check =
-               LIST_HEAD_INIT(security_hook_heads.ptrace_access_check),
-       .ptrace_traceme =
-               LIST_HEAD_INIT(security_hook_heads.ptrace_traceme),
-       .capget =       LIST_HEAD_INIT(security_hook_heads.capget),
-       .capset =       LIST_HEAD_INIT(security_hook_heads.capset),
-       .capable =      LIST_HEAD_INIT(security_hook_heads.capable),
-       .quotactl =     LIST_HEAD_INIT(security_hook_heads.quotactl),
-       .quota_on =     LIST_HEAD_INIT(security_hook_heads.quota_on),
-       .syslog =       LIST_HEAD_INIT(security_hook_heads.syslog),
-       .settime =      LIST_HEAD_INIT(security_hook_heads.settime),
-       .vm_enough_memory =
-               LIST_HEAD_INIT(security_hook_heads.vm_enough_memory),
-       .bprm_set_creds =
-               LIST_HEAD_INIT(security_hook_heads.bprm_set_creds),
-       .bprm_check_security =
-               LIST_HEAD_INIT(security_hook_heads.bprm_check_security),
-       .bprm_secureexec =
-               LIST_HEAD_INIT(security_hook_heads.bprm_secureexec),
-       .bprm_committing_creds =
-               LIST_HEAD_INIT(security_hook_heads.bprm_committing_creds),
-       .bprm_committed_creds =
-               LIST_HEAD_INIT(security_hook_heads.bprm_committed_creds),
-       .sb_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.sb_alloc_security),
-       .sb_free_security =
-               LIST_HEAD_INIT(security_hook_heads.sb_free_security),
-       .sb_copy_data = LIST_HEAD_INIT(security_hook_heads.sb_copy_data),
-       .sb_remount =   LIST_HEAD_INIT(security_hook_heads.sb_remount),
-       .sb_kern_mount =
-               LIST_HEAD_INIT(security_hook_heads.sb_kern_mount),
-       .sb_show_options =
-               LIST_HEAD_INIT(security_hook_heads.sb_show_options),
-       .sb_statfs =    LIST_HEAD_INIT(security_hook_heads.sb_statfs),
-       .sb_mount =     LIST_HEAD_INIT(security_hook_heads.sb_mount),
-       .sb_umount =    LIST_HEAD_INIT(security_hook_heads.sb_umount),
-       .sb_pivotroot = LIST_HEAD_INIT(security_hook_heads.sb_pivotroot),
-       .sb_set_mnt_opts =
-               LIST_HEAD_INIT(security_hook_heads.sb_set_mnt_opts),
-       .sb_clone_mnt_opts =
-               LIST_HEAD_INIT(security_hook_heads.sb_clone_mnt_opts),
-       .sb_parse_opts_str =
-               LIST_HEAD_INIT(security_hook_heads.sb_parse_opts_str),
-       .dentry_init_security =
-               LIST_HEAD_INIT(security_hook_heads.dentry_init_security),
-       .dentry_create_files_as =
-               LIST_HEAD_INIT(security_hook_heads.dentry_create_files_as),
- #ifdef CONFIG_SECURITY_PATH
-       .path_unlink =  LIST_HEAD_INIT(security_hook_heads.path_unlink),
-       .path_mkdir =   LIST_HEAD_INIT(security_hook_heads.path_mkdir),
-       .path_rmdir =   LIST_HEAD_INIT(security_hook_heads.path_rmdir),
-       .path_mknod =   LIST_HEAD_INIT(security_hook_heads.path_mknod),
-       .path_truncate =
-               LIST_HEAD_INIT(security_hook_heads.path_truncate),
-       .path_symlink = LIST_HEAD_INIT(security_hook_heads.path_symlink),
-       .path_link =    LIST_HEAD_INIT(security_hook_heads.path_link),
-       .path_rename =  LIST_HEAD_INIT(security_hook_heads.path_rename),
-       .path_chmod =   LIST_HEAD_INIT(security_hook_heads.path_chmod),
-       .path_chown =   LIST_HEAD_INIT(security_hook_heads.path_chown),
-       .path_chroot =  LIST_HEAD_INIT(security_hook_heads.path_chroot),
- #endif
-       .inode_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.inode_alloc_security),
-       .inode_free_security =
-               LIST_HEAD_INIT(security_hook_heads.inode_free_security),
-       .inode_init_security =
-               LIST_HEAD_INIT(security_hook_heads.inode_init_security),
-       .inode_create = LIST_HEAD_INIT(security_hook_heads.inode_create),
-       .inode_link =   LIST_HEAD_INIT(security_hook_heads.inode_link),
-       .inode_unlink = LIST_HEAD_INIT(security_hook_heads.inode_unlink),
-       .inode_symlink =
-               LIST_HEAD_INIT(security_hook_heads.inode_symlink),
-       .inode_mkdir =  LIST_HEAD_INIT(security_hook_heads.inode_mkdir),
-       .inode_rmdir =  LIST_HEAD_INIT(security_hook_heads.inode_rmdir),
-       .inode_mknod =  LIST_HEAD_INIT(security_hook_heads.inode_mknod),
-       .inode_rename = LIST_HEAD_INIT(security_hook_heads.inode_rename),
-       .inode_readlink =
-               LIST_HEAD_INIT(security_hook_heads.inode_readlink),
-       .inode_follow_link =
-               LIST_HEAD_INIT(security_hook_heads.inode_follow_link),
-       .inode_permission =
-               LIST_HEAD_INIT(security_hook_heads.inode_permission),
-       .inode_setattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_setattr),
-       .inode_getattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_getattr),
-       .inode_setxattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_setxattr),
-       .inode_post_setxattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_post_setxattr),
-       .inode_getxattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_getxattr),
-       .inode_listxattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_listxattr),
-       .inode_removexattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_removexattr),
-       .inode_need_killpriv =
-               LIST_HEAD_INIT(security_hook_heads.inode_need_killpriv),
-       .inode_killpriv =
-               LIST_HEAD_INIT(security_hook_heads.inode_killpriv),
-       .inode_getsecurity =
-               LIST_HEAD_INIT(security_hook_heads.inode_getsecurity),
-       .inode_setsecurity =
-               LIST_HEAD_INIT(security_hook_heads.inode_setsecurity),
-       .inode_listsecurity =
-               LIST_HEAD_INIT(security_hook_heads.inode_listsecurity),
-       .inode_getsecid =
-               LIST_HEAD_INIT(security_hook_heads.inode_getsecid),
-       .inode_copy_up =
-               LIST_HEAD_INIT(security_hook_heads.inode_copy_up),
-       .inode_copy_up_xattr =
-               LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr),
-       .file_permission =
-               LIST_HEAD_INIT(security_hook_heads.file_permission),
-       .file_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.file_alloc_security),
-       .file_free_security =
-               LIST_HEAD_INIT(security_hook_heads.file_free_security),
-       .file_ioctl =   LIST_HEAD_INIT(security_hook_heads.file_ioctl),
-       .mmap_addr =    LIST_HEAD_INIT(security_hook_heads.mmap_addr),
-       .mmap_file =    LIST_HEAD_INIT(security_hook_heads.mmap_file),
-       .file_mprotect =
-               LIST_HEAD_INIT(security_hook_heads.file_mprotect),
-       .file_lock =    LIST_HEAD_INIT(security_hook_heads.file_lock),
-       .file_fcntl =   LIST_HEAD_INIT(security_hook_heads.file_fcntl),
-       .file_set_fowner =
-               LIST_HEAD_INIT(security_hook_heads.file_set_fowner),
-       .file_send_sigiotask =
-               LIST_HEAD_INIT(security_hook_heads.file_send_sigiotask),
-       .file_receive = LIST_HEAD_INIT(security_hook_heads.file_receive),
-       .file_open =    LIST_HEAD_INIT(security_hook_heads.file_open),
-       .task_create =  LIST_HEAD_INIT(security_hook_heads.task_create),
-       .task_free =    LIST_HEAD_INIT(security_hook_heads.task_free),
-       .cred_alloc_blank =
-               LIST_HEAD_INIT(security_hook_heads.cred_alloc_blank),
-       .cred_free =    LIST_HEAD_INIT(security_hook_heads.cred_free),
-       .cred_prepare = LIST_HEAD_INIT(security_hook_heads.cred_prepare),
-       .cred_transfer =
-               LIST_HEAD_INIT(security_hook_heads.cred_transfer),
-       .kernel_act_as =
-               LIST_HEAD_INIT(security_hook_heads.kernel_act_as),
-       .kernel_create_files_as =
-               LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as),
-       .kernel_module_request =
-               LIST_HEAD_INIT(security_hook_heads.kernel_module_request),
-       .kernel_read_file =
-               LIST_HEAD_INIT(security_hook_heads.kernel_read_file),
-       .kernel_post_read_file =
-               LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file),
-       .task_fix_setuid =
-               LIST_HEAD_INIT(security_hook_heads.task_fix_setuid),
-       .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid),
-       .task_getpgid = LIST_HEAD_INIT(security_hook_heads.task_getpgid),
-       .task_getsid =  LIST_HEAD_INIT(security_hook_heads.task_getsid),
-       .task_getsecid =
-               LIST_HEAD_INIT(security_hook_heads.task_getsecid),
-       .task_setnice = LIST_HEAD_INIT(security_hook_heads.task_setnice),
-       .task_setioprio =
-               LIST_HEAD_INIT(security_hook_heads.task_setioprio),
-       .task_getioprio =
-               LIST_HEAD_INIT(security_hook_heads.task_getioprio),
-       .task_setrlimit =
-               LIST_HEAD_INIT(security_hook_heads.task_setrlimit),
-       .task_setscheduler =
-               LIST_HEAD_INIT(security_hook_heads.task_setscheduler),
-       .task_getscheduler =
-               LIST_HEAD_INIT(security_hook_heads.task_getscheduler),
-       .task_movememory =
-               LIST_HEAD_INIT(security_hook_heads.task_movememory),
-       .task_kill =    LIST_HEAD_INIT(security_hook_heads.task_kill),
-       .task_prctl =   LIST_HEAD_INIT(security_hook_heads.task_prctl),
-       .task_to_inode =
-               LIST_HEAD_INIT(security_hook_heads.task_to_inode),
-       .ipc_permission =
-               LIST_HEAD_INIT(security_hook_heads.ipc_permission),
-       .ipc_getsecid = LIST_HEAD_INIT(security_hook_heads.ipc_getsecid),
-       .msg_msg_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.msg_msg_alloc_security),
-       .msg_msg_free_security =
-               LIST_HEAD_INIT(security_hook_heads.msg_msg_free_security),
-       .msg_queue_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.msg_queue_alloc_security),
-       .msg_queue_free_security =
-               LIST_HEAD_INIT(security_hook_heads.msg_queue_free_security),
-       .msg_queue_associate =
-               LIST_HEAD_INIT(security_hook_heads.msg_queue_associate),
-       .msg_queue_msgctl =
-               LIST_HEAD_INIT(security_hook_heads.msg_queue_msgctl),
-       .msg_queue_msgsnd =
-               LIST_HEAD_INIT(security_hook_heads.msg_queue_msgsnd),
-       .msg_queue_msgrcv =
-               LIST_HEAD_INIT(security_hook_heads.msg_queue_msgrcv),
-       .shm_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.shm_alloc_security),
-       .shm_free_security =
-               LIST_HEAD_INIT(security_hook_heads.shm_free_security),
-       .shm_associate =
-               LIST_HEAD_INIT(security_hook_heads.shm_associate),
-       .shm_shmctl =   LIST_HEAD_INIT(security_hook_heads.shm_shmctl),
-       .shm_shmat =    LIST_HEAD_INIT(security_hook_heads.shm_shmat),
-       .sem_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.sem_alloc_security),
-       .sem_free_security =
-               LIST_HEAD_INIT(security_hook_heads.sem_free_security),
-       .sem_associate =
-               LIST_HEAD_INIT(security_hook_heads.sem_associate),
-       .sem_semctl =   LIST_HEAD_INIT(security_hook_heads.sem_semctl),
-       .sem_semop =    LIST_HEAD_INIT(security_hook_heads.sem_semop),
-       .netlink_send = LIST_HEAD_INIT(security_hook_heads.netlink_send),
-       .d_instantiate =
-               LIST_HEAD_INIT(security_hook_heads.d_instantiate),
-       .getprocattr =  LIST_HEAD_INIT(security_hook_heads.getprocattr),
-       .setprocattr =  LIST_HEAD_INIT(security_hook_heads.setprocattr),
-       .ismaclabel =   LIST_HEAD_INIT(security_hook_heads.ismaclabel),
-       .secid_to_secctx =
-               LIST_HEAD_INIT(security_hook_heads.secid_to_secctx),
-       .secctx_to_secid =
-               LIST_HEAD_INIT(security_hook_heads.secctx_to_secid),
-       .release_secctx =
-               LIST_HEAD_INIT(security_hook_heads.release_secctx),
-       .inode_invalidate_secctx =
-               LIST_HEAD_INIT(security_hook_heads.inode_invalidate_secctx),
-       .inode_notifysecctx =
-               LIST_HEAD_INIT(security_hook_heads.inode_notifysecctx),
-       .inode_setsecctx =
-               LIST_HEAD_INIT(security_hook_heads.inode_setsecctx),
-       .inode_getsecctx =
-               LIST_HEAD_INIT(security_hook_heads.inode_getsecctx),
- #ifdef CONFIG_SECURITY_NETWORK
-       .unix_stream_connect =
-               LIST_HEAD_INIT(security_hook_heads.unix_stream_connect),
-       .unix_may_send =
-               LIST_HEAD_INIT(security_hook_heads.unix_may_send),
-       .socket_create =
-               LIST_HEAD_INIT(security_hook_heads.socket_create),
-       .socket_post_create =
-               LIST_HEAD_INIT(security_hook_heads.socket_post_create),
-       .socket_bind =  LIST_HEAD_INIT(security_hook_heads.socket_bind),
-       .socket_connect =
-               LIST_HEAD_INIT(security_hook_heads.socket_connect),
-       .socket_listen =
-               LIST_HEAD_INIT(security_hook_heads.socket_listen),
-       .socket_accept =
-               LIST_HEAD_INIT(security_hook_heads.socket_accept),
-       .socket_sendmsg =
-               LIST_HEAD_INIT(security_hook_heads.socket_sendmsg),
-       .socket_recvmsg =
-               LIST_HEAD_INIT(security_hook_heads.socket_recvmsg),
-       .socket_getsockname =
-               LIST_HEAD_INIT(security_hook_heads.socket_getsockname),
-       .socket_getpeername =
-               LIST_HEAD_INIT(security_hook_heads.socket_getpeername),
-       .socket_getsockopt =
-               LIST_HEAD_INIT(security_hook_heads.socket_getsockopt),
-       .socket_setsockopt =
-               LIST_HEAD_INIT(security_hook_heads.socket_setsockopt),
-       .socket_shutdown =
-               LIST_HEAD_INIT(security_hook_heads.socket_shutdown),
-       .socket_sock_rcv_skb =
-               LIST_HEAD_INIT(security_hook_heads.socket_sock_rcv_skb),
-       .socket_getpeersec_stream =
-               LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_stream),
-       .socket_getpeersec_dgram =
-               LIST_HEAD_INIT(security_hook_heads.socket_getpeersec_dgram),
-       .sk_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.sk_alloc_security),
-       .sk_free_security =
-               LIST_HEAD_INIT(security_hook_heads.sk_free_security),
-       .sk_clone_security =
-               LIST_HEAD_INIT(security_hook_heads.sk_clone_security),
-       .sk_getsecid =  LIST_HEAD_INIT(security_hook_heads.sk_getsecid),
-       .sock_graft =   LIST_HEAD_INIT(security_hook_heads.sock_graft),
-       .inet_conn_request =
-               LIST_HEAD_INIT(security_hook_heads.inet_conn_request),
-       .inet_csk_clone =
-               LIST_HEAD_INIT(security_hook_heads.inet_csk_clone),
-       .inet_conn_established =
-               LIST_HEAD_INIT(security_hook_heads.inet_conn_established),
-       .secmark_relabel_packet =
-               LIST_HEAD_INIT(security_hook_heads.secmark_relabel_packet),
-       .secmark_refcount_inc =
-               LIST_HEAD_INIT(security_hook_heads.secmark_refcount_inc),
-       .secmark_refcount_dec =
-               LIST_HEAD_INIT(security_hook_heads.secmark_refcount_dec),
-       .req_classify_flow =
-               LIST_HEAD_INIT(security_hook_heads.req_classify_flow),
-       .tun_dev_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.tun_dev_alloc_security),
-       .tun_dev_free_security =
-               LIST_HEAD_INIT(security_hook_heads.tun_dev_free_security),
-       .tun_dev_create =
-               LIST_HEAD_INIT(security_hook_heads.tun_dev_create),
-       .tun_dev_attach_queue =
-               LIST_HEAD_INIT(security_hook_heads.tun_dev_attach_queue),
-       .tun_dev_attach =
-               LIST_HEAD_INIT(security_hook_heads.tun_dev_attach),
-       .tun_dev_open = LIST_HEAD_INIT(security_hook_heads.tun_dev_open),
- #endif        /* CONFIG_SECURITY_NETWORK */
- #ifdef CONFIG_SECURITY_NETWORK_XFRM
-       .xfrm_policy_alloc_security =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_alloc_security),
-       .xfrm_policy_clone_security =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_clone_security),
-       .xfrm_policy_free_security =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_free_security),
-       .xfrm_policy_delete_security =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_delete_security),
-       .xfrm_state_alloc =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc),
-       .xfrm_state_alloc_acquire =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_state_alloc_acquire),
-       .xfrm_state_free_security =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_state_free_security),
-       .xfrm_state_delete_security =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_state_delete_security),
-       .xfrm_policy_lookup =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_policy_lookup),
-       .xfrm_state_pol_flow_match =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_state_pol_flow_match),
-       .xfrm_decode_session =
-               LIST_HEAD_INIT(security_hook_heads.xfrm_decode_session),
- #endif        /* CONFIG_SECURITY_NETWORK_XFRM */
- #ifdef CONFIG_KEYS
-       .key_alloc =    LIST_HEAD_INIT(security_hook_heads.key_alloc),
-       .key_free =     LIST_HEAD_INIT(security_hook_heads.key_free),
-       .key_permission =
-               LIST_HEAD_INIT(security_hook_heads.key_permission),
-       .key_getsecurity =
-               LIST_HEAD_INIT(security_hook_heads.key_getsecurity),
- #endif        /* CONFIG_KEYS */
- #ifdef CONFIG_AUDIT
-       .audit_rule_init =
-               LIST_HEAD_INIT(security_hook_heads.audit_rule_init),
-       .audit_rule_known =
-               LIST_HEAD_INIT(security_hook_heads.audit_rule_known),
-       .audit_rule_match =
-               LIST_HEAD_INIT(security_hook_heads.audit_rule_match),
-       .audit_rule_free =
-               LIST_HEAD_INIT(security_hook_heads.audit_rule_free),
- #endif /* CONFIG_AUDIT */
- };
index 8e67bb4c9caba658b18f9d1dd0593907c8556c27,57e2596bdd8a0995be838dde0e2bcedb4acba67b..5aeaf30b7a1315a617f5c2d673043e959969fe14
@@@ -28,7 -28,7 +28,7 @@@ struct nlmsg_perm 
        u32     perm;
  };
  
- static struct nlmsg_perm nlmsg_route_perms[] =
+ static const struct nlmsg_perm nlmsg_route_perms[] =
  {
        { RTM_NEWLINK,          NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
        { RTM_DELLINK,          NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
@@@ -69,7 -69,6 +69,7 @@@
        { RTM_GETDCB,           NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_SETDCB,           NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
        { RTM_NEWNETCONF,       NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 +      { RTM_DELNETCONF,       NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
        { RTM_GETNETCONF,       NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_NEWMDB,           NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
        { RTM_DELMDB,           NETLINK_ROUTE_SOCKET__NLMSG_WRITE  },
@@@ -81,7 -80,7 +81,7 @@@
        { RTM_GETSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ  },
  };
  
- static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
+ static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
  {
        { TCPDIAG_GETSOCK,      NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
        { DCCPDIAG_GETSOCK,     NETLINK_TCPDIAG_SOCKET__NLMSG_READ },
@@@ -89,7 -88,7 +89,7 @@@
        { SOCK_DESTROY,         NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE },
  };
  
- static struct nlmsg_perm nlmsg_xfrm_perms[] =
+ static const struct nlmsg_perm nlmsg_xfrm_perms[] =
  {
        { XFRM_MSG_NEWSA,       NETLINK_XFRM_SOCKET__NLMSG_WRITE },
        { XFRM_MSG_DELSA,       NETLINK_XFRM_SOCKET__NLMSG_WRITE },
        { XFRM_MSG_MAPPING,     NETLINK_XFRM_SOCKET__NLMSG_READ  },
  };
  
- static struct nlmsg_perm nlmsg_audit_perms[] =
+ static const struct nlmsg_perm nlmsg_audit_perms[] =
  {
        { AUDIT_GET,            NETLINK_AUDIT_SOCKET__NLMSG_READ     },
        { AUDIT_SET,            NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
  };
  
  
- static int nlmsg_perm(u16 nlmsg_type, u32 *perm, struct nlmsg_perm *tab, size_t tabsize)
+ static int nlmsg_perm(u16 nlmsg_type, u32 *perm, const struct nlmsg_perm *tab, size_t tabsize)
  {
        int i, err = -EINVAL;