Merge branch 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Apr 2018 18:11:41 +0000 (11:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Apr 2018 18:11:41 +0000 (11:11 -0700)
Pull general security layer updates from James Morris:

 - Convert security hooks from list to hlist, a nice cleanup, saving
   about 50% of space, from Sargun Dhillon.

 - Only pass the cred, not the secid, to kill_pid_info_as_cred and
   security_task_kill (as the secid can be determined from the cred),
   from Stephen Smalley.

 - Close a potential race in kernel_read_file(), by making the file
   unwritable before calling the LSM check (vs after), from Kees Cook.

* 'next-general' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  security: convert security hooks to use hlist
  exec: Set file unwritable before LSM check
  usb, signal, security: only pass the cred, not the secid, to kill_pid_info_as_cred and security_task_kill

1  2 
include/linux/lsm_hooks.h
include/linux/security.h
kernel/signal.c
security/apparmor/lsm.c
security/security.c
security/selinux/hooks.c
security/smack/smack_lsm.c

   *    @p contains the task_struct for process.
   *    @info contains the signal information.
   *    @sig contains the signal value.
-  *    @secid contains the sid of the process where the signal originated
+  *    @cred contains the cred of the process where the signal originated, or
+  *    NULL if the current task is the originator.
   *    Return 0 if permission is granted.
   * @task_prctl:
   *    Check permission before performing a process control operation on the
   *    associated with the TUN device's security structure.
   *    @security pointer to the TUN devices's security structure.
   *
 + * Security hooks for SCTP
 + *
 + * @sctp_assoc_request:
 + *    Passes the @ep and @chunk->skb of the association INIT packet to
 + *    the security module.
 + *    @ep pointer to sctp endpoint structure.
 + *    @skb pointer to skbuff of association packet.
 + *    Return 0 on success, error on failure.
 + * @sctp_bind_connect:
 + *    Validiate permissions required for each address associated with sock
 + *    @sk. Depending on @optname, the addresses will be treated as either
 + *    for a connect or bind service. The @addrlen is calculated on each
 + *    ipv4 and ipv6 address using sizeof(struct sockaddr_in) or
 + *    sizeof(struct sockaddr_in6).
 + *    @sk pointer to sock structure.
 + *    @optname name of the option to validate.
 + *    @address list containing one or more ipv4/ipv6 addresses.
 + *    @addrlen total length of address(s).
 + *    Return 0 on success, error on failure.
 + * @sctp_sk_clone:
 + *    Called whenever a new socket is created by accept(2) (i.e. a TCP
 + *    style socket) or when a socket is 'peeled off' e.g userspace
 + *    calls sctp_peeloff(3).
 + *    @ep pointer to current sctp endpoint structure.
 + *    @sk pointer to current sock structure.
 + *    @sk pointer to new sock structure.
 + *
   * Security hooks for Infiniband
   *
   * @ib_pkey_access:
@@@ -1591,7 -1565,7 +1592,7 @@@ union security_list_options 
        int (*task_getscheduler)(struct task_struct *p);
        int (*task_movememory)(struct task_struct *p);
        int (*task_kill)(struct task_struct *p, struct siginfo *info,
-                               int sig, u32 secid);
+                               int sig, const struct cred *cred);
        int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3,
                                unsigned long arg4, unsigned long arg5);
        void (*task_to_inode)(struct task_struct *p, struct inode *inode);
        int (*msg_msg_alloc_security)(struct msg_msg *msg);
        void (*msg_msg_free_security)(struct msg_msg *msg);
  
 -      int (*msg_queue_alloc_security)(struct msg_queue *msq);
 -      void (*msg_queue_free_security)(struct msg_queue *msq);
 -      int (*msg_queue_associate)(struct msg_queue *msq, int msqflg);
 -      int (*msg_queue_msgctl)(struct msg_queue *msq, int cmd);
 -      int (*msg_queue_msgsnd)(struct msg_queue *msq, struct msg_msg *msg,
 +      int (*msg_queue_alloc_security)(struct kern_ipc_perm *msq);
 +      void (*msg_queue_free_security)(struct kern_ipc_perm *msq);
 +      int (*msg_queue_associate)(struct kern_ipc_perm *msq, int msqflg);
 +      int (*msg_queue_msgctl)(struct kern_ipc_perm *msq, int cmd);
 +      int (*msg_queue_msgsnd)(struct kern_ipc_perm *msq, struct msg_msg *msg,
                                int msqflg);
 -      int (*msg_queue_msgrcv)(struct msg_queue *msq, struct msg_msg *msg,
 +      int (*msg_queue_msgrcv)(struct kern_ipc_perm *msq, struct msg_msg *msg,
                                struct task_struct *target, long type,
                                int mode);
  
 -      int (*shm_alloc_security)(struct shmid_kernel *shp);
 -      void (*shm_free_security)(struct shmid_kernel *shp);
 -      int (*shm_associate)(struct shmid_kernel *shp, int shmflg);
 -      int (*shm_shmctl)(struct shmid_kernel *shp, int cmd);
 -      int (*shm_shmat)(struct shmid_kernel *shp, char __user *shmaddr,
 +      int (*shm_alloc_security)(struct kern_ipc_perm *shp);
 +      void (*shm_free_security)(struct kern_ipc_perm *shp);
 +      int (*shm_associate)(struct kern_ipc_perm *shp, int shmflg);
 +      int (*shm_shmctl)(struct kern_ipc_perm *shp, int cmd);
 +      int (*shm_shmat)(struct kern_ipc_perm *shp, char __user *shmaddr,
                                int shmflg);
  
 -      int (*sem_alloc_security)(struct sem_array *sma);
 -      void (*sem_free_security)(struct sem_array *sma);
 -      int (*sem_associate)(struct sem_array *sma, int semflg);
 -      int (*sem_semctl)(struct sem_array *sma, int cmd);
 -      int (*sem_semop)(struct sem_array *sma, struct sembuf *sops,
 +      int (*sem_alloc_security)(struct kern_ipc_perm *sma);
 +      void (*sem_free_security)(struct kern_ipc_perm *sma);
 +      int (*sem_associate)(struct kern_ipc_perm *sma, int semflg);
 +      int (*sem_semctl)(struct kern_ipc_perm *sma, int cmd);
 +      int (*sem_semop)(struct kern_ipc_perm *sma, struct sembuf *sops,
                                unsigned nsops, int alter);
  
        int (*netlink_send)(struct sock *sk, struct sk_buff *skb);
        int (*tun_dev_attach_queue)(void *security);
        int (*tun_dev_attach)(struct sock *sk, void *security);
        int (*tun_dev_open)(void *security);
 +      int (*sctp_assoc_request)(struct sctp_endpoint *ep,
 +                                struct sk_buff *skb);
 +      int (*sctp_bind_connect)(struct sock *sk, int optname,
 +                               struct sockaddr *address, int addrlen);
 +      void (*sctp_sk_clone)(struct sctp_endpoint *ep, struct sock *sk,
 +                            struct sock *newsk);
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_INFINIBAND
  };
  
  struct security_hook_heads {
-       struct list_head binder_set_context_mgr;
-       struct list_head binder_transaction;
-       struct list_head binder_transfer_binder;
-       struct list_head binder_transfer_file;
-       struct list_head ptrace_access_check;
-       struct list_head ptrace_traceme;
-       struct list_head capget;
-       struct list_head capset;
-       struct list_head capable;
-       struct list_head quotactl;
-       struct list_head quota_on;
-       struct list_head syslog;
-       struct list_head settime;
-       struct list_head vm_enough_memory;
-       struct list_head bprm_set_creds;
-       struct list_head bprm_check_security;
-       struct list_head bprm_committing_creds;
-       struct list_head bprm_committed_creds;
-       struct list_head sb_alloc_security;
-       struct list_head sb_free_security;
-       struct list_head sb_copy_data;
-       struct list_head sb_remount;
-       struct list_head sb_kern_mount;
-       struct list_head sb_show_options;
-       struct list_head sb_statfs;
-       struct list_head sb_mount;
-       struct list_head sb_umount;
-       struct list_head sb_pivotroot;
-       struct list_head sb_set_mnt_opts;
-       struct list_head sb_clone_mnt_opts;
-       struct list_head sb_parse_opts_str;
-       struct list_head dentry_init_security;
-       struct list_head dentry_create_files_as;
+       struct hlist_head binder_set_context_mgr;
+       struct hlist_head binder_transaction;
+       struct hlist_head binder_transfer_binder;
+       struct hlist_head binder_transfer_file;
+       struct hlist_head ptrace_access_check;
+       struct hlist_head ptrace_traceme;
+       struct hlist_head capget;
+       struct hlist_head capset;
+       struct hlist_head capable;
+       struct hlist_head quotactl;
+       struct hlist_head quota_on;
+       struct hlist_head syslog;
+       struct hlist_head settime;
+       struct hlist_head vm_enough_memory;
+       struct hlist_head bprm_set_creds;
+       struct hlist_head bprm_check_security;
+       struct hlist_head bprm_committing_creds;
+       struct hlist_head bprm_committed_creds;
+       struct hlist_head sb_alloc_security;
+       struct hlist_head sb_free_security;
+       struct hlist_head sb_copy_data;
+       struct hlist_head sb_remount;
+       struct hlist_head sb_kern_mount;
+       struct hlist_head sb_show_options;
+       struct hlist_head sb_statfs;
+       struct hlist_head sb_mount;
+       struct hlist_head sb_umount;
+       struct hlist_head sb_pivotroot;
+       struct hlist_head sb_set_mnt_opts;
+       struct hlist_head sb_clone_mnt_opts;
+       struct hlist_head sb_parse_opts_str;
+       struct hlist_head dentry_init_security;
+       struct hlist_head dentry_create_files_as;
  #ifdef CONFIG_SECURITY_PATH
-       struct list_head path_unlink;
-       struct list_head path_mkdir;
-       struct list_head path_rmdir;
-       struct list_head path_mknod;
-       struct list_head path_truncate;
-       struct list_head path_symlink;
-       struct list_head path_link;
-       struct list_head path_rename;
-       struct list_head path_chmod;
-       struct list_head path_chown;
-       struct list_head path_chroot;
+       struct hlist_head path_unlink;
+       struct hlist_head path_mkdir;
+       struct hlist_head path_rmdir;
+       struct hlist_head path_mknod;
+       struct hlist_head path_truncate;
+       struct hlist_head path_symlink;
+       struct hlist_head path_link;
+       struct hlist_head path_rename;
+       struct hlist_head path_chmod;
+       struct hlist_head path_chown;
+       struct hlist_head path_chroot;
  #endif
-       struct list_head inode_alloc_security;
-       struct list_head inode_free_security;
-       struct list_head inode_init_security;
-       struct list_head inode_create;
-       struct list_head inode_link;
-       struct list_head inode_unlink;
-       struct list_head inode_symlink;
-       struct list_head inode_mkdir;
-       struct list_head inode_rmdir;
-       struct list_head inode_mknod;
-       struct list_head inode_rename;
-       struct list_head inode_readlink;
-       struct list_head inode_follow_link;
-       struct list_head inode_permission;
-       struct list_head inode_setattr;
-       struct list_head inode_getattr;
-       struct list_head inode_setxattr;
-       struct list_head inode_post_setxattr;
-       struct list_head inode_getxattr;
-       struct list_head inode_listxattr;
-       struct list_head inode_removexattr;
-       struct list_head inode_need_killpriv;
-       struct list_head inode_killpriv;
-       struct list_head inode_getsecurity;
-       struct list_head inode_setsecurity;
-       struct list_head inode_listsecurity;
-       struct list_head inode_getsecid;
-       struct list_head inode_copy_up;
-       struct list_head inode_copy_up_xattr;
-       struct list_head file_permission;
-       struct list_head file_alloc_security;
-       struct list_head file_free_security;
-       struct list_head file_ioctl;
-       struct list_head mmap_addr;
-       struct list_head mmap_file;
-       struct list_head file_mprotect;
-       struct list_head file_lock;
-       struct list_head file_fcntl;
-       struct list_head file_set_fowner;
-       struct list_head file_send_sigiotask;
-       struct list_head file_receive;
-       struct list_head file_open;
-       struct list_head task_alloc;
-       struct list_head task_free;
-       struct list_head cred_alloc_blank;
-       struct list_head cred_free;
-       struct list_head cred_prepare;
-       struct list_head cred_transfer;
-       struct list_head kernel_act_as;
-       struct list_head kernel_create_files_as;
-       struct list_head kernel_read_file;
-       struct list_head kernel_post_read_file;
-       struct list_head kernel_module_request;
-       struct list_head task_fix_setuid;
-       struct list_head task_setpgid;
-       struct list_head task_getpgid;
-       struct list_head task_getsid;
-       struct list_head task_getsecid;
-       struct list_head task_setnice;
-       struct list_head task_setioprio;
-       struct list_head task_getioprio;
-       struct list_head task_prlimit;
-       struct list_head task_setrlimit;
-       struct list_head task_setscheduler;
-       struct list_head task_getscheduler;
-       struct list_head task_movememory;
-       struct list_head task_kill;
-       struct list_head task_prctl;
-       struct list_head task_to_inode;
-       struct list_head ipc_permission;
-       struct list_head ipc_getsecid;
-       struct list_head msg_msg_alloc_security;
-       struct list_head msg_msg_free_security;
-       struct list_head msg_queue_alloc_security;
-       struct list_head msg_queue_free_security;
-       struct list_head msg_queue_associate;
-       struct list_head msg_queue_msgctl;
-       struct list_head msg_queue_msgsnd;
-       struct list_head msg_queue_msgrcv;
-       struct list_head shm_alloc_security;
-       struct list_head shm_free_security;
-       struct list_head shm_associate;
-       struct list_head shm_shmctl;
-       struct list_head shm_shmat;
-       struct list_head sem_alloc_security;
-       struct list_head sem_free_security;
-       struct list_head sem_associate;
-       struct list_head sem_semctl;
-       struct list_head sem_semop;
-       struct list_head netlink_send;
-       struct list_head d_instantiate;
-       struct list_head getprocattr;
-       struct list_head setprocattr;
-       struct list_head ismaclabel;
-       struct list_head secid_to_secctx;
-       struct list_head secctx_to_secid;
-       struct list_head release_secctx;
-       struct list_head inode_invalidate_secctx;
-       struct list_head inode_notifysecctx;
-       struct list_head inode_setsecctx;
-       struct list_head inode_getsecctx;
+       struct hlist_head inode_alloc_security;
+       struct hlist_head inode_free_security;
+       struct hlist_head inode_init_security;
+       struct hlist_head inode_create;
+       struct hlist_head inode_link;
+       struct hlist_head inode_unlink;
+       struct hlist_head inode_symlink;
+       struct hlist_head inode_mkdir;
+       struct hlist_head inode_rmdir;
+       struct hlist_head inode_mknod;
+       struct hlist_head inode_rename;
+       struct hlist_head inode_readlink;
+       struct hlist_head inode_follow_link;
+       struct hlist_head inode_permission;
+       struct hlist_head inode_setattr;
+       struct hlist_head inode_getattr;
+       struct hlist_head inode_setxattr;
+       struct hlist_head inode_post_setxattr;
+       struct hlist_head inode_getxattr;
+       struct hlist_head inode_listxattr;
+       struct hlist_head inode_removexattr;
+       struct hlist_head inode_need_killpriv;
+       struct hlist_head inode_killpriv;
+       struct hlist_head inode_getsecurity;
+       struct hlist_head inode_setsecurity;
+       struct hlist_head inode_listsecurity;
+       struct hlist_head inode_getsecid;
+       struct hlist_head inode_copy_up;
+       struct hlist_head inode_copy_up_xattr;
+       struct hlist_head file_permission;
+       struct hlist_head file_alloc_security;
+       struct hlist_head file_free_security;
+       struct hlist_head file_ioctl;
+       struct hlist_head mmap_addr;
+       struct hlist_head mmap_file;
+       struct hlist_head file_mprotect;
+       struct hlist_head file_lock;
+       struct hlist_head file_fcntl;
+       struct hlist_head file_set_fowner;
+       struct hlist_head file_send_sigiotask;
+       struct hlist_head file_receive;
+       struct hlist_head file_open;
+       struct hlist_head task_alloc;
+       struct hlist_head task_free;
+       struct hlist_head cred_alloc_blank;
+       struct hlist_head cred_free;
+       struct hlist_head cred_prepare;
+       struct hlist_head cred_transfer;
+       struct hlist_head kernel_act_as;
+       struct hlist_head kernel_create_files_as;
+       struct hlist_head kernel_read_file;
+       struct hlist_head kernel_post_read_file;
+       struct hlist_head kernel_module_request;
+       struct hlist_head task_fix_setuid;
+       struct hlist_head task_setpgid;
+       struct hlist_head task_getpgid;
+       struct hlist_head task_getsid;
+       struct hlist_head task_getsecid;
+       struct hlist_head task_setnice;
+       struct hlist_head task_setioprio;
+       struct hlist_head task_getioprio;
+       struct hlist_head task_prlimit;
+       struct hlist_head task_setrlimit;
+       struct hlist_head task_setscheduler;
+       struct hlist_head task_getscheduler;
+       struct hlist_head task_movememory;
+       struct hlist_head task_kill;
+       struct hlist_head task_prctl;
+       struct hlist_head task_to_inode;
+       struct hlist_head ipc_permission;
+       struct hlist_head ipc_getsecid;
+       struct hlist_head msg_msg_alloc_security;
+       struct hlist_head msg_msg_free_security;
+       struct hlist_head msg_queue_alloc_security;
+       struct hlist_head msg_queue_free_security;
+       struct hlist_head msg_queue_associate;
+       struct hlist_head msg_queue_msgctl;
+       struct hlist_head msg_queue_msgsnd;
+       struct hlist_head msg_queue_msgrcv;
+       struct hlist_head shm_alloc_security;
+       struct hlist_head shm_free_security;
+       struct hlist_head shm_associate;
+       struct hlist_head shm_shmctl;
+       struct hlist_head shm_shmat;
+       struct hlist_head sem_alloc_security;
+       struct hlist_head sem_free_security;
+       struct hlist_head sem_associate;
+       struct hlist_head sem_semctl;
+       struct hlist_head sem_semop;
+       struct hlist_head netlink_send;
+       struct hlist_head d_instantiate;
+       struct hlist_head getprocattr;
+       struct hlist_head setprocattr;
+       struct hlist_head ismaclabel;
+       struct hlist_head secid_to_secctx;
+       struct hlist_head secctx_to_secid;
+       struct hlist_head release_secctx;
+       struct hlist_head inode_invalidate_secctx;
+       struct hlist_head inode_notifysecctx;
+       struct hlist_head inode_setsecctx;
+       struct hlist_head inode_getsecctx;
  #ifdef CONFIG_SECURITY_NETWORK
-       struct list_head unix_stream_connect;
-       struct list_head unix_may_send;
-       struct list_head socket_create;
-       struct list_head socket_post_create;
-       struct list_head socket_bind;
-       struct list_head socket_connect;
-       struct list_head socket_listen;
-       struct list_head socket_accept;
-       struct list_head socket_sendmsg;
-       struct list_head socket_recvmsg;
-       struct list_head socket_getsockname;
-       struct list_head socket_getpeername;
-       struct list_head socket_getsockopt;
-       struct list_head socket_setsockopt;
-       struct list_head socket_shutdown;
-       struct list_head socket_sock_rcv_skb;
-       struct list_head socket_getpeersec_stream;
-       struct list_head socket_getpeersec_dgram;
-       struct list_head sk_alloc_security;
-       struct list_head sk_free_security;
-       struct list_head sk_clone_security;
-       struct list_head sk_getsecid;
-       struct list_head sock_graft;
-       struct list_head inet_conn_request;
-       struct list_head inet_csk_clone;
-       struct list_head inet_conn_established;
-       struct list_head secmark_relabel_packet;
-       struct list_head secmark_refcount_inc;
-       struct list_head secmark_refcount_dec;
-       struct list_head req_classify_flow;
-       struct list_head tun_dev_alloc_security;
-       struct list_head tun_dev_free_security;
-       struct list_head tun_dev_create;
-       struct list_head tun_dev_attach_queue;
-       struct list_head tun_dev_attach;
-       struct list_head tun_dev_open;
-       struct list_head sctp_assoc_request;
-       struct list_head sctp_bind_connect;
-       struct list_head sctp_sk_clone;
+       struct hlist_head unix_stream_connect;
+       struct hlist_head unix_may_send;
+       struct hlist_head socket_create;
+       struct hlist_head socket_post_create;
+       struct hlist_head socket_bind;
+       struct hlist_head socket_connect;
+       struct hlist_head socket_listen;
+       struct hlist_head socket_accept;
+       struct hlist_head socket_sendmsg;
+       struct hlist_head socket_recvmsg;
+       struct hlist_head socket_getsockname;
+       struct hlist_head socket_getpeername;
+       struct hlist_head socket_getsockopt;
+       struct hlist_head socket_setsockopt;
+       struct hlist_head socket_shutdown;
+       struct hlist_head socket_sock_rcv_skb;
+       struct hlist_head socket_getpeersec_stream;
+       struct hlist_head socket_getpeersec_dgram;
+       struct hlist_head sk_alloc_security;
+       struct hlist_head sk_free_security;
+       struct hlist_head sk_clone_security;
+       struct hlist_head sk_getsecid;
+       struct hlist_head sock_graft;
+       struct hlist_head inet_conn_request;
+       struct hlist_head inet_csk_clone;
+       struct hlist_head inet_conn_established;
+       struct hlist_head secmark_relabel_packet;
+       struct hlist_head secmark_refcount_inc;
+       struct hlist_head secmark_refcount_dec;
+       struct hlist_head req_classify_flow;
+       struct hlist_head tun_dev_alloc_security;
+       struct hlist_head tun_dev_free_security;
+       struct hlist_head tun_dev_create;
+       struct hlist_head tun_dev_attach_queue;
+       struct hlist_head tun_dev_attach;
+       struct hlist_head tun_dev_open;
++      struct hlist_head sctp_assoc_request;
++      struct hlist_head sctp_bind_connect;
++      struct hlist_head sctp_sk_clone;
  #endif        /* CONFIG_SECURITY_NETWORK */
  #ifdef CONFIG_SECURITY_INFINIBAND
-       struct list_head ib_pkey_access;
-       struct list_head ib_endport_manage_subnet;
-       struct list_head ib_alloc_security;
-       struct list_head ib_free_security;
+       struct hlist_head ib_pkey_access;
+       struct hlist_head ib_endport_manage_subnet;
+       struct hlist_head ib_alloc_security;
+       struct hlist_head ib_free_security;
  #endif        /* CONFIG_SECURITY_INFINIBAND */
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
-       struct list_head xfrm_policy_alloc_security;
-       struct list_head xfrm_policy_clone_security;
-       struct list_head xfrm_policy_free_security;
-       struct list_head xfrm_policy_delete_security;
-       struct list_head xfrm_state_alloc;
-       struct list_head xfrm_state_alloc_acquire;
-       struct list_head xfrm_state_free_security;
-       struct list_head xfrm_state_delete_security;
-       struct list_head xfrm_policy_lookup;
-       struct list_head xfrm_state_pol_flow_match;
-       struct list_head xfrm_decode_session;
+       struct hlist_head xfrm_policy_alloc_security;
+       struct hlist_head xfrm_policy_clone_security;
+       struct hlist_head xfrm_policy_free_security;
+       struct hlist_head xfrm_policy_delete_security;
+       struct hlist_head xfrm_state_alloc;
+       struct hlist_head xfrm_state_alloc_acquire;
+       struct hlist_head xfrm_state_free_security;
+       struct hlist_head xfrm_state_delete_security;
+       struct hlist_head xfrm_policy_lookup;
+       struct hlist_head xfrm_state_pol_flow_match;
+       struct hlist_head xfrm_decode_session;
  #endif        /* CONFIG_SECURITY_NETWORK_XFRM */
  #ifdef CONFIG_KEYS
-       struct list_head key_alloc;
-       struct list_head key_free;
-       struct list_head key_permission;
-       struct list_head key_getsecurity;
+       struct hlist_head key_alloc;
+       struct hlist_head key_free;
+       struct hlist_head key_permission;
+       struct hlist_head key_getsecurity;
  #endif        /* CONFIG_KEYS */
  #ifdef CONFIG_AUDIT
-       struct list_head audit_rule_init;
-       struct list_head audit_rule_known;
-       struct list_head audit_rule_match;
-       struct list_head audit_rule_free;
+       struct hlist_head audit_rule_init;
+       struct hlist_head audit_rule_known;
+       struct hlist_head audit_rule_match;
+       struct hlist_head audit_rule_free;
  #endif /* CONFIG_AUDIT */
  #ifdef CONFIG_BPF_SYSCALL
-       struct list_head bpf;
-       struct list_head bpf_map;
-       struct list_head bpf_prog;
-       struct list_head bpf_map_alloc_security;
-       struct list_head bpf_map_free_security;
-       struct list_head bpf_prog_alloc_security;
-       struct list_head bpf_prog_free_security;
+       struct hlist_head bpf;
+       struct hlist_head bpf_map;
+       struct hlist_head bpf_prog;
+       struct hlist_head bpf_map_alloc_security;
+       struct hlist_head bpf_map_free_security;
+       struct hlist_head bpf_prog_alloc_security;
+       struct hlist_head bpf_prog_free_security;
  #endif /* CONFIG_BPF_SYSCALL */
  } __randomize_layout;
  
   * For use with generic list macros for common operations.
   */
  struct security_hook_list {
-       struct list_head                list;
-       struct list_head                *head;
+       struct hlist_node               list;
+       struct hlist_head               *head;
        union security_list_options     hook;
        char                            *lsm;
  } __randomize_layout;
@@@ -2038,7 -2003,7 +2039,7 @@@ static inline void security_delete_hook
        int i;
  
        for (i = 0; i < count; i++)
-               list_del_rcu(&hooks[i].list);
+               hlist_del_rcu(&hooks[i].list);
  }
  #endif /* CONFIG_SECURITY_SELINUX_DISABLE */
  
diff --combined include/linux/security.h
@@@ -36,6 -36,7 +36,6 @@@ struct linux_binprm
  struct cred;
  struct rlimit;
  struct siginfo;
 -struct sem_array;
  struct sembuf;
  struct kern_ipc_perm;
  struct audit_context;
@@@ -49,7 -50,9 +49,7 @@@ struct qstr
  struct iattr;
  struct fown_struct;
  struct file_operations;
 -struct shmid_kernel;
  struct msg_msg;
 -struct msg_queue;
  struct xattr;
  struct xfrm_sec_ctx;
  struct mm_struct;
@@@ -112,7 -115,6 +112,7 @@@ struct xfrm_policy
  struct xfrm_state;
  struct xfrm_user_sec_ctx;
  struct seq_file;
 +struct sctp_endpoint;
  
  #ifdef CONFIG_MMU
  extern unsigned long mmap_min_addr;
@@@ -345,7 -347,7 +345,7 @@@ int security_task_setscheduler(struct t
  int security_task_getscheduler(struct task_struct *p);
  int security_task_movememory(struct task_struct *p);
  int security_task_kill(struct task_struct *p, struct siginfo *info,
-                       int sig, u32 secid);
+                       int sig, const struct cred *cred);
  int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
                        unsigned long arg4, unsigned long arg5);
  void security_task_to_inode(struct task_struct *p, struct inode *inode);
@@@ -353,24 -355,24 +353,24 @@@ int security_ipc_permission(struct kern
  void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
  int security_msg_msg_alloc(struct msg_msg *msg);
  void security_msg_msg_free(struct msg_msg *msg);
 -int security_msg_queue_alloc(struct msg_queue *msq);
 -void security_msg_queue_free(struct msg_queue *msq);
 -int security_msg_queue_associate(struct msg_queue *msq, int msqflg);
 -int security_msg_queue_msgctl(struct msg_queue *msq, int cmd);
 -int security_msg_queue_msgsnd(struct msg_queue *msq,
 +int security_msg_queue_alloc(struct kern_ipc_perm *msq);
 +void security_msg_queue_free(struct kern_ipc_perm *msq);
 +int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg);
 +int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd);
 +int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                              struct msg_msg *msg, int msqflg);
 -int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
 +int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                              struct task_struct *target, long type, int mode);
 -int security_shm_alloc(struct shmid_kernel *shp);
 -void security_shm_free(struct shmid_kernel *shp);
 -int security_shm_associate(struct shmid_kernel *shp, int shmflg);
 -int security_shm_shmctl(struct shmid_kernel *shp, int cmd);
 -int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg);
 -int security_sem_alloc(struct sem_array *sma);
 -void security_sem_free(struct sem_array *sma);
 -int security_sem_associate(struct sem_array *sma, int semflg);
 -int security_sem_semctl(struct sem_array *sma, int cmd);
 -int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
 +int security_shm_alloc(struct kern_ipc_perm *shp);
 +void security_shm_free(struct kern_ipc_perm *shp);
 +int security_shm_associate(struct kern_ipc_perm *shp, int shmflg);
 +int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd);
 +int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg);
 +int security_sem_alloc(struct kern_ipc_perm *sma);
 +void security_sem_free(struct kern_ipc_perm *sma);
 +int security_sem_associate(struct kern_ipc_perm *sma, int semflg);
 +int security_sem_semctl(struct kern_ipc_perm *sma, int cmd);
 +int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
                        unsigned nsops, int alter);
  void security_d_instantiate(struct dentry *dentry, struct inode *inode);
  int security_getprocattr(struct task_struct *p, char *name, char **value);
@@@ -1008,7 -1010,7 +1008,7 @@@ static inline int security_task_movemem
  
  static inline int security_task_kill(struct task_struct *p,
                                     struct siginfo *info, int sig,
-                                    u32 secid)
+                                    const struct cred *cred)
  {
        return 0;
  }
@@@ -1043,32 -1045,32 +1043,32 @@@ static inline int security_msg_msg_allo
  static inline void security_msg_msg_free(struct msg_msg *msg)
  { }
  
 -static inline int security_msg_queue_alloc(struct msg_queue *msq)
 +static inline int security_msg_queue_alloc(struct kern_ipc_perm *msq)
  {
        return 0;
  }
  
 -static inline void security_msg_queue_free(struct msg_queue *msq)
 +static inline void security_msg_queue_free(struct kern_ipc_perm *msq)
  { }
  
 -static inline int security_msg_queue_associate(struct msg_queue *msq,
 +static inline int security_msg_queue_associate(struct kern_ipc_perm *msq,
                                               int msqflg)
  {
        return 0;
  }
  
 -static inline int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
 +static inline int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
  {
        return 0;
  }
  
 -static inline int security_msg_queue_msgsnd(struct msg_queue *msq,
 +static inline int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                                            struct msg_msg *msg, int msqflg)
  {
        return 0;
  }
  
 -static inline int security_msg_queue_msgrcv(struct msg_queue *msq,
 +static inline int security_msg_queue_msgrcv(struct kern_ipc_perm *msq,
                                            struct msg_msg *msg,
                                            struct task_struct *target,
                                            long type, int mode)
        return 0;
  }
  
 -static inline int security_shm_alloc(struct shmid_kernel *shp)
 +static inline int security_shm_alloc(struct kern_ipc_perm *shp)
  {
        return 0;
  }
  
 -static inline void security_shm_free(struct shmid_kernel *shp)
 +static inline void security_shm_free(struct kern_ipc_perm *shp)
  { }
  
 -static inline int security_shm_associate(struct shmid_kernel *shp,
 +static inline int security_shm_associate(struct kern_ipc_perm *shp,
                                         int shmflg)
  {
        return 0;
  }
  
 -static inline int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
 +static inline int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
  {
        return 0;
  }
  
 -static inline int security_shm_shmat(struct shmid_kernel *shp,
 +static inline int security_shm_shmat(struct kern_ipc_perm *shp,
                                     char __user *shmaddr, int shmflg)
  {
        return 0;
  }
  
 -static inline int security_sem_alloc(struct sem_array *sma)
 +static inline int security_sem_alloc(struct kern_ipc_perm *sma)
  {
        return 0;
  }
  
 -static inline void security_sem_free(struct sem_array *sma)
 +static inline void security_sem_free(struct kern_ipc_perm *sma)
  { }
  
 -static inline int security_sem_associate(struct sem_array *sma, int semflg)
 +static inline int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
  {
        return 0;
  }
  
 -static inline int security_sem_semctl(struct sem_array *sma, int cmd)
 +static inline int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
  {
        return 0;
  }
  
 -static inline int security_sem_semop(struct sem_array *sma,
 +static inline int security_sem_semop(struct kern_ipc_perm *sma,
                                     struct sembuf *sops, unsigned nsops,
                                     int alter)
  {
@@@ -1227,11 -1229,6 +1227,11 @@@ int security_tun_dev_create(void)
  int security_tun_dev_attach_queue(void *security);
  int security_tun_dev_attach(struct sock *sk, void *security);
  int security_tun_dev_open(void *security);
 +int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb);
 +int security_sctp_bind_connect(struct sock *sk, int optname,
 +                             struct sockaddr *address, int addrlen);
 +void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
 +                          struct sock *newsk);
  
  #else /* CONFIG_SECURITY_NETWORK */
  static inline int security_unix_stream_connect(struct sock *sock,
@@@ -1424,25 -1421,6 +1424,25 @@@ static inline int security_tun_dev_open
  {
        return 0;
  }
 +
 +static inline int security_sctp_assoc_request(struct sctp_endpoint *ep,
 +                                            struct sk_buff *skb)
 +{
 +      return 0;
 +}
 +
 +static inline int security_sctp_bind_connect(struct sock *sk, int optname,
 +                                           struct sockaddr *address,
 +                                           int addrlen)
 +{
 +      return 0;
 +}
 +
 +static inline void security_sctp_sk_clone(struct sctp_endpoint *ep,
 +                                        struct sock *sk,
 +                                        struct sock *newsk)
 +{
 +}
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_INFINIBAND
diff --combined kernel/signal.c
@@@ -770,7 -770,7 +770,7 @@@ static int check_kill_permission(int si
                }
        }
  
-       return security_task_kill(t, info, sig, 0);
+       return security_task_kill(t, info, sig, NULL);
  }
  
  /**
@@@ -1361,7 -1361,7 +1361,7 @@@ static int kill_as_cred_perm(const stru
  
  /* like kill_pid_info(), but doesn't use uid/euid of "current" */
  int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
-                        const struct cred *cred, u32 secid)
+                        const struct cred *cred)
  {
        int ret = -EINVAL;
        struct task_struct *p;
                ret = -EPERM;
                goto out_unlock;
        }
-       ret = security_task_kill(p, info, sig, secid);
+       ret = security_task_kill(p, info, sig, cred);
        if (ret)
                goto out_unlock;
  
@@@ -2843,6 -2843,10 +2843,6 @@@ enum siginfo_layout siginfo_layout(int 
  #ifdef FPE_FIXME
                if ((sig == SIGFPE) && (si_code == FPE_FIXME))
                        layout = SIL_FAULT;
 -#endif
 -#ifdef BUS_FIXME
 -              if ((sig == SIGBUS) && (si_code == BUS_FIXME))
 -                      layout = SIL_FAULT;
  #endif
        }
        return layout;
@@@ -3569,8 -3573,9 +3569,8 @@@ int __save_altstack(stack_t __user *uss
  }
  
  #ifdef CONFIG_COMPAT
 -COMPAT_SYSCALL_DEFINE2(sigaltstack,
 -                      const compat_stack_t __user *, uss_ptr,
 -                      compat_stack_t __user *, uoss_ptr)
 +static int do_compat_sigaltstack(const compat_stack_t __user *uss_ptr,
 +                               compat_stack_t __user *uoss_ptr)
  {
        stack_t uss, uoss;
        int ret;
        return ret;
  }
  
 +COMPAT_SYSCALL_DEFINE2(sigaltstack,
 +                      const compat_stack_t __user *, uss_ptr,
 +                      compat_stack_t __user *, uoss_ptr)
 +{
 +      return do_compat_sigaltstack(uss_ptr, uoss_ptr);
 +}
 +
  int compat_restore_altstack(const compat_stack_t __user *uss)
  {
 -      int err = compat_sys_sigaltstack(uss, NULL);
 +      int err = do_compat_sigaltstack(uss, NULL);
        /* squash all but -EFAULT for now */
        return err == -EFAULT ? err : 0;
  }
@@@ -3631,20 -3629,11 +3631,20 @@@ int __compat_save_altstack(compat_stack
  
  /**
   *  sys_sigpending - examine pending signals
 - *  @set: where mask of pending signal is returned
 + *  @uset: where mask of pending signal is returned
   */
 -SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set)
 +SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, uset)
  {
 -      return sys_rt_sigpending((sigset_t __user *)set, sizeof(old_sigset_t)); 
 +      sigset_t set;
 +      int err;
 +
 +      if (sizeof(old_sigset_t) > sizeof(*uset))
 +              return -EINVAL;
 +
 +      err = do_sigpending(&set);
 +      if (!err && copy_to_user(uset, &set, sizeof(old_sigset_t)))
 +              err = -EFAULT;
 +      return err;
  }
  
  #ifdef CONFIG_COMPAT
diff --combined security/apparmor/lsm.c
@@@ -23,6 -23,7 +23,6 @@@
  #include <linux/sysctl.h>
  #include <linux/audit.h>
  #include <linux/user_namespace.h>
 -#include <linux/kmemleak.h>
  #include <net/sock.h>
  
  #include "include/apparmor.h"
@@@ -716,16 -717,23 +716,23 @@@ static int apparmor_task_setrlimit(stru
  }
  
  static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
-                             int sig, u32 secid)
+                             int sig, const struct cred *cred)
  {
        struct aa_label *cl, *tl;
        int error;
  
-       if (secid)
-               /* TODO: after secid to label mapping is done.
-                *  Dealing with USB IO specific behavior
+       if (cred) {
+               /*
+                * Dealing with USB IO specific behavior
                 */
-               return 0;
+               cl = aa_get_newest_cred_label(cred);
+               tl = aa_get_task_label(target);
+               error = aa_may_signal(cl, tl, sig);
+               aa_put_label(cl);
+               aa_put_label(tl);
+               return error;
+       }
        cl = __begin_current_label_crit_section();
        tl = aa_get_task_label(target);
        error = aa_may_signal(cl, tl, sig);
diff --combined security/security.c
@@@ -61,11 -61,11 +61,11 @@@ static void __init do_security_initcall
  int __init security_init(void)
  {
        int i;
-       struct list_head *list = (struct list_head *) &security_hook_heads;
+       struct hlist_head *list = (struct hlist_head *) &security_hook_heads;
  
-       for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct list_head);
+       for (i = 0; i < sizeof(security_hook_heads) / sizeof(struct hlist_head);
             i++)
-               INIT_LIST_HEAD(&list[i]);
+               INIT_HLIST_HEAD(&list[i]);
        pr_info("Security Framework initialized\n");
  
        /*
@@@ -163,7 -163,7 +163,7 @@@ void __init security_add_hooks(struct s
  
        for (i = 0; i < count; i++) {
                hooks[i].lsm = lsm;
-               list_add_tail_rcu(&hooks[i].list, hooks[i].head);
+               hlist_add_tail_rcu(&hooks[i].list, hooks[i].head);
        }
        if (lsm_append(lsm, &lsm_names) < 0)
                panic("%s - Cannot get early memory.\n", __func__);
@@@ -201,7 -201,7 +201,7 @@@ EXPORT_SYMBOL(unregister_lsm_notifier)
        do {                                                    \
                struct security_hook_list *P;                   \
                                                                \
-               list_for_each_entry(P, &security_hook_heads.FUNC, list) \
+               hlist_for_each_entry(P, &security_hook_heads.FUNC, list) \
                        P->hook.FUNC(__VA_ARGS__);              \
        } while (0)
  
        do {                                                    \
                struct security_hook_list *P;                   \
                                                                \
-               list_for_each_entry(P, &security_hook_heads.FUNC, list) { \
+               hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \
                        RC = P->hook.FUNC(__VA_ARGS__);         \
                        if (RC != 0)                            \
                                break;                          \
@@@ -317,7 -317,7 +317,7 @@@ int security_vm_enough_memory_mm(struc
         * agree that it should be set it will. If any module
         * thinks it should not be set it won't.
         */
-       list_for_each_entry(hp, &security_hook_heads.vm_enough_memory, list) {
+       hlist_for_each_entry(hp, &security_hook_heads.vm_enough_memory, list) {
                rc = hp->hook.vm_enough_memory(mm, pages);
                if (rc <= 0) {
                        cap_sys_admin = 0;
@@@ -805,7 -805,7 +805,7 @@@ int security_inode_getsecurity(struct i
        /*
         * Only one module will provide an attribute with a given name.
         */
-       list_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) {
+       hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) {
                rc = hp->hook.inode_getsecurity(inode, name, buffer, alloc);
                if (rc != -EOPNOTSUPP)
                        return rc;
@@@ -823,7 -823,7 +823,7 @@@ int security_inode_setsecurity(struct i
        /*
         * Only one module will provide an attribute with a given name.
         */
-       list_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) {
+       hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) {
                rc = hp->hook.inode_setsecurity(inode, name, value, size,
                                                                flags);
                if (rc != -EOPNOTSUPP)
@@@ -1114,9 -1114,9 +1114,9 @@@ int security_task_movememory(struct tas
  }
  
  int security_task_kill(struct task_struct *p, struct siginfo *info,
-                       int sig, u32 secid)
+                       int sig, const struct cred *cred)
  {
-       return call_int_hook(task_kill, 0, p, info, sig, secid);
+       return call_int_hook(task_kill, 0, p, info, sig, cred);
  }
  
  int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
        int rc = -ENOSYS;
        struct security_hook_list *hp;
  
-       list_for_each_entry(hp, &security_hook_heads.task_prctl, list) {
+       hlist_for_each_entry(hp, &security_hook_heads.task_prctl, list) {
                thisrc = hp->hook.task_prctl(option, arg2, arg3, arg4, arg5);
                if (thisrc != -ENOSYS) {
                        rc = thisrc;
@@@ -1163,84 -1163,84 +1163,84 @@@ void security_msg_msg_free(struct msg_m
        call_void_hook(msg_msg_free_security, msg);
  }
  
 -int security_msg_queue_alloc(struct msg_queue *msq)
 +int security_msg_queue_alloc(struct kern_ipc_perm *msq)
  {
        return call_int_hook(msg_queue_alloc_security, 0, msq);
  }
  
 -void security_msg_queue_free(struct msg_queue *msq)
 +void security_msg_queue_free(struct kern_ipc_perm *msq)
  {
        call_void_hook(msg_queue_free_security, msq);
  }
  
 -int security_msg_queue_associate(struct msg_queue *msq, int msqflg)
 +int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
  {
        return call_int_hook(msg_queue_associate, 0, msq, msqflg);
  }
  
 -int security_msg_queue_msgctl(struct msg_queue *msq, int cmd)
 +int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
  {
        return call_int_hook(msg_queue_msgctl, 0, msq, cmd);
  }
  
 -int security_msg_queue_msgsnd(struct msg_queue *msq,
 +int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
                               struct msg_msg *msg, int msqflg)
  {
        return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg);
  }
  
 -int security_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
 +int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                               struct task_struct *target, long type, int mode)
  {
        return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode);
  }
  
 -int security_shm_alloc(struct shmid_kernel *shp)
 +int security_shm_alloc(struct kern_ipc_perm *shp)
  {
        return call_int_hook(shm_alloc_security, 0, shp);
  }
  
 -void security_shm_free(struct shmid_kernel *shp)
 +void security_shm_free(struct kern_ipc_perm *shp)
  {
        call_void_hook(shm_free_security, shp);
  }
  
 -int security_shm_associate(struct shmid_kernel *shp, int shmflg)
 +int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
  {
        return call_int_hook(shm_associate, 0, shp, shmflg);
  }
  
 -int security_shm_shmctl(struct shmid_kernel *shp, int cmd)
 +int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
  {
        return call_int_hook(shm_shmctl, 0, shp, cmd);
  }
  
 -int security_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr, int shmflg)
 +int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg)
  {
        return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg);
  }
  
 -int security_sem_alloc(struct sem_array *sma)
 +int security_sem_alloc(struct kern_ipc_perm *sma)
  {
        return call_int_hook(sem_alloc_security, 0, sma);
  }
  
 -void security_sem_free(struct sem_array *sma)
 +void security_sem_free(struct kern_ipc_perm *sma)
  {
        call_void_hook(sem_free_security, sma);
  }
  
 -int security_sem_associate(struct sem_array *sma, int semflg)
 +int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
  {
        return call_int_hook(sem_associate, 0, sma, semflg);
  }
  
 -int security_sem_semctl(struct sem_array *sma, int cmd)
 +int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
  {
        return call_int_hook(sem_semctl, 0, sma, cmd);
  }
  
 -int security_sem_semop(struct sem_array *sma, struct sembuf *sops,
 +int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
                        unsigned nsops, int alter)
  {
        return call_int_hook(sem_semop, 0, sma, sops, nsops, alter);
@@@ -1473,7 -1473,6 +1473,7 @@@ void security_inet_conn_established(str
  {
        call_void_hook(inet_conn_established, sk, skb);
  }
 +EXPORT_SYMBOL(security_inet_conn_established);
  
  int security_secmark_relabel_packet(u32 secid)
  {
@@@ -1529,27 -1528,6 +1529,27 @@@ int security_tun_dev_open(void *securit
  }
  EXPORT_SYMBOL(security_tun_dev_open);
  
 +int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb)
 +{
 +      return call_int_hook(sctp_assoc_request, 0, ep, skb);
 +}
 +EXPORT_SYMBOL(security_sctp_assoc_request);
 +
 +int security_sctp_bind_connect(struct sock *sk, int optname,
 +                             struct sockaddr *address, int addrlen)
 +{
 +      return call_int_hook(sctp_bind_connect, 0, sk, optname,
 +                           address, addrlen);
 +}
 +EXPORT_SYMBOL(security_sctp_bind_connect);
 +
 +void security_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
 +                          struct sock *newsk)
 +{
 +      call_void_hook(sctp_sk_clone, ep, sk, newsk);
 +}
 +EXPORT_SYMBOL(security_sctp_sk_clone);
 +
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_INFINIBAND
@@@ -1651,7 -1629,7 +1651,7 @@@ int security_xfrm_state_pol_flow_match(
         * For speed optimization, we explicitly break the loop rather than
         * using the macro
         */
-       list_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match,
+       hlist_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match,
                                list) {
                rc = hp->hook.xfrm_state_pol_flow_match(x, xp, fl);
                break;
diff --combined security/selinux/hooks.c
@@@ -67,8 -67,6 +67,8 @@@
  #include <linux/tcp.h>
  #include <linux/udp.h>
  #include <linux/dccp.h>
 +#include <linux/sctp.h>
 +#include <net/sctp/structs.h>
  #include <linux/quota.h>
  #include <linux/un.h>         /* for Unix socket types */
  #include <net/af_unix.h>      /* for Unix socket types */
  #include "audit.h"
  #include "avc_ss.h"
  
 +struct selinux_state selinux_state;
 +
  /* SECMARK reference count */
  static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
  
  #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 -int selinux_enforcing;
 +static int selinux_enforcing_boot;
  
  static int __init enforcing_setup(char *str)
  {
        unsigned long enforcing;
        if (!kstrtoul(str, 0, &enforcing))
 -              selinux_enforcing = enforcing ? 1 : 0;
 +              selinux_enforcing_boot = enforcing ? 1 : 0;
        return 1;
  }
  __setup("enforcing=", enforcing_setup);
 +#else
 +#define selinux_enforcing_boot 1
  #endif
  
  #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
@@@ -135,19 -129,6 +135,19 @@@ __setup("selinux=", selinux_enabled_set
  int selinux_enabled = 1;
  #endif
  
 +static unsigned int selinux_checkreqprot_boot =
 +      CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 +
 +static int __init checkreqprot_setup(char *str)
 +{
 +      unsigned long checkreqprot;
 +
 +      if (!kstrtoul(str, 0, &checkreqprot))
 +              selinux_checkreqprot_boot = checkreqprot ? 1 : 0;
 +      return 1;
 +}
 +__setup("checkreqprot=", checkreqprot_setup);
 +
  static struct kmem_cache *sel_inode_cache;
  static struct kmem_cache *file_security_cache;
  
   */
  static int selinux_secmark_enabled(void)
  {
 -      return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
 +      return (selinux_policycap_alwaysnetwork() ||
 +              atomic_read(&selinux_secmark_refcount));
  }
  
  /**
   */
  static int selinux_peerlbl_enabled(void)
  {
 -      return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
 +      return (selinux_policycap_alwaysnetwork() ||
 +              netlbl_enabled() || selinux_xfrm_enabled());
  }
  
  static int selinux_netcache_avc_callback(u32 event)
@@@ -285,8 -264,7 +285,8 @@@ static int __inode_security_revalidate(
  
        might_sleep_if(may_sleep);
  
 -      if (ss_initialized && isec->initialized != LABEL_INITIALIZED) {
 +      if (selinux_state.initialized &&
 +          isec->initialized != LABEL_INITIALIZED) {
                if (!may_sleep)
                        return -ECHILD;
  
@@@ -468,14 -446,12 +468,14 @@@ static int may_context_mount_sb_relabel
        const struct task_security_struct *tsec = cred->security;
        int rc;
  
 -      rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
 +      rc = avc_has_perm(&selinux_state,
 +                        tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__RELABELFROM, NULL);
        if (rc)
                return rc;
  
 -      rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
 +      rc = avc_has_perm(&selinux_state,
 +                        tsec->sid, sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__RELABELTO, NULL);
        return rc;
  }
@@@ -486,14 -462,12 +486,14 @@@ static int may_context_mount_inode_rela
  {
        const struct task_security_struct *tsec = cred->security;
        int rc;
 -      rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
 +      rc = avc_has_perm(&selinux_state,
 +                        tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__RELABELFROM, NULL);
        if (rc)
                return rc;
  
 -      rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, sbsec->sid, SECCLASS_FILESYSTEM,
                          FILESYSTEM__ASSOCIATE, NULL);
        return rc;
  }
@@@ -512,7 -486,7 +512,7 @@@ static int selinux_is_sblabel_mnt(struc
                !strcmp(sb->s_type->name, "debugfs") ||
                !strcmp(sb->s_type->name, "tracefs") ||
                !strcmp(sb->s_type->name, "rootfs") ||
 -              (selinux_policycap_cgroupseclabel &&
 +              (selinux_policycap_cgroupseclabel() &&
                 (!strcmp(sb->s_type->name, "cgroup") ||
                  !strcmp(sb->s_type->name, "cgroup2")));
  }
@@@ -612,7 -586,7 +612,7 @@@ static int selinux_get_mnt_opts(const s
        if (!(sbsec->flags & SE_SBINITIALIZED))
                return -EINVAL;
  
 -      if (!ss_initialized)
 +      if (!selinux_state.initialized)
                return -EINVAL;
  
        /* make sure we always check enough bits to cover the mask */
  
        i = 0;
        if (sbsec->flags & FSCONTEXT_MNT) {
 -              rc = security_sid_to_context(sbsec->sid, &context, &len);
 +              rc = security_sid_to_context(&selinux_state, sbsec->sid,
 +                                           &context, &len);
                if (rc)
                        goto out_free;
                opts->mnt_opts[i] = context;
                opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
        }
        if (sbsec->flags & CONTEXT_MNT) {
 -              rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
 +              rc = security_sid_to_context(&selinux_state,
 +                                           sbsec->mntpoint_sid,
 +                                           &context, &len);
                if (rc)
                        goto out_free;
                opts->mnt_opts[i] = context;
                opts->mnt_opts_flags[i++] = CONTEXT_MNT;
        }
        if (sbsec->flags & DEFCONTEXT_MNT) {
 -              rc = security_sid_to_context(sbsec->def_sid, &context, &len);
 +              rc = security_sid_to_context(&selinux_state, sbsec->def_sid,
 +                                           &context, &len);
                if (rc)
                        goto out_free;
                opts->mnt_opts[i] = context;
                struct dentry *root = sbsec->sb->s_root;
                struct inode_security_struct *isec = backing_inode_security(root);
  
 -              rc = security_sid_to_context(isec->sid, &context, &len);
 +              rc = security_sid_to_context(&selinux_state, isec->sid,
 +                                           &context, &len);
                if (rc)
                        goto out_free;
                opts->mnt_opts[i] = context;
@@@ -735,7 -704,7 +735,7 @@@ static int selinux_set_mnt_opts(struct 
  
        mutex_lock(&sbsec->lock);
  
 -      if (!ss_initialized) {
 +      if (!selinux_state.initialized) {
                if (!num_opts) {
                        /* Defer initialization until selinux_complete_init,
                           after the initial policy is loaded and the security
  
                if (flags[i] == SBLABEL_MNT)
                        continue;
 -              rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
 +              rc = security_context_str_to_sid(&selinux_state,
 +                                               mount_options[i], &sid,
 +                                               GFP_KERNEL);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_str_to_sid"
                               "(%s) failed for (dev %s, type %s) errno=%d\n",
                 * Determine the labeling behavior to use for this
                 * filesystem type.
                 */
 -              rc = security_fs_use(sb);
 +              rc = security_fs_use(&selinux_state, sb);
                if (rc) {
                        printk(KERN_WARNING
                                "%s: security_fs_use(%s) returned %d\n",
                }
                if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
                        sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
 -                      rc = security_transition_sid(current_sid(), current_sid(),
 +                      rc = security_transition_sid(&selinux_state,
 +                                                   current_sid(),
 +                                                   current_sid(),
                                                     SECCLASS_FILE, NULL,
                                                     &sbsec->mntpoint_sid);
                        if (rc)
@@@ -1022,7 -987,7 +1022,7 @@@ static int selinux_sb_clone_mnt_opts(co
         * if the parent was able to be mounted it clearly had no special lsm
         * mount options.  thus we can safely deal with this superblock later
         */
 -      if (!ss_initialized)
 +      if (!selinux_state.initialized)
                return 0;
  
        /*
  
        if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
                !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
 -              rc = security_fs_use(newsb);
 +              rc = security_fs_use(&selinux_state, newsb);
                if (rc)
                        goto out;
        }
@@@ -1332,7 -1297,7 +1332,7 @@@ static inline int default_protocol_dgra
  
  static inline u16 socket_type_to_security_class(int family, int type, int protocol)
  {
 -      int extsockclass = selinux_policycap_extsockclass;
 +      int extsockclass = selinux_policycap_extsockclass();
  
        switch (family) {
        case PF_UNIX:
@@@ -1506,8 -1471,7 +1506,8 @@@ static int selinux_genfs_get_sid(struc
                                path++;
                        }
                }
 -              rc = security_genfs_sid(sb->s_type->name, path, tclass, sid);
 +              rc = security_genfs_sid(&selinux_state, sb->s_type->name,
 +                                      path, tclass, sid);
        }
        free_page((unsigned long)buffer);
        return rc;
@@@ -1625,8 -1589,7 +1625,8 @@@ static int inode_doinit_with_dentry(str
                        sid = sbsec->def_sid;
                        rc = 0;
                } else {
 -                      rc = security_context_to_sid_default(context, rc, &sid,
 +                      rc = security_context_to_sid_default(&selinux_state,
 +                                                           context, rc, &sid,
                                                             sbsec->def_sid,
                                                             GFP_NOFS);
                        if (rc) {
                sid = sbsec->sid;
  
                /* Try to obtain a transition SID. */
 -              rc = security_transition_sid(task_sid, sid, sclass, NULL, &sid);
 +              rc = security_transition_sid(&selinux_state, task_sid, sid,
 +                                           sclass, NULL, &sid);
                if (rc)
                        goto out;
                break;
@@@ -1778,11 -1740,9 +1778,11 @@@ static int cred_has_capability(const st
                return -EINVAL;
        }
  
 -      rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
 +      rc = avc_has_perm_noaudit(&selinux_state,
 +                                sid, sid, sclass, av, 0, &avd);
        if (audit == SECURITY_CAP_AUDIT) {
 -              int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
 +              int rc2 = avc_audit(&selinux_state,
 +                                  sid, sid, sclass, av, &avd, rc, &ad, 0);
                if (rc2)
                        return rc2;
        }
@@@ -1808,8 -1768,7 +1808,8 @@@ static int inode_has_perm(const struct 
        sid = cred_sid(cred);
        isec = inode->i_security;
  
 -      return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, isec->sclass, perms, adp);
  }
  
  /* Same as inode_has_perm, but pass explicit audit data containing
@@@ -1882,8 -1841,7 +1882,8 @@@ static int file_has_perm(const struct c
        ad.u.file = file;
  
        if (sid != fsec->sid) {
 -              rc = avc_has_perm(sid, fsec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, fsec->sid,
                                  SECCLASS_FD,
                                  FD__USE,
                                  &ad);
@@@ -1925,8 -1883,7 +1925,8 @@@ selinux_determine_inode_label(const str
                *_new_isid = tsec->create_sid;
        } else {
                const struct inode_security_struct *dsec = inode_security(dir);
 -              return security_transition_sid(tsec->sid, dsec->sid, tclass,
 +              return security_transition_sid(&selinux_state, tsec->sid,
 +                                             dsec->sid, tclass,
                                               name, _new_isid);
        }
  
@@@ -1953,8 -1910,7 +1953,8 @@@ static int may_create(struct inode *dir
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
  
 -      rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, dsec->sid, SECCLASS_DIR,
                          DIR__ADD_NAME | DIR__SEARCH,
                          &ad);
        if (rc)
        if (rc)
                return rc;
  
 -      rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, newsid, tclass, FILE__CREATE, &ad);
        if (rc)
                return rc;
  
 -      return avc_has_perm(newsid, sbsec->sid,
 +      return avc_has_perm(&selinux_state,
 +                          newsid, sbsec->sid,
                            SECCLASS_FILESYSTEM,
                            FILESYSTEM__ASSOCIATE, &ad);
  }
@@@ -2000,8 -1954,7 +2000,8 @@@ static int may_link(struct inode *dir
  
        av = DIR__SEARCH;
        av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
 -      rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, av, &ad);
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, dsec->sid, SECCLASS_DIR, av, &ad);
        if (rc)
                return rc;
  
                return 0;
        }
  
 -      rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid, isec->sclass, av, &ad);
        return rc;
  }
  
@@@ -2046,19 -1998,16 +2046,19 @@@ static inline int may_rename(struct ino
        ad.type = LSM_AUDIT_DATA_DENTRY;
  
        ad.u.dentry = old_dentry;
 -      rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, old_dsec->sid, SECCLASS_DIR,
                          DIR__REMOVE_NAME | DIR__SEARCH, &ad);
        if (rc)
                return rc;
 -      rc = avc_has_perm(sid, old_isec->sid,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, old_isec->sid,
                          old_isec->sclass, FILE__RENAME, &ad);
        if (rc)
                return rc;
        if (old_is_dir && new_dir != old_dir) {
 -              rc = avc_has_perm(sid, old_isec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, old_isec->sid,
                                  old_isec->sclass, DIR__REPARENT, &ad);
                if (rc)
                        return rc;
        av = DIR__ADD_NAME | DIR__SEARCH;
        if (d_is_positive(new_dentry))
                av |= DIR__REMOVE_NAME;
 -      rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
        if (rc)
                return rc;
        if (d_is_positive(new_dentry)) {
                new_isec = backing_inode_security(new_dentry);
                new_is_dir = d_is_dir(new_dentry);
 -              rc = avc_has_perm(sid, new_isec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, new_isec->sid,
                                  new_isec->sclass,
                                  (new_is_dir ? DIR__RMDIR : FILE__UNLINK), &ad);
                if (rc)
@@@ -2096,8 -2043,7 +2096,8 @@@ static int superblock_has_perm(const st
        u32 sid = cred_sid(cred);
  
        sbsec = sb->s_security;
 -      return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
 +      return avc_has_perm(&selinux_state,
 +                          sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
  }
  
  /* Convert a Linux mode and permission mask to an access vector. */
@@@ -2160,8 -2106,7 +2160,8 @@@ static inline u32 open_file_to_av(struc
        u32 av = file_to_av(file);
        struct inode *inode = file_inode(file);
  
 -      if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
 +      if (selinux_policycap_openperm() &&
 +          inode->i_sb->s_magic != SOCKFS_MAGIC)
                av |= FILE__OPEN;
  
        return av;
@@@ -2174,8 -2119,7 +2174,8 @@@ static int selinux_binder_set_context_m
        u32 mysid = current_sid();
        u32 mgrsid = task_sid(mgr);
  
 -      return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
 +      return avc_has_perm(&selinux_state,
 +                          mysid, mgrsid, SECCLASS_BINDER,
                            BINDER__SET_CONTEXT_MGR, NULL);
  }
  
@@@ -2188,15 -2132,13 +2188,15 @@@ static int selinux_binder_transaction(s
        int rc;
  
        if (mysid != fromsid) {
 -              rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
 +              rc = avc_has_perm(&selinux_state,
 +                                mysid, fromsid, SECCLASS_BINDER,
                                  BINDER__IMPERSONATE, NULL);
                if (rc)
                        return rc;
        }
  
 -      return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
 +      return avc_has_perm(&selinux_state,
 +                          fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
                            NULL);
  }
  
@@@ -2206,8 -2148,7 +2206,8 @@@ static int selinux_binder_transfer_bind
        u32 fromsid = task_sid(from);
        u32 tosid = task_sid(to);
  
 -      return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
 +      return avc_has_perm(&selinux_state,
 +                          fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
                            NULL);
  }
  
@@@ -2226,8 -2167,7 +2226,8 @@@ static int selinux_binder_transfer_file
        ad.u.path = file->f_path;
  
        if (sid != fsec->sid) {
 -              rc = avc_has_perm(sid, fsec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, fsec->sid,
                                  SECCLASS_FD,
                                  FD__USE,
                                  &ad);
                return 0;
  
        isec = backing_inode_security(dentry);
 -      return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, isec->sclass, file_to_av(file),
                            &ad);
  }
  
@@@ -2257,25 -2196,21 +2257,25 @@@ static int selinux_ptrace_access_check(
        u32 csid = task_sid(child);
  
        if (mode & PTRACE_MODE_READ)
 -              return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
 +              return avc_has_perm(&selinux_state,
 +                                  sid, csid, SECCLASS_FILE, FILE__READ, NULL);
  
 -      return avc_has_perm(sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
 +      return avc_has_perm(&selinux_state,
 +                          sid, csid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL);
  }
  
  static int selinux_ptrace_traceme(struct task_struct *parent)
  {
 -      return avc_has_perm(task_sid(parent), current_sid(), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          task_sid(parent), current_sid(), SECCLASS_PROCESS,
                            PROCESS__PTRACE, NULL);
  }
  
  static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
  {
 -      return avc_has_perm(current_sid(), task_sid(target), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(target), SECCLASS_PROCESS,
                            PROCESS__GETCAP, NULL);
  }
  
@@@ -2284,8 -2219,7 +2284,8 @@@ static int selinux_capset(struct cred *
                          const kernel_cap_t *inheritable,
                          const kernel_cap_t *permitted)
  {
 -      return avc_has_perm(cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          cred_sid(old), cred_sid(new), SECCLASS_PROCESS,
                            PROCESS__SETCAP, NULL);
  }
  
@@@ -2345,21 -2279,18 +2345,21 @@@ static int selinux_syslog(int type
        switch (type) {
        case SYSLOG_ACTION_READ_ALL:    /* Read last kernel messages */
        case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
 -              return avc_has_perm(current_sid(), SECINITSID_KERNEL,
 +              return avc_has_perm(&selinux_state,
 +                                  current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, NULL);
        case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
        case SYSLOG_ACTION_CONSOLE_ON:  /* Enable logging to console */
        /* Set level of messages printed to console */
        case SYSLOG_ACTION_CONSOLE_LEVEL:
 -              return avc_has_perm(current_sid(), SECINITSID_KERNEL,
 +              return avc_has_perm(&selinux_state,
 +                                  current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE,
                                    NULL);
        }
        /* All other syslog types */
 -      return avc_has_perm(current_sid(), SECINITSID_KERNEL,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), SECINITSID_KERNEL,
                            SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, NULL);
  }
  
@@@ -2420,14 -2351,13 +2420,14 @@@ static int check_nnp_nosuid(const struc
         * policy allows the corresponding permission between
         * the old and new contexts.
         */
 -      if (selinux_policycap_nnp_nosuid_transition) {
 +      if (selinux_policycap_nnp_nosuid_transition()) {
                av = 0;
                if (nnp)
                        av |= PROCESS2__NNP_TRANSITION;
                if (nosuid)
                        av |= PROCESS2__NOSUID_TRANSITION;
 -              rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                old_tsec->sid, new_tsec->sid,
                                  SECCLASS_PROCESS2, av, NULL);
                if (!rc)
                        return 0;
         * i.e. SIDs that are guaranteed to only be allowed a subset
         * of the permissions of the current SID.
         */
 -      rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
 +      rc = security_bounded_transition(&selinux_state, old_tsec->sid,
 +                                       new_tsec->sid);
        if (!rc)
                return 0;
  
@@@ -2491,8 -2420,8 +2491,8 @@@ static int selinux_bprm_set_creds(struc
                        return rc;
        } else {
                /* Check for a default transition on this program. */
 -              rc = security_transition_sid(old_tsec->sid, isec->sid,
 -                                           SECCLASS_PROCESS, NULL,
 +              rc = security_transition_sid(&selinux_state, old_tsec->sid,
 +                                           isec->sid, SECCLASS_PROCESS, NULL,
                                             &new_tsec->sid);
                if (rc)
                        return rc;
        ad.u.file = bprm->file;
  
        if (new_tsec->sid == old_tsec->sid) {
 -              rc = avc_has_perm(old_tsec->sid, isec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                old_tsec->sid, isec->sid,
                                  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
                if (rc)
                        return rc;
        } else {
                /* Check permissions for the transition. */
 -              rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                old_tsec->sid, new_tsec->sid,
                                  SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
                if (rc)
                        return rc;
  
 -              rc = avc_has_perm(new_tsec->sid, isec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                new_tsec->sid, isec->sid,
                                  SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
                if (rc)
                        return rc;
  
                /* Check for shared state */
                if (bprm->unsafe & LSM_UNSAFE_SHARE) {
 -                      rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
 +                      rc = avc_has_perm(&selinux_state,
 +                                        old_tsec->sid, new_tsec->sid,
                                          SECCLASS_PROCESS, PROCESS__SHARE,
                                          NULL);
                        if (rc)
                if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
                        u32 ptsid = ptrace_parent_sid();
                        if (ptsid != 0) {
 -                              rc = avc_has_perm(ptsid, new_tsec->sid,
 +                              rc = avc_has_perm(&selinux_state,
 +                                                ptsid, new_tsec->sid,
                                                  SECCLASS_PROCESS,
                                                  PROCESS__PTRACE, NULL);
                                if (rc)
                /* Enable secure mode for SIDs transitions unless
                   the noatsecure permission is granted between
                   the two SIDs, i.e. ahp returns 0. */
 -              rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                old_tsec->sid, new_tsec->sid,
                                  SECCLASS_PROCESS, PROCESS__NOATSECURE,
                                  NULL);
                bprm->secureexec |= !!rc;
@@@ -2652,8 -2575,7 +2652,8 @@@ static void selinux_bprm_committing_cre
         * higher than the default soft limit for cases where the default is
         * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
         */
 -      rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
 +      rc = avc_has_perm(&selinux_state,
 +                        new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
                          PROCESS__RLIMITINH, NULL);
        if (rc) {
                /* protect against do_prlimit() */
@@@ -2693,8 -2615,7 +2693,8 @@@ static void selinux_bprm_committed_cred
         * This must occur _after_ the task SID has been updated so that any
         * kill done after the flush will be checked against the new SID.
         */
 -      rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
 +      rc = avc_has_perm(&selinux_state,
 +                        osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL);
        if (rc) {
                if (IS_ENABLED(CONFIG_POSIX_TIMERS)) {
                        memset(&itimer, 0, sizeof itimer);
@@@ -2858,9 -2779,7 +2858,9 @@@ static int selinux_sb_remount(struct su
  
                if (flags[i] == SBLABEL_MNT)
                        continue;
 -              rc = security_context_str_to_sid(mount_options[i], &sid, GFP_KERNEL);
 +              rc = security_context_str_to_sid(&selinux_state,
 +                                               mount_options[i], &sid,
 +                                               GFP_KERNEL);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_str_to_sid"
                               "(%s) failed for (dev %s, type %s) errno=%d\n",
@@@ -2985,8 -2904,7 +2985,8 @@@ static int selinux_dentry_init_security
        if (rc)
                return rc;
  
 -      return security_sid_to_context(newsid, (char **)ctx, ctxlen);
 +      return security_sid_to_context(&selinux_state, newsid, (char **)ctx,
 +                                     ctxlen);
  }
  
  static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
@@@ -3040,15 -2958,14 +3040,15 @@@ static int selinux_inode_init_security(
                isec->initialized = LABEL_INITIALIZED;
        }
  
 -      if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
 +      if (!selinux_state.initialized || !(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
  
        if (name)
                *name = XATTR_SELINUX_SUFFIX;
  
        if (value && len) {
 -              rc = security_sid_to_context_force(newsid, &context, &clen);
 +              rc = security_sid_to_context_force(&selinux_state, newsid,
 +                                                 &context, &clen);
                if (rc)
                        return rc;
                *value = context;
@@@ -3123,8 -3040,7 +3123,8 @@@ static int selinux_inode_follow_link(st
        if (IS_ERR(isec))
                return PTR_ERR(isec);
  
 -      return avc_has_perm_flags(sid, isec->sid, isec->sclass, FILE__READ, &ad,
 +      return avc_has_perm_flags(&selinux_state,
 +                                sid, isec->sid, isec->sclass, FILE__READ, &ad,
                                  rcu ? MAY_NOT_BLOCK : 0);
  }
  
@@@ -3140,8 -3056,7 +3140,8 @@@ static noinline int audit_inode_permiss
        ad.type = LSM_AUDIT_DATA_INODE;
        ad.u.inode = inode;
  
 -      rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
 +      rc = slow_avc_audit(&selinux_state,
 +                          current_sid(), isec->sid, isec->sclass, perms,
                            audited, denied, result, &ad, flags);
        if (rc)
                return rc;
@@@ -3179,8 -3094,7 +3179,8 @@@ static int selinux_inode_permission(str
        if (IS_ERR(isec))
                return PTR_ERR(isec);
  
 -      rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
 +      rc = avc_has_perm_noaudit(&selinux_state,
 +                                sid, isec->sid, isec->sclass, perms, 0, &avd);
        audited = avc_audit_required(perms, &avd, rc,
                                     from_access ? FILE__AUDIT_ACCESS : 0,
                                     &denied);
@@@ -3212,7 -3126,7 +3212,7 @@@ static int selinux_inode_setattr(struc
                        ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
                return dentry_has_perm(cred, dentry, FILE__SETATTR);
  
 -      if (selinux_policycap_openperm &&
 +      if (selinux_policycap_openperm() &&
            inode->i_sb->s_magic != SOCKFS_MAGIC &&
            (ia_valid & ATTR_SIZE) &&
            !(ia_valid & ATTR_FILE))
@@@ -3269,14 -3183,12 +3269,14 @@@ static int selinux_inode_setxattr(struc
        ad.u.dentry = dentry;
  
        isec = backing_inode_security(dentry);
 -      rc = avc_has_perm(sid, isec->sid, isec->sclass,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid, isec->sclass,
                          FILE__RELABELFROM, &ad);
        if (rc)
                return rc;
  
 -      rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
 +      rc = security_context_to_sid(&selinux_state, value, size, &newsid,
 +                                   GFP_KERNEL);
        if (rc == -EINVAL) {
                if (!has_cap_mac_admin(true)) {
                        struct audit_buffer *ab;
  
                        return rc;
                }
 -              rc = security_context_to_sid_force(value, size, &newsid);
 +              rc = security_context_to_sid_force(&selinux_state, value,
 +                                                 size, &newsid);
        }
        if (rc)
                return rc;
  
 -      rc = avc_has_perm(sid, newsid, isec->sclass,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, newsid, isec->sclass,
                          FILE__RELABELTO, &ad);
        if (rc)
                return rc;
  
 -      rc = security_validate_transition(isec->sid, newsid, sid,
 -                                        isec->sclass);
 +      rc = security_validate_transition(&selinux_state, isec->sid, newsid,
 +                                        sid, isec->sclass);
        if (rc)
                return rc;
  
 -      return avc_has_perm(newsid,
 +      return avc_has_perm(&selinux_state,
 +                          newsid,
                            sbsec->sid,
                            SECCLASS_FILESYSTEM,
                            FILESYSTEM__ASSOCIATE,
@@@ -3340,8 -3249,7 +3340,8 @@@ static void selinux_inode_post_setxattr
                return;
        }
  
 -      rc = security_context_to_sid_force(value, size, &newsid);
 +      rc = security_context_to_sid_force(&selinux_state, value, size,
 +                                         &newsid);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to map context to SID"
                       "for (%s, %lu), rc=%d\n",
@@@ -3416,12 -3324,10 +3416,12 @@@ static int selinux_inode_getsecurity(st
         */
        isec = inode_security(inode);
        if (has_cap_mac_admin(false))
 -              error = security_sid_to_context_force(isec->sid, &context,
 +              error = security_sid_to_context_force(&selinux_state,
 +                                                    isec->sid, &context,
                                                      &size);
        else
 -              error = security_sid_to_context(isec->sid, &context, &size);
 +              error = security_sid_to_context(&selinux_state, isec->sid,
 +                                              &context, &size);
        if (error)
                return error;
        error = size;
@@@ -3447,8 -3353,7 +3447,8 @@@ static int selinux_inode_setsecurity(st
        if (!value || !size)
                return -EACCES;
  
 -      rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
 +      rc = security_context_to_sid(&selinux_state, value, size, &newsid,
 +                                   GFP_KERNEL);
        if (rc)
                return rc;
  
@@@ -3537,7 -3442,7 +3537,7 @@@ static int selinux_file_permission(stru
  
        isec = inode_security(inode);
        if (sid == fsec->sid && fsec->isid == isec->sid &&
 -          fsec->pseqno == avc_policy_seqno())
 +          fsec->pseqno == avc_policy_seqno(&selinux_state))
                /* No change since file_open check. */
                return 0;
  
@@@ -3577,8 -3482,7 +3577,8 @@@ static int ioctl_has_perm(const struct 
        ad.u.op->path = file->f_path;
  
        if (ssid != fsec->sid) {
 -              rc = avc_has_perm(ssid, fsec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                ssid, fsec->sid,
                                SECCLASS_FD,
                                FD__USE,
                                &ad);
                return 0;
  
        isec = inode_security(inode);
 -      rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
 -                      requested, driver, xperm, &ad);
 +      rc = avc_has_extended_perms(&selinux_state,
 +                                  ssid, isec->sid, isec->sclass,
 +                                  requested, driver, xperm, &ad);
  out:
        return rc;
  }
@@@ -3660,8 -3563,7 +3660,8 @@@ static int file_map_prot_check(struct f
                 * private file mapping that will also be writable.
                 * This has an additional check.
                 */
 -              rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, sid, SECCLASS_PROCESS,
                                  PROCESS__EXECMEM, NULL);
                if (rc)
                        goto error;
@@@ -3691,8 -3593,7 +3691,8 @@@ static int selinux_mmap_addr(unsigned l
  
        if (addr < CONFIG_LSM_MMAP_MIN_ADDR) {
                u32 sid = current_sid();
 -              rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, sid, SECCLASS_MEMPROTECT,
                                  MEMPROTECT__MMAP_ZERO, NULL);
        }
  
@@@ -3714,7 -3615,7 +3714,7 @@@ static int selinux_mmap_file(struct fil
                        return rc;
        }
  
 -      if (selinux_checkreqprot)
 +      if (selinux_state.checkreqprot)
                prot = reqprot;
  
        return file_map_prot_check(file, prot,
@@@ -3728,7 -3629,7 +3728,7 @@@ static int selinux_file_mprotect(struc
        const struct cred *cred = current_cred();
        u32 sid = cred_sid(cred);
  
 -      if (selinux_checkreqprot)
 +      if (selinux_state.checkreqprot)
                prot = reqprot;
  
        if (default_noexec &&
                int rc = 0;
                if (vma->vm_start >= vma->vm_mm->start_brk &&
                    vma->vm_end <= vma->vm_mm->brk) {
 -                      rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
 +                      rc = avc_has_perm(&selinux_state,
 +                                        sid, sid, SECCLASS_PROCESS,
                                          PROCESS__EXECHEAP, NULL);
                } else if (!vma->vm_file &&
                           ((vma->vm_start <= vma->vm_mm->start_stack &&
                             vma->vm_end >= vma->vm_mm->start_stack) ||
                            vma_is_stack_for_current(vma))) {
 -                      rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
 +                      rc = avc_has_perm(&selinux_state,
 +                                        sid, sid, SECCLASS_PROCESS,
                                          PROCESS__EXECSTACK, NULL);
                } else if (vma->vm_file && vma->anon_vma) {
                        /*
@@@ -3836,8 -3735,7 +3836,8 @@@ static int selinux_file_send_sigiotask(
        else
                perm = signal_to_av(signum);
  
 -      return avc_has_perm(fsec->fown_sid, sid,
 +      return avc_has_perm(&selinux_state,
 +                          fsec->fown_sid, sid,
                            SECCLASS_PROCESS, perm, NULL);
  }
  
@@@ -3863,7 -3761,7 +3863,7 @@@ static int selinux_file_open(struct fil
         * struct as its SID.
         */
        fsec->isid = isec->sid;
 -      fsec->pseqno = avc_policy_seqno();
 +      fsec->pseqno = avc_policy_seqno(&selinux_state);
        /*
         * Since the inode label or policy seqno may have changed
         * between the selinux_inode_permission check and the saving
@@@ -3882,8 -3780,7 +3882,8 @@@ static int selinux_task_alloc(struct ta
  {
        u32 sid = current_sid();
  
 -      return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
 +      return avc_has_perm(&selinux_state,
 +                          sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
  }
  
  /*
@@@ -3957,8 -3854,7 +3957,8 @@@ static int selinux_kernel_act_as(struc
        u32 sid = current_sid();
        int ret;
  
 -      ret = avc_has_perm(sid, secid,
 +      ret = avc_has_perm(&selinux_state,
 +                         sid, secid,
                           SECCLASS_KERNEL_SERVICE,
                           KERNEL_SERVICE__USE_AS_OVERRIDE,
                           NULL);
@@@ -3982,8 -3878,7 +3982,8 @@@ static int selinux_kernel_create_files_
        u32 sid = current_sid();
        int ret;
  
 -      ret = avc_has_perm(sid, isec->sid,
 +      ret = avc_has_perm(&selinux_state,
 +                         sid, isec->sid,
                           SECCLASS_KERNEL_SERVICE,
                           KERNEL_SERVICE__CREATE_FILES_AS,
                           NULL);
@@@ -4000,8 -3895,7 +4000,8 @@@ static int selinux_kernel_module_reques
        ad.type = LSM_AUDIT_DATA_KMOD;
        ad.u.kmod_name = kmod_name;
  
 -      return avc_has_perm(current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), SECINITSID_KERNEL, SECCLASS_SYSTEM,
                            SYSTEM__MODULE_REQUEST, &ad);
  }
  
@@@ -4015,8 -3909,7 +4015,8 @@@ static int selinux_kernel_module_from_f
  
        /* init_module */
        if (file == NULL)
 -              return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
 +              return avc_has_perm(&selinux_state,
 +                                  sid, sid, SECCLASS_SYSTEM,
                                        SYSTEM__MODULE_LOAD, NULL);
  
        /* finit_module */
  
        fsec = file->f_security;
        if (sid != fsec->sid) {
 -              rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
                if (rc)
                        return rc;
        }
  
        isec = inode_security(file_inode(file));
 -      return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, SECCLASS_SYSTEM,
                                SYSTEM__MODULE_LOAD, &ad);
  }
  
@@@ -4056,22 -3947,19 +4056,22 @@@ static int selinux_kernel_read_file(str
  
  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__SETPGID, NULL);
  }
  
  static int selinux_task_getpgid(struct task_struct *p)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__GETPGID, NULL);
  }
  
  static int selinux_task_getsid(struct task_struct *p)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__GETSESSION, NULL);
  }
  
@@@ -4082,22 -3970,19 +4082,22 @@@ static void selinux_task_getsecid(struc
  
  static int selinux_task_setnice(struct task_struct *p, int nice)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
  }
  
  static int selinux_task_setioprio(struct task_struct *p, int ioprio)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
  }
  
  static int selinux_task_getioprio(struct task_struct *p)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__GETSCHED, NULL);
  }
  
@@@ -4112,8 -3997,7 +4112,8 @@@ static int selinux_task_prlimit(const s
                av |= PROCESS__SETRLIMIT;
        if (flags & LSM_PRLIMIT_READ)
                av |= PROCESS__GETRLIMIT;
 -      return avc_has_perm(cred_sid(cred), cred_sid(tcred),
 +      return avc_has_perm(&selinux_state,
 +                          cred_sid(cred), cred_sid(tcred),
                            SECCLASS_PROCESS, av, NULL);
  }
  
@@@ -4127,8 -4011,7 +4127,8 @@@ static int selinux_task_setrlimit(struc
           later be used as a safe reset point for the soft limit
           upon context transitions.  See selinux_bprm_committing_creds. */
        if (old_rlim->rlim_max != new_rlim->rlim_max)
 -              return avc_has_perm(current_sid(), task_sid(p),
 +              return avc_has_perm(&selinux_state,
 +                                  current_sid(), task_sid(p),
                                    SECCLASS_PROCESS, PROCESS__SETRLIMIT, NULL);
  
        return 0;
  
  static int selinux_task_setscheduler(struct task_struct *p)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
  }
  
  static int selinux_task_getscheduler(struct task_struct *p)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__GETSCHED, NULL);
  }
  
  static int selinux_task_movememory(struct task_struct *p)
  {
 -      return avc_has_perm(current_sid(), task_sid(p), SECCLASS_PROCESS,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), task_sid(p), SECCLASS_PROCESS,
                            PROCESS__SETSCHED, NULL);
  }
  
  static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
-                               int sig, u32 secid)
+                               int sig, const struct cred *cred)
  {
+       u32 secid;
        u32 perm;
  
        if (!sig)
                perm = PROCESS__SIGNULL; /* null signal; existence test */
        else
                perm = signal_to_av(sig);
-       if (!secid)
+       if (!cred)
                secid = current_sid();
 -      return avc_has_perm(secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
+       else
+               secid = cred_sid(cred);
 +      return avc_has_perm(&selinux_state,
 +                          secid, task_sid(p), SECCLASS_PROCESS, perm, NULL);
  }
  
  static void selinux_task_to_inode(struct task_struct *p,
@@@ -4255,23 -4137,6 +4258,23 @@@ static int selinux_parse_skb_ipv4(struc
                break;
        }
  
 +#if IS_ENABLED(CONFIG_IP_SCTP)
 +      case IPPROTO_SCTP: {
 +              struct sctphdr _sctph, *sh;
 +
 +              if (ntohs(ih->frag_off) & IP_OFFSET)
 +                      break;
 +
 +              offset += ihlen;
 +              sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
 +              if (sh == NULL)
 +                      break;
 +
 +              ad->u.net->sport = sh->source;
 +              ad->u.net->dport = sh->dest;
 +              break;
 +      }
 +#endif
        default:
                break;
        }
@@@ -4345,19 -4210,6 +4348,19 @@@ static int selinux_parse_skb_ipv6(struc
                break;
        }
  
 +#if IS_ENABLED(CONFIG_IP_SCTP)
 +      case IPPROTO_SCTP: {
 +              struct sctphdr _sctph, *sh;
 +
 +              sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
 +              if (sh == NULL)
 +                      break;
 +
 +              ad->u.net->sport = sh->source;
 +              ad->u.net->dport = sh->dest;
 +              break;
 +      }
 +#endif
        /* includes fragments */
        default:
                break;
@@@ -4438,8 -4290,7 +4441,8 @@@ static int selinux_skb_peerlbl_sid(stru
        if (unlikely(err))
                return -EACCES;
  
 -      err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
 +      err = security_net_peersid_resolve(&selinux_state, nlbl_sid,
 +                                         nlbl_type, xfrm_sid, sid);
        if (unlikely(err)) {
                printk(KERN_WARNING
                       "SELinux: failure in selinux_skb_peerlbl_sid(),"
@@@ -4467,8 -4318,7 +4470,8 @@@ static int selinux_conn_sid(u32 sk_sid
        int err = 0;
  
        if (skb_sid != SECSID_NULL)
 -              err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid);
 +              err = security_sid_mls_copy(&selinux_state, sk_sid, skb_sid,
 +                                          conn_sid);
        else
                *conn_sid = sk_sid;
  
@@@ -4485,8 -4335,8 +4488,8 @@@ static int socket_sockcreate_sid(const 
                return 0;
        }
  
 -      return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
 -                                     socksid);
 +      return security_transition_sid(&selinux_state, tsec->sid, tsec->sid,
 +                                     secclass, NULL, socksid);
  }
  
  static int sock_has_perm(struct sock *sk, u32 perms)
        ad.u.net = &net;
        ad.u.net->sk = sk;
  
 -      return avc_has_perm(current_sid(), sksec->sid, sksec->sclass, perms,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), sksec->sid, sksec->sclass, perms,
                            &ad);
  }
  
@@@ -4523,8 -4372,7 +4526,8 @@@ static int selinux_socket_create(int fa
        if (rc)
                return rc;
  
 -      return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
 +      return avc_has_perm(&selinux_state,
 +                          tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
  }
  
  static int selinux_socket_post_create(struct socket *sock, int family,
                sksec = sock->sk->sk_security;
                sksec->sclass = sclass;
                sksec->sid = sid;
 +              /* Allows detection of the first association on this socket */
 +              if (sksec->sclass == SECCLASS_SCTP_SOCKET)
 +                      sksec->sctp_assoc_state = SCTP_ASSOC_UNSET;
 +
                err = selinux_netlbl_socket_post_create(sock->sk, family);
        }
  
@@@ -4575,7 -4419,11 +4578,7 @@@ static int selinux_socket_bind(struct s
        if (err)
                goto out;
  
 -      /*
 -       * If PF_INET or PF_INET6, check name_bind permission for the port.
 -       * Multiple address binding for SCTP is not supported yet: we just
 -       * check the first address now.
 -       */
 +      /* If PF_INET or PF_INET6, check name_bind permission for the port. */
        family = sk->sk_family;
        if (family == PF_INET || family == PF_INET6) {
                char *addrp;
                unsigned short snum;
                u32 sid, node_perm;
  
 -              if (family == PF_INET) {
 -                      if (addrlen < sizeof(struct sockaddr_in)) {
 -                              err = -EINVAL;
 -                              goto out;
 -                      }
 +              /*
 +               * sctp_bindx(3) calls via selinux_sctp_bind_connect()
 +               * that validates multiple binding addresses. Because of this
 +               * need to check address->sa_family as it is possible to have
 +               * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
 +               */
 +              switch (address->sa_family) {
 +              case AF_INET:
 +                      if (addrlen < sizeof(struct sockaddr_in))
 +                              return -EINVAL;
                        addr4 = (struct sockaddr_in *)address;
                        snum = ntohs(addr4->sin_port);
                        addrp = (char *)&addr4->sin_addr.s_addr;
 -              } else {
 -                      if (addrlen < SIN6_LEN_RFC2133) {
 -                              err = -EINVAL;
 -                              goto out;
 -                      }
 +                      break;
 +              case AF_INET6:
 +                      if (addrlen < SIN6_LEN_RFC2133)
 +                              return -EINVAL;
                        addr6 = (struct sockaddr_in6 *)address;
                        snum = ntohs(addr6->sin6_port);
                        addrp = (char *)&addr6->sin6_addr.s6_addr;
 +                      break;
 +              default:
 +                      /* Note that SCTP services expect -EINVAL, whereas
 +                       * others expect -EAFNOSUPPORT.
 +                       */
 +                      if (sksec->sclass == SECCLASS_SCTP_SOCKET)
 +                              return -EINVAL;
 +                      else
 +                              return -EAFNOSUPPORT;
                }
  
                if (snum) {
                                ad.u.net = &net;
                                ad.u.net->sport = htons(snum);
                                ad.u.net->family = family;
 -                              err = avc_has_perm(sksec->sid, sid,
 +                              err = avc_has_perm(&selinux_state,
 +                                                 sksec->sid, sid,
                                                   sksec->sclass,
                                                   SOCKET__NAME_BIND, &ad);
                                if (err)
                        node_perm = DCCP_SOCKET__NODE_BIND;
                        break;
  
 +              case SECCLASS_SCTP_SOCKET:
 +                      node_perm = SCTP_SOCKET__NODE_BIND;
 +                      break;
 +
                default:
                        node_perm = RAWIP_SOCKET__NODE_BIND;
                        break;
                ad.u.net->sport = htons(snum);
                ad.u.net->family = family;
  
 -              if (family == PF_INET)
 +              if (address->sa_family == AF_INET)
                        ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
                else
                        ad.u.net->v6info.saddr = addr6->sin6_addr;
  
 -              err = avc_has_perm(sksec->sid, sid,
 +              err = avc_has_perm(&selinux_state,
 +                                 sksec->sid, sid,
                                   sksec->sclass, node_perm, &ad);
                if (err)
                        goto out;
        return err;
  }
  
 -static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
 +/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
 + * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt
 + */
 +static int selinux_socket_connect_helper(struct socket *sock,
 +                                       struct sockaddr *address, int addrlen)
  {
        struct sock *sk = sock->sk;
        struct sk_security_struct *sksec = sk->sk_security;
                return err;
  
        /*
 -       * If a TCP or DCCP socket, check name_connect permission for the port.
 +       * If a TCP, DCCP or SCTP socket, check name_connect permission
 +       * for the port.
         */
        if (sksec->sclass == SECCLASS_TCP_SOCKET ||
 -          sksec->sclass == SECCLASS_DCCP_SOCKET) {
 +          sksec->sclass == SECCLASS_DCCP_SOCKET ||
 +          sksec->sclass == SECCLASS_SCTP_SOCKET) {
                struct common_audit_data ad;
                struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                unsigned short snum;
                u32 sid, perm;
  
 -              if (sk->sk_family == PF_INET) {
 +              /* sctp_connectx(3) calls via selinux_sctp_bind_connect()
 +               * that validates multiple connect addresses. Because of this
 +               * need to check address->sa_family as it is possible to have
 +               * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
 +               */
 +              switch (address->sa_family) {
 +              case AF_INET:
                        addr4 = (struct sockaddr_in *)address;
                        if (addrlen < sizeof(struct sockaddr_in))
                                return -EINVAL;
                        snum = ntohs(addr4->sin_port);
 -              } else {
 +                      break;
 +              case AF_INET6:
                        addr6 = (struct sockaddr_in6 *)address;
                        if (addrlen < SIN6_LEN_RFC2133)
                                return -EINVAL;
                        snum = ntohs(addr6->sin6_port);
 +                      break;
 +              default:
 +                      /* Note that SCTP services expect -EINVAL, whereas
 +                       * others expect -EAFNOSUPPORT.
 +                       */
 +                      if (sksec->sclass == SECCLASS_SCTP_SOCKET)
 +                              return -EINVAL;
 +                      else
 +                              return -EAFNOSUPPORT;
                }
  
                err = sel_netport_sid(sk->sk_protocol, snum, &sid);
                if (err)
 -                      goto out;
 +                      return err;
  
 -              perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
 -                     TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
 +              switch (sksec->sclass) {
 +              case SECCLASS_TCP_SOCKET:
 +                      perm = TCP_SOCKET__NAME_CONNECT;
 +                      break;
 +              case SECCLASS_DCCP_SOCKET:
 +                      perm = DCCP_SOCKET__NAME_CONNECT;
 +                      break;
 +              case SECCLASS_SCTP_SOCKET:
 +                      perm = SCTP_SOCKET__NAME_CONNECT;
 +                      break;
 +              }
  
                ad.type = LSM_AUDIT_DATA_NET;
                ad.u.net = &net;
                ad.u.net->dport = htons(snum);
                ad.u.net->family = sk->sk_family;
 -              err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
 +              err = avc_has_perm(&selinux_state,
 +                                 sksec->sid, sid, sksec->sclass, perm, &ad);
                if (err)
 -                      goto out;
 +                      return err;
        }
  
 -      err = selinux_netlbl_socket_connect(sk, address);
 +      return 0;
 +}
  
 -out:
 -      return err;
 +/* Supports connect(2), see comments in selinux_socket_connect_helper() */
 +static int selinux_socket_connect(struct socket *sock,
 +                                struct sockaddr *address, int addrlen)
 +{
 +      int err;
 +      struct sock *sk = sock->sk;
 +
 +      err = selinux_socket_connect_helper(sock, address, addrlen);
 +      if (err)
 +              return err;
 +
 +      return selinux_netlbl_socket_connect(sk, address);
  }
  
  static int selinux_socket_listen(struct socket *sock, int backlog)
@@@ -4877,8 -4663,7 +4880,8 @@@ static int selinux_socket_unix_stream_c
        ad.u.net = &net;
        ad.u.net->sk = other;
  
 -      err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
 +      err = avc_has_perm(&selinux_state,
 +                         sksec_sock->sid, sksec_other->sid,
                           sksec_other->sclass,
                           UNIX_STREAM_SOCKET__CONNECTTO, &ad);
        if (err)
  
        /* server child socket */
        sksec_new->peer_sid = sksec_sock->sid;
 -      err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid,
 -                                  &sksec_new->sid);
 +      err = security_sid_mls_copy(&selinux_state, sksec_other->sid,
 +                                  sksec_sock->sid, &sksec_new->sid);
        if (err)
                return err;
  
@@@ -4909,8 -4694,7 +4912,8 @@@ static int selinux_socket_unix_may_send
        ad.u.net = &net;
        ad.u.net->sk = other->sk;
  
 -      return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
 +      return avc_has_perm(&selinux_state,
 +                          ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
                            &ad);
  }
  
@@@ -4925,8 -4709,7 +4928,8 @@@ static int selinux_inet_sys_rcv_skb(str
        err = sel_netif_sid(ns, ifindex, &if_sid);
        if (err)
                return err;
 -      err = avc_has_perm(peer_sid, if_sid,
 +      err = avc_has_perm(&selinux_state,
 +                         peer_sid, if_sid,
                           SECCLASS_NETIF, NETIF__INGRESS, ad);
        if (err)
                return err;
        err = sel_netnode_sid(addrp, family, &node_sid);
        if (err)
                return err;
 -      return avc_has_perm(peer_sid, node_sid,
 +      return avc_has_perm(&selinux_state,
 +                          peer_sid, node_sid,
                            SECCLASS_NODE, NODE__RECVFROM, ad);
  }
  
@@@ -4958,8 -4740,7 +4961,8 @@@ static int selinux_sock_rcv_skb_compat(
                return err;
  
        if (selinux_secmark_enabled()) {
 -              err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
 +              err = avc_has_perm(&selinux_state,
 +                                 sk_sid, skb->secmark, SECCLASS_PACKET,
                                   PACKET__RECV, &ad);
                if (err)
                        return err;
@@@ -4996,7 -4777,7 +4999,7 @@@ static int selinux_socket_sock_rcv_skb(
         * to the selinux_sock_rcv_skb_compat() function to deal with the
         * special handling.  We do this in an attempt to keep this function
         * as fast and as clean as possible. */
 -      if (!selinux_policycap_netpeer)
 +      if (!selinux_policycap_netpeer())
                return selinux_sock_rcv_skb_compat(sk, skb, family);
  
        secmark_active = selinux_secmark_enabled();
                        selinux_netlbl_err(skb, family, err, 0);
                        return err;
                }
 -              err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
 +              err = avc_has_perm(&selinux_state,
 +                                 sk_sid, peer_sid, SECCLASS_PEER,
                                   PEER__RECV, &ad);
                if (err) {
                        selinux_netlbl_err(skb, family, err, 0);
        }
  
        if (secmark_active) {
 -              err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
 +              err = avc_has_perm(&selinux_state,
 +                                 sk_sid, skb->secmark, SECCLASS_PACKET,
                                   PACKET__RECV, &ad);
                if (err)
                        return err;
@@@ -5054,14 -4833,12 +5057,14 @@@ static int selinux_socket_getpeersec_st
        u32 peer_sid = SECSID_NULL;
  
        if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
 -          sksec->sclass == SECCLASS_TCP_SOCKET)
 +          sksec->sclass == SECCLASS_TCP_SOCKET ||
 +          sksec->sclass == SECCLASS_SCTP_SOCKET)
                peer_sid = sksec->peer_sid;
        if (peer_sid == SECSID_NULL)
                return -ENOPROTOOPT;
  
 -      err = security_sid_to_context(peer_sid, &scontext, &scontext_len);
 +      err = security_sid_to_context(&selinux_state, peer_sid, &scontext,
 +                                    &scontext_len);
        if (err)
                return err;
  
@@@ -5169,172 -4946,6 +5172,172 @@@ static void selinux_sock_graft(struct s
        sksec->sclass = isec->sclass;
  }
  
 +/* Called whenever SCTP receives an INIT chunk. This happens when an incoming
 + * connect(2), sctp_connectx(3) or sctp_sendmsg(3) (with no association
 + * already present).
 + */
 +static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
 +                                    struct sk_buff *skb)
 +{
 +      struct sk_security_struct *sksec = ep->base.sk->sk_security;
 +      struct common_audit_data ad;
 +      struct lsm_network_audit net = {0,};
 +      u8 peerlbl_active;
 +      u32 peer_sid = SECINITSID_UNLABELED;
 +      u32 conn_sid;
 +      int err = 0;
 +
 +      if (!selinux_policycap_extsockclass())
 +              return 0;
 +
 +      peerlbl_active = selinux_peerlbl_enabled();
 +
 +      if (peerlbl_active) {
 +              /* This will return peer_sid = SECSID_NULL if there are
 +               * no peer labels, see security_net_peersid_resolve().
 +               */
 +              err = selinux_skb_peerlbl_sid(skb, ep->base.sk->sk_family,
 +                                            &peer_sid);
 +              if (err)
 +                      return err;
 +
 +              if (peer_sid == SECSID_NULL)
 +                      peer_sid = SECINITSID_UNLABELED;
 +      }
 +
 +      if (sksec->sctp_assoc_state == SCTP_ASSOC_UNSET) {
 +              sksec->sctp_assoc_state = SCTP_ASSOC_SET;
 +
 +              /* Here as first association on socket. As the peer SID
 +               * was allowed by peer recv (and the netif/node checks),
 +               * then it is approved by policy and used as the primary
 +               * peer SID for getpeercon(3).
 +               */
 +              sksec->peer_sid = peer_sid;
 +      } else if  (sksec->peer_sid != peer_sid) {
 +              /* Other association peer SIDs are checked to enforce
 +               * consistency among the peer SIDs.
 +               */
 +              ad.type = LSM_AUDIT_DATA_NET;
 +              ad.u.net = &net;
 +              ad.u.net->sk = ep->base.sk;
 +              err = avc_has_perm(&selinux_state,
 +                                 sksec->peer_sid, peer_sid, sksec->sclass,
 +                                 SCTP_SOCKET__ASSOCIATION, &ad);
 +              if (err)
 +                      return err;
 +      }
 +
 +      /* Compute the MLS component for the connection and store
 +       * the information in ep. This will be used by SCTP TCP type
 +       * sockets and peeled off connections as they cause a new
 +       * socket to be generated. selinux_sctp_sk_clone() will then
 +       * plug this into the new socket.
 +       */
 +      err = selinux_conn_sid(sksec->sid, peer_sid, &conn_sid);
 +      if (err)
 +              return err;
 +
 +      ep->secid = conn_sid;
 +      ep->peer_secid = peer_sid;
 +
 +      /* Set any NetLabel labels including CIPSO/CALIPSO options. */
 +      return selinux_netlbl_sctp_assoc_request(ep, skb);
 +}
 +
 +/* Check if sctp IPv4/IPv6 addresses are valid for binding or connecting
 + * based on their @optname.
 + */
 +static int selinux_sctp_bind_connect(struct sock *sk, int optname,
 +                                   struct sockaddr *address,
 +                                   int addrlen)
 +{
 +      int len, err = 0, walk_size = 0;
 +      void *addr_buf;
 +      struct sockaddr *addr;
 +      struct socket *sock;
 +
 +      if (!selinux_policycap_extsockclass())
 +              return 0;
 +
 +      /* Process one or more addresses that may be IPv4 or IPv6 */
 +      sock = sk->sk_socket;
 +      addr_buf = address;
 +
 +      while (walk_size < addrlen) {
 +              addr = addr_buf;
 +              switch (addr->sa_family) {
 +              case AF_INET:
 +                      len = sizeof(struct sockaddr_in);
 +                      break;
 +              case AF_INET6:
 +                      len = sizeof(struct sockaddr_in6);
 +                      break;
 +              default:
 +                      return -EAFNOSUPPORT;
 +              }
 +
 +              err = -EINVAL;
 +              switch (optname) {
 +              /* Bind checks */
 +              case SCTP_PRIMARY_ADDR:
 +              case SCTP_SET_PEER_PRIMARY_ADDR:
 +              case SCTP_SOCKOPT_BINDX_ADD:
 +                      err = selinux_socket_bind(sock, addr, len);
 +                      break;
 +              /* Connect checks */
 +              case SCTP_SOCKOPT_CONNECTX:
 +              case SCTP_PARAM_SET_PRIMARY:
 +              case SCTP_PARAM_ADD_IP:
 +              case SCTP_SENDMSG_CONNECT:
 +                      err = selinux_socket_connect_helper(sock, addr, len);
 +                      if (err)
 +                              return err;
 +
 +                      /* As selinux_sctp_bind_connect() is called by the
 +                       * SCTP protocol layer, the socket is already locked,
 +                       * therefore selinux_netlbl_socket_connect_locked() is
 +                       * is called here. The situations handled are:
 +                       * sctp_connectx(3), sctp_sendmsg(3), sendmsg(2),
 +                       * whenever a new IP address is added or when a new
 +                       * primary address is selected.
 +                       * Note that an SCTP connect(2) call happens before
 +                       * the SCTP protocol layer and is handled via
 +                       * selinux_socket_connect().
 +                       */
 +                      err = selinux_netlbl_socket_connect_locked(sk, addr);
 +                      break;
 +              }
 +
 +              if (err)
 +                      return err;
 +
 +              addr_buf += len;
 +              walk_size += len;
 +      }
 +
 +      return 0;
 +}
 +
 +/* Called whenever a new socket is created by accept(2) or sctp_peeloff(3). */
 +static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
 +                                struct sock *newsk)
 +{
 +      struct sk_security_struct *sksec = sk->sk_security;
 +      struct sk_security_struct *newsksec = newsk->sk_security;
 +
 +      /* If policy does not support SECCLASS_SCTP_SOCKET then call
 +       * the non-sctp clone version.
 +       */
 +      if (!selinux_policycap_extsockclass())
 +              return selinux_sk_clone_security(sk, newsk);
 +
 +      newsksec->sid = ep->secid;
 +      newsksec->peer_sid = ep->peer_secid;
 +      newsksec->sclass = sksec->sclass;
 +      selinux_netlbl_sctp_sk_clone(sk, newsk);
 +}
 +
  static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
                                     struct request_sock *req)
  {
@@@ -5393,9 -5004,7 +5396,9 @@@ static int selinux_secmark_relabel_pack
        __tsec = current_security();
        tsid = __tsec->sid;
  
 -      return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL);
 +      return avc_has_perm(&selinux_state,
 +                          tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO,
 +                          NULL);
  }
  
  static void selinux_secmark_refcount_inc(void)
@@@ -5443,8 -5052,7 +5446,8 @@@ static int selinux_tun_dev_create(void
         * connections unlike traditional sockets - check the TUN driver to
         * get a better understanding of why this socket is special */
  
 -      return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
 +      return avc_has_perm(&selinux_state,
 +                          sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE,
                            NULL);
  }
  
@@@ -5452,8 -5060,7 +5455,8 @@@ static int selinux_tun_dev_attach_queue
  {
        struct tun_security_struct *tunsec = security;
  
 -      return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
 +      return avc_has_perm(&selinux_state,
 +                          current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
                            TUN_SOCKET__ATTACH_QUEUE, NULL);
  }
  
@@@ -5481,13 -5088,11 +5484,13 @@@ static int selinux_tun_dev_open(void *s
        u32 sid = current_sid();
        int err;
  
 -      err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
 +      err = avc_has_perm(&selinux_state,
 +                         sid, tunsec->sid, SECCLASS_TUN_SOCKET,
                           TUN_SOCKET__RELABELFROM, NULL);
        if (err)
                return err;
 -      err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET,
 +      err = avc_has_perm(&selinux_state,
 +                         sid, sid, SECCLASS_TUN_SOCKET,
                           TUN_SOCKET__RELABELTO, NULL);
        if (err)
                return err;
@@@ -5518,8 -5123,7 +5521,8 @@@ static int selinux_nlmsg_perm(struct so
                               sk->sk_protocol, nlh->nlmsg_type,
                               secclass_map[sksec->sclass - 1].name,
                               task_pid_nr(current), current->comm);
 -                      if (!selinux_enforcing || security_get_allow_unknown())
 +                      if (!enforcing_enabled(&selinux_state) ||
 +                          security_get_allow_unknown(&selinux_state))
                                err = 0;
                }
  
@@@ -5549,7 -5153,7 +5552,7 @@@ static unsigned int selinux_ip_forward(
        u8 netlbl_active;
        u8 peerlbl_active;
  
 -      if (!selinux_policycap_netpeer)
 +      if (!selinux_policycap_netpeer())
                return NF_ACCEPT;
  
        secmark_active = selinux_secmark_enabled();
        }
  
        if (secmark_active)
 -              if (avc_has_perm(peer_sid, skb->secmark,
 +              if (avc_has_perm(&selinux_state,
 +                               peer_sid, skb->secmark,
                                 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
                        return NF_DROP;
  
@@@ -5691,8 -5294,7 +5694,8 @@@ static unsigned int selinux_ip_postrout
                return NF_DROP;
  
        if (selinux_secmark_enabled())
 -              if (avc_has_perm(sksec->sid, skb->secmark,
 +              if (avc_has_perm(&selinux_state,
 +                               sksec->sid, skb->secmark,
                                 SECCLASS_PACKET, PACKET__SEND, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
  
@@@ -5720,7 -5322,7 +5723,7 @@@ static unsigned int selinux_ip_postrout
         * to the selinux_ip_postroute_compat() function to deal with the
         * special handling.  We do this in an attempt to keep this function
         * as fast and as clean as possible. */
 -      if (!selinux_policycap_netpeer)
 +      if (!selinux_policycap_netpeer())
                return selinux_ip_postroute_compat(skb, ifindex, family);
  
        secmark_active = selinux_secmark_enabled();
                return NF_DROP;
  
        if (secmark_active)
 -              if (avc_has_perm(peer_sid, skb->secmark,
 +              if (avc_has_perm(&selinux_state,
 +                               peer_sid, skb->secmark,
                                 SECCLASS_PACKET, secmark_perm, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
  
  
                if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
                        return NF_DROP;
 -              if (avc_has_perm(peer_sid, if_sid,
 +              if (avc_has_perm(&selinux_state,
 +                               peer_sid, if_sid,
                                 SECCLASS_NETIF, NETIF__EGRESS, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
  
                if (sel_netnode_sid(addrp, family, &node_sid))
                        return NF_DROP;
 -              if (avc_has_perm(peer_sid, node_sid,
 +              if (avc_has_perm(&selinux_state,
 +                               peer_sid, node_sid,
                                 SECCLASS_NODE, NODE__SENDTO, &ad))
                        return NF_DROP_ERR(-ECONNREFUSED);
        }
@@@ -5922,8 -5521,7 +5925,8 @@@ static int ipc_has_perm(struct kern_ipc
        ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = ipc_perms->key;
  
 -      return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, isec->sclass, perms, &ad);
  }
  
  static int selinux_msg_msg_alloc_security(struct msg_msg *msg)
@@@ -5937,54 -5535,52 +5940,54 @@@ static void selinux_msg_msg_free_securi
  }
  
  /* message queue security operations */
 -static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
 +static int selinux_msg_queue_alloc_security(struct kern_ipc_perm *msq)
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
        int rc;
  
 -      rc = ipc_alloc_security(&msq->q_perm, SECCLASS_MSGQ);
 +      rc = ipc_alloc_security(msq, SECCLASS_MSGQ);
        if (rc)
                return rc;
  
 -      isec = msq->q_perm.security;
 +      isec = msq->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = msq->q_perm.key;
 +      ad.u.ipc_id = msq->key;
  
 -      rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__CREATE, &ad);
        if (rc) {
 -              ipc_free_security(&msq->q_perm);
 +              ipc_free_security(msq);
                return rc;
        }
        return 0;
  }
  
 -static void selinux_msg_queue_free_security(struct msg_queue *msq)
 +static void selinux_msg_queue_free_security(struct kern_ipc_perm *msq)
  {
 -      ipc_free_security(&msq->q_perm);
 +      ipc_free_security(msq);
  }
  
 -static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
 +static int selinux_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
  
 -      isec = msq->q_perm.security;
 +      isec = msq->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = msq->q_perm.key;
 +      ad.u.ipc_id = msq->key;
  
 -      return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, SECCLASS_MSGQ,
                            MSGQ__ASSOCIATE, &ad);
  }
  
 -static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
 +static int selinux_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
  {
        int err;
        int perms;
        case IPC_INFO:
        case MSG_INFO:
                /* No specific object, just general system-wide information. */
 -              return avc_has_perm(current_sid(), SECINITSID_KERNEL,
 +              return avc_has_perm(&selinux_state,
 +                                  current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
        case IPC_STAT:
        case MSG_STAT:
                return 0;
        }
  
 -      err = ipc_has_perm(&msq->q_perm, perms);
 +      err = ipc_has_perm(msq, perms);
        return err;
  }
  
 -static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, int msqflg)
 +static int selinux_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg)
  {
        struct ipc_security_struct *isec;
        struct msg_security_struct *msec;
        u32 sid = current_sid();
        int rc;
  
 -      isec = msq->q_perm.security;
 +      isec = msq->security;
        msec = msg->security;
  
        /*
                 * Compute new sid based on current process and
                 * message queue this message will be stored in
                 */
 -              rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
 -                                           NULL, &msec->sid);
 +              rc = security_transition_sid(&selinux_state, sid, isec->sid,
 +                                           SECCLASS_MSG, NULL, &msec->sid);
                if (rc)
                        return rc;
        }
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = msq->q_perm.key;
 +      ad.u.ipc_id = msq->key;
  
        /* Can this process write to the queue? */
 -      rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__WRITE, &ad);
        if (!rc)
                /* Can this process send the message */
 -              rc = avc_has_perm(sid, msec->sid, SECCLASS_MSG,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, msec->sid, SECCLASS_MSG,
                                  MSG__SEND, &ad);
        if (!rc)
                /* Can the message be put in the queue? */
 -              rc = avc_has_perm(msec->sid, isec->sid, SECCLASS_MSGQ,
 +              rc = avc_has_perm(&selinux_state,
 +                                msec->sid, isec->sid, SECCLASS_MSGQ,
                                  MSGQ__ENQUEUE, &ad);
  
        return rc;
  }
  
 -static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
 +static int selinux_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
                                    struct task_struct *target,
                                    long type, int mode)
  {
        u32 sid = task_sid(target);
        int rc;
  
 -      isec = msq->q_perm.security;
 +      isec = msq->security;
        msec = msg->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = msq->q_perm.key;
 +      ad.u.ipc_id = msq->key;
  
 -      rc = avc_has_perm(sid, isec->sid,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid,
                          SECCLASS_MSGQ, MSGQ__READ, &ad);
        if (!rc)
 -              rc = avc_has_perm(sid, msec->sid,
 +              rc = avc_has_perm(&selinux_state,
 +                                sid, msec->sid,
                                  SECCLASS_MSG, MSG__RECEIVE, &ad);
        return rc;
  }
  
  /* Shared Memory security operations */
 -static int selinux_shm_alloc_security(struct shmid_kernel *shp)
 +static int selinux_shm_alloc_security(struct kern_ipc_perm *shp)
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
        int rc;
  
 -      rc = ipc_alloc_security(&shp->shm_perm, SECCLASS_SHM);
 +      rc = ipc_alloc_security(shp, SECCLASS_SHM);
        if (rc)
                return rc;
  
 -      isec = shp->shm_perm.security;
 +      isec = shp->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = shp->shm_perm.key;
 +      ad.u.ipc_id = shp->key;
  
 -      rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid, SECCLASS_SHM,
                          SHM__CREATE, &ad);
        if (rc) {
 -              ipc_free_security(&shp->shm_perm);
 +              ipc_free_security(shp);
                return rc;
        }
        return 0;
  }
  
 -static void selinux_shm_free_security(struct shmid_kernel *shp)
 +static void selinux_shm_free_security(struct kern_ipc_perm *shp)
  {
 -      ipc_free_security(&shp->shm_perm);
 +      ipc_free_security(shp);
  }
  
 -static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
 +static int selinux_shm_associate(struct kern_ipc_perm *shp, int shmflg)
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
  
 -      isec = shp->shm_perm.security;
 +      isec = shp->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = shp->shm_perm.key;
 +      ad.u.ipc_id = shp->key;
  
 -      return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, SECCLASS_SHM,
                            SHM__ASSOCIATE, &ad);
  }
  
  /* Note, at this point, shp is locked down */
 -static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
 +static int selinux_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
  {
        int perms;
        int err;
        case IPC_INFO:
        case SHM_INFO:
                /* No specific object, just general system-wide information. */
 -              return avc_has_perm(current_sid(), SECINITSID_KERNEL,
 +              return avc_has_perm(&selinux_state,
 +                                  current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
        case IPC_STAT:
        case SHM_STAT:
                return 0;
        }
  
 -      err = ipc_has_perm(&shp->shm_perm, perms);
 +      err = ipc_has_perm(shp, perms);
        return err;
  }
  
 -static int selinux_shm_shmat(struct shmid_kernel *shp,
 +static int selinux_shm_shmat(struct kern_ipc_perm *shp,
                             char __user *shmaddr, int shmflg)
  {
        u32 perms;
        else
                perms = SHM__READ | SHM__WRITE;
  
 -      return ipc_has_perm(&shp->shm_perm, perms);
 +      return ipc_has_perm(shp, perms);
  }
  
  /* Semaphore security operations */
 -static int selinux_sem_alloc_security(struct sem_array *sma)
 +static int selinux_sem_alloc_security(struct kern_ipc_perm *sma)
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
        int rc;
  
 -      rc = ipc_alloc_security(&sma->sem_perm, SECCLASS_SEM);
 +      rc = ipc_alloc_security(sma, SECCLASS_SEM);
        if (rc)
                return rc;
  
 -      isec = sma->sem_perm.security;
 +      isec = sma->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = sma->sem_perm.key;
 +      ad.u.ipc_id = sma->key;
  
 -      rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
 +      rc = avc_has_perm(&selinux_state,
 +                        sid, isec->sid, SECCLASS_SEM,
                          SEM__CREATE, &ad);
        if (rc) {
 -              ipc_free_security(&sma->sem_perm);
 +              ipc_free_security(sma);
                return rc;
        }
        return 0;
  }
  
 -static void selinux_sem_free_security(struct sem_array *sma)
 +static void selinux_sem_free_security(struct kern_ipc_perm *sma)
  {
 -      ipc_free_security(&sma->sem_perm);
 +      ipc_free_security(sma);
  }
  
 -static int selinux_sem_associate(struct sem_array *sma, int semflg)
 +static int selinux_sem_associate(struct kern_ipc_perm *sma, int semflg)
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
        u32 sid = current_sid();
  
 -      isec = sma->sem_perm.security;
 +      isec = sma->security;
  
        ad.type = LSM_AUDIT_DATA_IPC;
 -      ad.u.ipc_id = sma->sem_perm.key;
 +      ad.u.ipc_id = sma->key;
  
 -      return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
 +      return avc_has_perm(&selinux_state,
 +                          sid, isec->sid, SECCLASS_SEM,
                            SEM__ASSOCIATE, &ad);
  }
  
  /* Note, at this point, sma is locked down */
 -static int selinux_sem_semctl(struct sem_array *sma, int cmd)
 +static int selinux_sem_semctl(struct kern_ipc_perm *sma, int cmd)
  {
        int err;
        u32 perms;
        case IPC_INFO:
        case SEM_INFO:
                /* No specific object, just general system-wide information. */
 -              return avc_has_perm(current_sid(), SECINITSID_KERNEL,
 +              return avc_has_perm(&selinux_state,
 +                                  current_sid(), SECINITSID_KERNEL,
                                    SECCLASS_SYSTEM, SYSTEM__IPC_INFO, NULL);
        case GETPID:
        case GETNCNT:
                return 0;
        }
  
 -      err = ipc_has_perm(&sma->sem_perm, perms);
 +      err = ipc_has_perm(sma, perms);
        return err;
  }
  
 -static int selinux_sem_semop(struct sem_array *sma,
 +static int selinux_sem_semop(struct kern_ipc_perm *sma,
                             struct sembuf *sops, unsigned nsops, int alter)
  {
        u32 perms;
        else
                perms = SEM__READ;
  
 -      return ipc_has_perm(&sma->sem_perm, perms);
 +      return ipc_has_perm(sma, perms);
  }
  
  static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
@@@ -6327,8 -5911,7 +6330,8 @@@ static int selinux_getprocattr(struct t
        __tsec = __task_cred(p)->security;
  
        if (current != p) {
 -              error = avc_has_perm(current_sid(), __tsec->sid,
 +              error = avc_has_perm(&selinux_state,
 +                                   current_sid(), __tsec->sid,
                                     SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
                if (error)
                        goto bad;
        if (!sid)
                return 0;
  
 -      error = security_sid_to_context(sid, value, &len);
 +      error = security_sid_to_context(&selinux_state, sid, value, &len);
        if (error)
                return error;
        return len;
@@@ -6377,24 -5960,19 +6380,24 @@@ static int selinux_setprocattr(const ch
         * Basic control over ability to set these attributes at all.
         */
        if (!strcmp(name, "exec"))
 -              error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
 +              error = avc_has_perm(&selinux_state,
 +                                   mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETEXEC, NULL);
        else if (!strcmp(name, "fscreate"))
 -              error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
 +              error = avc_has_perm(&selinux_state,
 +                                   mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETFSCREATE, NULL);
        else if (!strcmp(name, "keycreate"))
 -              error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
 +              error = avc_has_perm(&selinux_state,
 +                                   mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETKEYCREATE, NULL);
        else if (!strcmp(name, "sockcreate"))
 -              error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
 +              error = avc_has_perm(&selinux_state,
 +                                   mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETSOCKCREATE, NULL);
        else if (!strcmp(name, "current"))
 -              error = avc_has_perm(mysid, mysid, SECCLASS_PROCESS,
 +              error = avc_has_perm(&selinux_state,
 +                                   mysid, mysid, SECCLASS_PROCESS,
                                     PROCESS__SETCURRENT, NULL);
        else
                error = -EINVAL;
                        str[size-1] = 0;
                        size--;
                }
 -              error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
 +              error = security_context_to_sid(&selinux_state, value, size,
 +                                              &sid, GFP_KERNEL);
                if (error == -EINVAL && !strcmp(name, "fscreate")) {
                        if (!has_cap_mac_admin(true)) {
                                struct audit_buffer *ab;
  
                                return error;
                        }
 -                      error = security_context_to_sid_force(value, size,
 -                                                            &sid);
 +                      error = security_context_to_sid_force(
 +                                                    &selinux_state,
 +                                                    value, size, &sid);
                }
                if (error)
                        return error;
        } else if (!strcmp(name, "fscreate")) {
                tsec->create_sid = sid;
        } else if (!strcmp(name, "keycreate")) {
 -              error = avc_has_perm(mysid, sid, SECCLASS_KEY, KEY__CREATE,
 +              error = avc_has_perm(&selinux_state,
 +                                   mysid, sid, SECCLASS_KEY, KEY__CREATE,
                                     NULL);
                if (error)
                        goto abort_change;
                /* Only allow single threaded processes to change context */
                error = -EPERM;
                if (!current_is_single_threaded()) {
 -                      error = security_bounded_transition(tsec->sid, sid);
 +                      error = security_bounded_transition(&selinux_state,
 +                                                          tsec->sid, sid);
                        if (error)
                                goto abort_change;
                }
  
                /* Check permissions for the transition. */
 -              error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
 +              error = avc_has_perm(&selinux_state,
 +                                   tsec->sid, sid, SECCLASS_PROCESS,
                                     PROCESS__DYNTRANSITION, NULL);
                if (error)
                        goto abort_change;
                   Otherwise, leave SID unchanged and fail. */
                ptsid = ptrace_parent_sid();
                if (ptsid != 0) {
 -                      error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS,
 +                      error = avc_has_perm(&selinux_state,
 +                                           ptsid, sid, SECCLASS_PROCESS,
                                             PROCESS__PTRACE, NULL);
                        if (error)
                                goto abort_change;
@@@ -6512,14 -6084,12 +6515,14 @@@ static int selinux_ismaclabel(const cha
  
  static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  {
 -      return security_sid_to_context(secid, secdata, seclen);
 +      return security_sid_to_context(&selinux_state, secid,
 +                                     secdata, seclen);
  }
  
  static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
  {
 -      return security_context_to_sid(secdata, seclen, secid, GFP_KERNEL);
 +      return security_context_to_sid(&selinux_state, secdata, seclen,
 +                                     secid, GFP_KERNEL);
  }
  
  static void selinux_release_secctx(char *secdata, u32 seclen)
@@@ -6611,8 -6181,7 +6614,8 @@@ static int selinux_key_permission(key_r
        key = key_ref_to_ptr(key_ref);
        ksec = key->security;
  
 -      return avc_has_perm(sid, ksec->sid, SECCLASS_KEY, perm, NULL);
 +      return avc_has_perm(&selinux_state,
 +                          sid, ksec->sid, SECCLASS_KEY, perm, NULL);
  }
  
  static int selinux_key_getsecurity(struct key *key, char **_buffer)
        unsigned len;
        int rc;
  
 -      rc = security_sid_to_context(ksec->sid, &context, &len);
 +      rc = security_sid_to_context(&selinux_state, ksec->sid,
 +                                   &context, &len);
        if (!rc)
                rc = len;
        *_buffer = context;
@@@ -6648,8 -6216,7 +6651,8 @@@ static int selinux_ib_pkey_access(void 
        ibpkey.subnet_prefix = subnet_prefix;
        ibpkey.pkey = pkey_val;
        ad.u.ibpkey = &ibpkey;
 -      return avc_has_perm(sec->sid, sid,
 +      return avc_has_perm(&selinux_state,
 +                          sec->sid, sid,
                            SECCLASS_INFINIBAND_PKEY,
                            INFINIBAND_PKEY__ACCESS, &ad);
  }
@@@ -6663,8 -6230,7 +6666,8 @@@ static int selinux_ib_endport_manage_su
        struct ib_security_struct *sec = ib_sec;
        struct lsm_ibendport_audit ibendport;
  
 -      err = security_ib_endport_sid(dev_name, port_num, &sid);
 +      err = security_ib_endport_sid(&selinux_state, dev_name, port_num,
 +                                    &sid);
  
        if (err)
                return err;
        strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
        ibendport.port = port_num;
        ad.u.ibendport = &ibendport;
 -      return avc_has_perm(sec->sid, sid,
 +      return avc_has_perm(&selinux_state,
 +                          sec->sid, sid,
                            SECCLASS_INFINIBAND_ENDPORT,
                            INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
  }
@@@ -6707,13 -6272,11 +6710,13 @@@ static int selinux_bpf(int cmd, union b
  
        switch (cmd) {
        case BPF_MAP_CREATE:
 -              ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
 +              ret = avc_has_perm(&selinux_state,
 +                                 sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
                                   NULL);
                break;
        case BPF_PROG_LOAD:
 -              ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
 +              ret = avc_has_perm(&selinux_state,
 +                                 sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
                                   NULL);
                break;
        default:
@@@ -6753,16 -6316,14 +6756,16 @@@ static int bpf_fd_pass(struct file *fil
        if (file->f_op == &bpf_map_fops) {
                map = file->private_data;
                bpfsec = map->security;
 -              ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
 +              ret = avc_has_perm(&selinux_state,
 +                                 sid, bpfsec->sid, SECCLASS_BPF,
                                   bpf_map_fmode_to_av(file->f_mode), NULL);
                if (ret)
                        return ret;
        } else if (file->f_op == &bpf_prog_fops) {
                prog = file->private_data;
                bpfsec = prog->aux->security;
 -              ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
 +              ret = avc_has_perm(&selinux_state,
 +                                 sid, bpfsec->sid, SECCLASS_BPF,
                                   BPF__PROG_RUN, NULL);
                if (ret)
                        return ret;
@@@ -6776,8 -6337,7 +6779,8 @@@ static int selinux_bpf_map(struct bpf_m
        struct bpf_security_struct *bpfsec;
  
        bpfsec = map->security;
 -      return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
 +      return avc_has_perm(&selinux_state,
 +                          sid, bpfsec->sid, SECCLASS_BPF,
                            bpf_map_fmode_to_av(fmode), NULL);
  }
  
@@@ -6787,8 -6347,7 +6790,8 @@@ static int selinux_bpf_prog(struct bpf_
        struct bpf_security_struct *bpfsec;
  
        bpfsec = prog->aux->security;
 -      return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
 +      return avc_has_perm(&selinux_state,
 +                          sid, bpfsec->sid, SECCLASS_BPF,
                            BPF__PROG_RUN, NULL);
  }
  
@@@ -7007,9 -6566,6 +7010,9 @@@ static struct security_hook_list selinu
        LSM_HOOK_INIT(sk_clone_security, selinux_sk_clone_security),
        LSM_HOOK_INIT(sk_getsecid, selinux_sk_getsecid),
        LSM_HOOK_INIT(sock_graft, selinux_sock_graft),
 +      LSM_HOOK_INIT(sctp_assoc_request, selinux_sctp_assoc_request),
 +      LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
 +      LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
        LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
        LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
        LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
@@@ -7085,12 -6641,6 +7088,12 @@@ static __init int selinux_init(void
  
        printk(KERN_INFO "SELinux:  Initializing.\n");
  
 +      memset(&selinux_state, 0, sizeof(selinux_state));
 +      enforcing_set(&selinux_state, selinux_enforcing_boot);
 +      selinux_state.checkreqprot = selinux_checkreqprot_boot;
 +      selinux_ss_init(&selinux_state.ss);
 +      selinux_avc_init(&selinux_state.avc);
 +
        /* Set the security state for the initial task. */
        cred_init_security();
  
                                            0, SLAB_PANIC, NULL);
        avc_init();
  
 +      avtab_cache_init();
 +
 +      ebitmap_cache_init();
 +
 +      hashtab_cache_init();
 +
        security_add_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks), "selinux");
  
        if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
        if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
                panic("SELinux: Unable to register AVC LSM notifier callback\n");
  
 -      if (selinux_enforcing)
 +      if (selinux_enforcing_boot)
                printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
        else
                printk(KERN_DEBUG "SELinux:  Starting in permissive mode\n");
@@@ -7239,22 -6783,23 +7242,22 @@@ static void selinux_nf_ip_exit(void
  #endif /* CONFIG_NETFILTER */
  
  #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 -static int selinux_disabled;
 -
 -int selinux_disable(void)
 +int selinux_disable(struct selinux_state *state)
  {
 -      if (ss_initialized) {
 +      if (state->initialized) {
                /* Not permitted after initial policy load. */
                return -EINVAL;
        }
  
 -      if (selinux_disabled) {
 +      if (state->disabled) {
                /* Only do this once. */
                return -EINVAL;
        }
  
 +      state->disabled = 1;
 +
        printk(KERN_INFO "SELinux:  Disabled at runtime.\n");
  
 -      selinux_disabled = 1;
        selinux_enabled = 0;
  
        security_delete_hooks(selinux_hooks, ARRAY_SIZE(selinux_hooks));
@@@ -2228,15 -2228,13 +2228,13 @@@ static int smack_task_movememory(struc
   * @p: the task object
   * @info: unused
   * @sig: unused
-  * @secid: identifies the smack to use in lieu of current's
+  * @cred: identifies the cred to use in lieu of current's
   *
   * Return 0 if write access is permitted
   *
-  * The secid behavior is an artifact of an SELinux hack
-  * in the USB code. Someday it may go away.
   */
  static int smack_task_kill(struct task_struct *p, struct siginfo *info,
-                          int sig, u32 secid)
+                          int sig, const struct cred *cred)
  {
        struct smk_audit_info ad;
        struct smack_known *skp;
         * Sending a signal requires that the sender
         * can write the receiver.
         */
-       if (secid == 0) {
+       if (cred == NULL) {
                rc = smk_curacc(tkp, MAY_DELIVER, &ad);
                rc = smk_bu_task(p, MAY_DELIVER, rc);
                return rc;
        }
        /*
-        * If the secid isn't 0 we're dealing with some USB IO
+        * If the cred isn't NULL we're dealing with some USB IO
         * specific behavior. This is not clean. For one thing
         * we can't take privilege into account.
         */
-       skp = smack_from_secid(secid);
+       skp = smk_of_task(cred->security);
        rc = smk_access(skp, tkp, MAY_DELIVER, &ad);
        rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc);
        return rc;
@@@ -2945,24 -2943,25 +2943,24 @@@ static void smack_msg_msg_free_security
  }
  
  /**
 - * smack_of_shm - the smack pointer for the shm
 - * @shp: the object
 + * smack_of_ipc - the smack pointer for the ipc
 + * @isp: the object
   *
   * Returns a pointer to the smack value
   */
 -static struct smack_known *smack_of_shm(struct shmid_kernel *shp)
 +static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp)
  {
 -      return (struct smack_known *)shp->shm_perm.security;
 +      return (struct smack_known *)isp->security;
  }
  
  /**
 - * smack_shm_alloc_security - Set the security blob for shm
 - * @shp: the object
 + * smack_ipc_alloc_security - Set the security blob for ipc
 + * @isp: the object
   *
   * Returns 0
   */
 -static int smack_shm_alloc_security(struct shmid_kernel *shp)
 +static int smack_ipc_alloc_security(struct kern_ipc_perm *isp)
  {
 -      struct kern_ipc_perm *isp = &shp->shm_perm;
        struct smack_known *skp = smk_of_current();
  
        isp->security = skp;
  }
  
  /**
 - * smack_shm_free_security - Clear the security blob for shm
 - * @shp: the object
 + * smack_ipc_free_security - Clear the security blob for ipc
 + * @isp: the object
   *
   * Clears the blob pointer
   */
 -static void smack_shm_free_security(struct shmid_kernel *shp)
 +static void smack_ipc_free_security(struct kern_ipc_perm *isp)
  {
 -      struct kern_ipc_perm *isp = &shp->shm_perm;
 -
        isp->security = NULL;
  }
  
  /**
   * smk_curacc_shm : check if current has access on shm
 - * @shp : the object
 + * @isp : the object
   * @access : access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smk_curacc_shm(struct shmid_kernel *shp, int access)
 +static int smk_curacc_shm(struct kern_ipc_perm *isp, int access)
  {
 -      struct smack_known *ssp = smack_of_shm(shp);
 +      struct smack_known *ssp = smack_of_ipc(isp);
        struct smk_audit_info ad;
        int rc;
  
  #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
 -      ad.a.u.ipc_id = shp->shm_perm.id;
 +      ad.a.u.ipc_id = isp->id;
  #endif
        rc = smk_curacc(ssp, access, &ad);
        rc = smk_bu_current("shm", ssp, access, rc);
  
  /**
   * smack_shm_associate - Smack access check for shm
 - * @shp: the object
 + * @isp: the object
   * @shmflg: access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
 +static int smack_shm_associate(struct kern_ipc_perm *isp, int shmflg)
  {
        int may;
  
        may = smack_flags_to_may(shmflg);
 -      return smk_curacc_shm(shp, may);
 +      return smk_curacc_shm(isp, may);
  }
  
  /**
   * smack_shm_shmctl - Smack access check for shm
 - * @shp: the object
 + * @isp: the object
   * @cmd: what it wants to do
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
 +static int smack_shm_shmctl(struct kern_ipc_perm *isp, int cmd)
  {
        int may;
  
        default:
                return -EINVAL;
        }
 -      return smk_curacc_shm(shp, may);
 +      return smk_curacc_shm(isp, may);
  }
  
  /**
   * smack_shm_shmat - Smack access for shmat
 - * @shp: the object
 + * @isp: the object
   * @shmaddr: unused
   * @shmflg: access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
 +static int smack_shm_shmat(struct kern_ipc_perm *ipc, char __user *shmaddr,
                           int shmflg)
  {
        int may;
  
        may = smack_flags_to_may(shmflg);
 -      return smk_curacc_shm(shp, may);
 -}
 -
 -/**
 - * smack_of_sem - the smack pointer for the sem
 - * @sma: the object
 - *
 - * Returns a pointer to the smack value
 - */
 -static struct smack_known *smack_of_sem(struct sem_array *sma)
 -{
 -      return (struct smack_known *)sma->sem_perm.security;
 -}
 -
 -/**
 - * smack_sem_alloc_security - Set the security blob for sem
 - * @sma: the object
 - *
 - * Returns 0
 - */
 -static int smack_sem_alloc_security(struct sem_array *sma)
 -{
 -      struct kern_ipc_perm *isp = &sma->sem_perm;
 -      struct smack_known *skp = smk_of_current();
 -
 -      isp->security = skp;
 -      return 0;
 -}
 -
 -/**
 - * smack_sem_free_security - Clear the security blob for sem
 - * @sma: the object
 - *
 - * Clears the blob pointer
 - */
 -static void smack_sem_free_security(struct sem_array *sma)
 -{
 -      struct kern_ipc_perm *isp = &sma->sem_perm;
 -
 -      isp->security = NULL;
 +      return smk_curacc_shm(ipc, may);
  }
  
  /**
   * smk_curacc_sem : check if current has access on sem
 - * @sma : the object
 + * @isp : the object
   * @access : access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smk_curacc_sem(struct sem_array *sma, int access)
 +static int smk_curacc_sem(struct kern_ipc_perm *isp, int access)
  {
 -      struct smack_known *ssp = smack_of_sem(sma);
 +      struct smack_known *ssp = smack_of_ipc(isp);
        struct smk_audit_info ad;
        int rc;
  
  #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
 -      ad.a.u.ipc_id = sma->sem_perm.id;
 +      ad.a.u.ipc_id = isp->id;
  #endif
        rc = smk_curacc(ssp, access, &ad);
        rc = smk_bu_current("sem", ssp, access, rc);
  
  /**
   * smack_sem_associate - Smack access check for sem
 - * @sma: the object
 + * @isp: the object
   * @semflg: access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_sem_associate(struct sem_array *sma, int semflg)
 +static int smack_sem_associate(struct kern_ipc_perm *isp, int semflg)
  {
        int may;
  
        may = smack_flags_to_may(semflg);
 -      return smk_curacc_sem(sma, may);
 +      return smk_curacc_sem(isp, may);
  }
  
  /**
   * smack_sem_shmctl - Smack access check for sem
 - * @sma: the object
 + * @isp: the object
   * @cmd: what it wants to do
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_sem_semctl(struct sem_array *sma, int cmd)
 +static int smack_sem_semctl(struct kern_ipc_perm *isp, int cmd)
  {
        int may;
  
                return -EINVAL;
        }
  
 -      return smk_curacc_sem(sma, may);
 +      return smk_curacc_sem(isp, may);
  }
  
  /**
   * smack_sem_semop - Smack checks of semaphore operations
 - * @sma: the object
 + * @isp: the object
   * @sops: unused
   * @nsops: unused
   * @alter: unused
   *
   * Returns 0 if access is allowed, error code otherwise
   */
 -static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
 +static int smack_sem_semop(struct kern_ipc_perm *isp, struct sembuf *sops,
                           unsigned nsops, int alter)
  {
 -      return smk_curacc_sem(sma, MAY_READWRITE);
 -}
 -
 -/**
 - * smack_msg_alloc_security - Set the security blob for msg
 - * @msq: the object
 - *
 - * Returns 0
 - */
 -static int smack_msg_queue_alloc_security(struct msg_queue *msq)
 -{
 -      struct kern_ipc_perm *kisp = &msq->q_perm;
 -      struct smack_known *skp = smk_of_current();
 -
 -      kisp->security = skp;
 -      return 0;
 -}
 -
 -/**
 - * smack_msg_free_security - Clear the security blob for msg
 - * @msq: the object
 - *
 - * Clears the blob pointer
 - */
 -static void smack_msg_queue_free_security(struct msg_queue *msq)
 -{
 -      struct kern_ipc_perm *kisp = &msq->q_perm;
 -
 -      kisp->security = NULL;
 -}
 -
 -/**
 - * smack_of_msq - the smack pointer for the msq
 - * @msq: the object
 - *
 - * Returns a pointer to the smack label entry
 - */
 -static struct smack_known *smack_of_msq(struct msg_queue *msq)
 -{
 -      return (struct smack_known *)msq->q_perm.security;
 +      return smk_curacc_sem(isp, MAY_READWRITE);
  }
  
  /**
   * smk_curacc_msq : helper to check if current has access on msq
 - * @msq : the msq
 + * @isp : the msq
   * @access : access requested
   *
   * return 0 if current has access, error otherwise
   */
 -static int smk_curacc_msq(struct msg_queue *msq, int access)
 +static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
  {
 -      struct smack_known *msp = smack_of_msq(msq);
 +      struct smack_known *msp = smack_of_ipc(isp);
        struct smk_audit_info ad;
        int rc;
  
  #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
 -      ad.a.u.ipc_id = msq->q_perm.id;
 +      ad.a.u.ipc_id = isp->id;
  #endif
        rc = smk_curacc(msp, access, &ad);
        rc = smk_bu_current("msq", msp, access, rc);
  
  /**
   * smack_msg_queue_associate - Smack access check for msg_queue
 - * @msq: the object
 + * @isp: the object
   * @msqflg: access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
 +static int smack_msg_queue_associate(struct kern_ipc_perm *isp, int msqflg)
  {
        int may;
  
        may = smack_flags_to_may(msqflg);
 -      return smk_curacc_msq(msq, may);
 +      return smk_curacc_msq(isp, may);
  }
  
  /**
   * smack_msg_queue_msgctl - Smack access check for msg_queue
 - * @msq: the object
 + * @isp: the object
   * @cmd: what it wants to do
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
 +static int smack_msg_queue_msgctl(struct kern_ipc_perm *isp, int cmd)
  {
        int may;
  
                return -EINVAL;
        }
  
 -      return smk_curacc_msq(msq, may);
 +      return smk_curacc_msq(isp, may);
  }
  
  /**
   * smack_msg_queue_msgsnd - Smack access check for msg_queue
 - * @msq: the object
 + * @isp: the object
   * @msg: unused
   * @msqflg: access requested
   *
   * Returns 0 if current has the requested access, error code otherwise
   */
 -static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
 +static int smack_msg_queue_msgsnd(struct kern_ipc_perm *isp, struct msg_msg *msg,
                                  int msqflg)
  {
        int may;
  
        may = smack_flags_to_may(msqflg);
 -      return smk_curacc_msq(msq, may);
 +      return smk_curacc_msq(isp, may);
  }
  
  /**
   * smack_msg_queue_msgsnd - Smack access check for msg_queue
 - * @msq: the object
 + * @isp: the object
   * @msg: unused
   * @target: unused
   * @type: unused
   *
   * Returns 0 if current has read and write access, error code otherwise
   */
 -static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
 +static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp, struct msg_msg *msg,
                        struct task_struct *target, long type, int mode)
  {
 -      return smk_curacc_msq(msq, MAY_READWRITE);
 +      return smk_curacc_msq(isp, MAY_READWRITE);
  }
  
  /**
@@@ -4675,21 -4754,21 +4673,21 @@@ static struct security_hook_list smack_
        LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security),
        LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security),
  
 -      LSM_HOOK_INIT(msg_queue_alloc_security, smack_msg_queue_alloc_security),
 -      LSM_HOOK_INIT(msg_queue_free_security, smack_msg_queue_free_security),
 +      LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security),
 +      LSM_HOOK_INIT(msg_queue_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate),
        LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl),
        LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd),
        LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv),
  
 -      LSM_HOOK_INIT(shm_alloc_security, smack_shm_alloc_security),
 -      LSM_HOOK_INIT(shm_free_security, smack_shm_free_security),
 +      LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security),
 +      LSM_HOOK_INIT(shm_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(shm_associate, smack_shm_associate),
        LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl),
        LSM_HOOK_INIT(shm_shmat, smack_shm_shmat),
  
 -      LSM_HOOK_INIT(sem_alloc_security, smack_sem_alloc_security),
 -      LSM_HOOK_INIT(sem_free_security, smack_sem_free_security),
 +      LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security),
 +      LSM_HOOK_INIT(sem_free_security, smack_ipc_free_security),
        LSM_HOOK_INIT(sem_associate, smack_sem_associate),
        LSM_HOOK_INIT(sem_semctl, smack_sem_semctl),
        LSM_HOOK_INIT(sem_semop, smack_sem_semop),