These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / security / smack / smack_lsm.c
index b644757..7c57c7f 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/binfmts.h>
+#include <linux/parser.h>
 #include "smack.h"
 
 #define TRANS_TRUE     "TRUE"
 #define SMK_RECEIVING  1
 #define SMK_SENDING    2
 
-#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
-LIST_HEAD(smk_ipv6_port_list);
-#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
+#ifdef SMACK_IPV6_PORT_LABELING
+static LIST_HEAD(smk_ipv6_port_list);
+#endif
 static struct kmem_cache *smack_inode_cache;
 int smack_enabled;
 
+static const match_table_t smk_mount_tokens = {
+       {Opt_fsdefault, SMK_FSDEFAULT "%s"},
+       {Opt_fsfloor, SMK_FSFLOOR "%s"},
+       {Opt_fshat, SMK_FSHAT "%s"},
+       {Opt_fsroot, SMK_FSROOT "%s"},
+       {Opt_fstransmute, SMK_FSTRANS "%s"},
+       {Opt_error, NULL},
+};
+
 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
 static char *smk_bu_mess[] = {
        "Bringup Error",        /* Unused */
@@ -245,8 +255,8 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
  * @ip: a pointer to the inode
  * @dp: a pointer to the dentry
  *
- * Returns a pointer to the master list entry for the Smack label
- * or NULL if there was no label to fetch.
+ * Returns a pointer to the master list entry for the Smack label,
+ * NULL if there was no label to fetch, or an error code.
  */
 static struct smack_known *smk_fetch(const char *name, struct inode *ip,
                                        struct dentry *dp)
@@ -256,14 +266,18 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
        struct smack_known *skp = NULL;
 
        if (ip->i_op->getxattr == NULL)
-               return NULL;
+               return ERR_PTR(-EOPNOTSUPP);
 
        buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
        if (buffer == NULL)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
-       if (rc > 0)
+       if (rc < 0)
+               skp = ERR_PTR(rc);
+       else if (rc == 0)
+               skp = NULL;
+       else
                skp = smk_import_entry(buffer, rc);
 
        kfree(buffer);
@@ -277,7 +291,7 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
  *
  * Returns the new blob or NULL if there's no memory available
  */
-struct inode_smack *new_inode_smack(struct smack_known *skp)
+static struct inode_smack *new_inode_smack(struct smack_known *skp)
 {
        struct inode_smack *isp;
 
@@ -312,6 +326,7 @@ static struct task_smack *new_task_smack(struct smack_known *task,
        tsp->smk_task = task;
        tsp->smk_forked = forked;
        INIT_LIST_HEAD(&tsp->smk_rules);
+       INIT_LIST_HEAD(&tsp->smk_relabel);
        mutex_init(&tsp->smk_rules_lock);
 
        return tsp;
@@ -346,6 +361,35 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
        return rc;
 }
 
+/**
+ * smk_copy_relabel - copy smk_relabel labels list
+ * @nhead: new rules header pointer
+ * @ohead: old rules header pointer
+ * @gfp: type of the memory for the allocation
+ *
+ * Returns 0 on success, -ENOMEM on error
+ */
+static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead,
+                               gfp_t gfp)
+{
+       struct smack_known_list_elem *nklep;
+       struct smack_known_list_elem *oklep;
+
+       INIT_LIST_HEAD(nhead);
+
+       list_for_each_entry(oklep, ohead, list) {
+               nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
+               if (nklep == NULL) {
+                       smk_destroy_label_list(nhead);
+                       return -ENOMEM;
+               }
+               nklep->smk_label = oklep->smk_label;
+               list_add(&nklep->list, nhead);
+       }
+
+       return 0;
+}
+
 /**
  * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_*
  * @mode - input mode in form of PTRACE_MODE_*
@@ -354,12 +398,10 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
  */
 static inline unsigned int smk_ptrace_mode(unsigned int mode)
 {
-       switch (mode) {
-       case PTRACE_MODE_READ:
-               return MAY_READ;
-       case PTRACE_MODE_ATTACH:
+       if (mode & PTRACE_MODE_ATTACH)
                return MAY_READWRITE;
-       }
+       if (mode & PTRACE_MODE_READ)
+               return MAY_READ;
 
        return 0;
 }
@@ -436,17 +478,11 @@ static int smk_ptrace_rule_check(struct task_struct *tracer,
  */
 static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
 {
-       int rc;
        struct smack_known *skp;
 
-       rc = cap_ptrace_access_check(ctp, mode);
-       if (rc != 0)
-               return rc;
-
        skp = smk_of_task_struct(ctp);
 
-       rc = smk_ptrace_rule_check(current, skp, mode, __func__);
-       return rc;
+       return smk_ptrace_rule_check(current, skp, mode, __func__);
 }
 
 /**
@@ -462,10 +498,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
        int rc;
        struct smack_known *skp;
 
-       rc = cap_ptrace_traceme(ptp);
-       if (rc != 0)
-               return rc;
-
        skp = smk_of_task(current_security());
 
        rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__);
@@ -583,72 +615,197 @@ static int smack_sb_copy_data(char *orig, char *smackopts)
 }
 
 /**
- * smack_sb_kern_mount - Smack specific mount processing
+ * smack_parse_opts_str - parse Smack specific mount options
+ * @options: mount options string
+ * @opts: where to store converted mount opts
+ *
+ * Returns 0 on success or -ENOMEM on error.
+ *
+ * converts Smack specific mount options to generic security option format
+ */
+static int smack_parse_opts_str(char *options,
+               struct security_mnt_opts *opts)
+{
+       char *p;
+       char *fsdefault = NULL;
+       char *fsfloor = NULL;
+       char *fshat = NULL;
+       char *fsroot = NULL;
+       char *fstransmute = NULL;
+       int rc = -ENOMEM;
+       int num_mnt_opts = 0;
+       int token;
+
+       opts->num_mnt_opts = 0;
+
+       if (!options)
+               return 0;
+
+       while ((p = strsep(&options, ",")) != NULL) {
+               substring_t args[MAX_OPT_ARGS];
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, smk_mount_tokens, args);
+
+               switch (token) {
+               case Opt_fsdefault:
+                       if (fsdefault)
+                               goto out_opt_err;
+                       fsdefault = match_strdup(&args[0]);
+                       if (!fsdefault)
+                               goto out_err;
+                       break;
+               case Opt_fsfloor:
+                       if (fsfloor)
+                               goto out_opt_err;
+                       fsfloor = match_strdup(&args[0]);
+                       if (!fsfloor)
+                               goto out_err;
+                       break;
+               case Opt_fshat:
+                       if (fshat)
+                               goto out_opt_err;
+                       fshat = match_strdup(&args[0]);
+                       if (!fshat)
+                               goto out_err;
+                       break;
+               case Opt_fsroot:
+                       if (fsroot)
+                               goto out_opt_err;
+                       fsroot = match_strdup(&args[0]);
+                       if (!fsroot)
+                               goto out_err;
+                       break;
+               case Opt_fstransmute:
+                       if (fstransmute)
+                               goto out_opt_err;
+                       fstransmute = match_strdup(&args[0]);
+                       if (!fstransmute)
+                               goto out_err;
+                       break;
+               default:
+                       rc = -EINVAL;
+                       pr_warn("Smack:  unknown mount option\n");
+                       goto out_err;
+               }
+       }
+
+       opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
+       if (!opts->mnt_opts)
+               goto out_err;
+
+       opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int),
+                       GFP_ATOMIC);
+       if (!opts->mnt_opts_flags) {
+               kfree(opts->mnt_opts);
+               goto out_err;
+       }
+
+       if (fsdefault) {
+               opts->mnt_opts[num_mnt_opts] = fsdefault;
+               opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT;
+       }
+       if (fsfloor) {
+               opts->mnt_opts[num_mnt_opts] = fsfloor;
+               opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT;
+       }
+       if (fshat) {
+               opts->mnt_opts[num_mnt_opts] = fshat;
+               opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT;
+       }
+       if (fsroot) {
+               opts->mnt_opts[num_mnt_opts] = fsroot;
+               opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT;
+       }
+       if (fstransmute) {
+               opts->mnt_opts[num_mnt_opts] = fstransmute;
+               opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT;
+       }
+
+       opts->num_mnt_opts = num_mnt_opts;
+       return 0;
+
+out_opt_err:
+       rc = -EINVAL;
+       pr_warn("Smack: duplicate mount options\n");
+
+out_err:
+       kfree(fsdefault);
+       kfree(fsfloor);
+       kfree(fshat);
+       kfree(fsroot);
+       kfree(fstransmute);
+       return rc;
+}
+
+/**
+ * smack_set_mnt_opts - set Smack specific mount options
  * @sb: the file system superblock
- * @flags: the mount flags
- * @data: the smack mount options
+ * @opts: Smack mount options
+ * @kern_flags: mount option from kernel space or user space
+ * @set_kern_flags: where to store converted mount opts
  *
  * Returns 0 on success, an error code on failure
+ *
+ * Allow filesystems with binary mount data to explicitly set Smack mount
+ * labels.
  */
-static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
+static int smack_set_mnt_opts(struct super_block *sb,
+               struct security_mnt_opts *opts,
+               unsigned long kern_flags,
+               unsigned long *set_kern_flags)
 {
        struct dentry *root = sb->s_root;
        struct inode *inode = d_backing_inode(root);
        struct superblock_smack *sp = sb->s_security;
        struct inode_smack *isp;
        struct smack_known *skp;
-       char *op;
-       char *commap;
+       int i;
+       int num_opts = opts->num_mnt_opts;
        int transmute = 0;
-       int specified = 0;
 
        if (sp->smk_initialized)
                return 0;
 
        sp->smk_initialized = 1;
 
-       for (op = data; op != NULL; op = commap) {
-               commap = strchr(op, ',');
-               if (commap != NULL)
-                       *commap++ = '\0';
-
-               if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
-                       op += strlen(SMK_FSHAT);
-                       skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_hat = skp;
-                               specified = 1;
-                       }
-               } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
-                       op += strlen(SMK_FSFLOOR);
-                       skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_floor = skp;
-                               specified = 1;
-                       }
-               } else if (strncmp(op, SMK_FSDEFAULT,
-                                  strlen(SMK_FSDEFAULT)) == 0) {
-                       op += strlen(SMK_FSDEFAULT);
-                       skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_default = skp;
-                               specified = 1;
-                       }
-               } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
-                       op += strlen(SMK_FSROOT);
-                       skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_root = skp;
-                               specified = 1;
-                       }
-               } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) {
-                       op += strlen(SMK_FSTRANS);
-                       skp = smk_import_entry(op, 0);
-                       if (skp != NULL) {
-                               sp->smk_root = skp;
-                               transmute = 1;
-                               specified = 1;
-                       }
+       for (i = 0; i < num_opts; i++) {
+               switch (opts->mnt_opts_flags[i]) {
+               case FSDEFAULT_MNT:
+                       skp = smk_import_entry(opts->mnt_opts[i], 0);
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_default = skp;
+                       break;
+               case FSFLOOR_MNT:
+                       skp = smk_import_entry(opts->mnt_opts[i], 0);
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_floor = skp;
+                       break;
+               case FSHAT_MNT:
+                       skp = smk_import_entry(opts->mnt_opts[i], 0);
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_hat = skp;
+                       break;
+               case FSROOT_MNT:
+                       skp = smk_import_entry(opts->mnt_opts[i], 0);
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_root = skp;
+                       break;
+               case FSTRANS_MNT:
+                       skp = smk_import_entry(opts->mnt_opts[i], 0);
+                       if (IS_ERR(skp))
+                               return PTR_ERR(skp);
+                       sp->smk_root = skp;
+                       transmute = 1;
+                       break;
+               default:
+                       break;
                }
        }
 
@@ -656,7 +813,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
                /*
                 * Unprivileged mounts don't get to specify Smack values.
                 */
-               if (specified)
+               if (num_opts)
                        return -EPERM;
                /*
                 * Unprivileged mounts get root and default from the caller.
@@ -665,6 +822,7 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
                sp->smk_root = skp;
                sp->smk_default = skp;
        }
+
        /*
         * Initialize the root inode.
         */
@@ -683,6 +841,37 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
        return 0;
 }
 
+/**
+ * smack_sb_kern_mount - Smack specific mount processing
+ * @sb: the file system superblock
+ * @flags: the mount flags
+ * @data: the smack mount options
+ *
+ * Returns 0 on success, an error code on failure
+ */
+static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
+{
+       int rc = 0;
+       char *options = data;
+       struct security_mnt_opts opts;
+
+       security_init_mnt_opts(&opts);
+
+       if (!options)
+               goto out;
+
+       rc = smack_parse_opts_str(options, &opts);
+       if (rc)
+               goto out_err;
+
+out:
+       rc = smack_set_mnt_opts(sb, &opts, 0, NULL);
+
+out_err:
+       security_free_mnt_opts(&opts);
+       return rc;
+}
+
 /**
  * smack_sb_statfs - Smack check on statfs
  * @dentry: identifies the file system in question
@@ -721,10 +910,6 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
        struct inode_smack *isp;
        int rc;
 
-       rc = cap_bprm_set_creds(bprm);
-       if (rc != 0)
-               return rc;
-
        if (bprm->cred_prepared)
                return 0;
 
@@ -779,12 +964,11 @@ static void smack_bprm_committing_creds(struct linux_binprm *bprm)
 static int smack_bprm_secureexec(struct linux_binprm *bprm)
 {
        struct task_smack *tsp = current_security();
-       int ret = cap_bprm_secureexec(bprm);
 
-       if (!ret && (tsp->smk_task != tsp->smk_forked))
-               ret = 1;
+       if (tsp->smk_task != tsp->smk_forked)
+               return 1;
 
-       return ret;
+       return 0;
 }
 
 /*
@@ -1133,7 +1317,9 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
 
        if (rc == 0 && check_import) {
                skp = size ? smk_import_entry(value, size) : NULL;
-               if (skp == NULL || (check_star &&
+               if (IS_ERR(skp))
+                       rc = PTR_ERR(skp);
+               else if (skp == NULL || (check_star &&
                    (skp == &smack_known_star || skp == &smack_known_web)))
                        rc = -EINVAL;
        }
@@ -1173,19 +1359,19 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
 
        if (strcmp(name, XATTR_NAME_SMACK) == 0) {
                skp = smk_import_entry(value, size);
-               if (skp != NULL)
+               if (!IS_ERR(skp))
                        isp->smk_inode = skp;
                else
                        isp->smk_inode = &smack_known_invalid;
        } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
                skp = smk_import_entry(value, size);
-               if (skp != NULL)
+               if (!IS_ERR(skp))
                        isp->smk_task = skp;
                else
                        isp->smk_task = &smack_known_invalid;
        } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
                skp = smk_import_entry(value, size);
-               if (skp != NULL)
+               if (!IS_ERR(skp))
                        isp->smk_mmap = skp;
                else
                        isp->smk_mmap = &smack_known_invalid;
@@ -1673,6 +1859,9 @@ static int smack_file_receive(struct file *file)
        struct smk_audit_info ad;
        struct inode *inode = file_inode(file);
 
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
        smk_ad_setfield_u_fs_path(&ad, file->f_path);
        /*
@@ -1761,6 +1950,8 @@ static void smack_cred_free(struct cred *cred)
                return;
        cred->security = NULL;
 
+       smk_destroy_label_list(&tsp->smk_relabel);
+
        list_for_each_safe(l, n, &tsp->smk_rules) {
                rp = list_entry(l, struct smack_rule, list);
                list_del(&rp->list);
@@ -1792,6 +1983,11 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
        if (rc != 0)
                return rc;
 
+       rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel,
+                               gfp);
+       if (rc != 0)
+               return rc;
+
        new->security = new_tsp;
        return 0;
 }
@@ -1934,12 +2130,7 @@ static void smack_task_getsecid(struct task_struct *p, u32 *secid)
  */
 static int smack_task_setnice(struct task_struct *p, int nice)
 {
-       int rc;
-
-       rc = cap_task_setnice(p, nice);
-       if (rc == 0)
-               rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
-       return rc;
+       return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
 /**
@@ -1951,12 +2142,7 @@ static int smack_task_setnice(struct task_struct *p, int nice)
  */
 static int smack_task_setioprio(struct task_struct *p, int ioprio)
 {
-       int rc;
-
-       rc = cap_task_setioprio(p, ioprio);
-       if (rc == 0)
-               rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
-       return rc;
+       return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
 /**
@@ -1980,12 +2166,7 @@ static int smack_task_getioprio(struct task_struct *p)
  */
 static int smack_task_setscheduler(struct task_struct *p)
 {
-       int rc;
-
-       rc = cap_task_setscheduler(p);
-       if (rc == 0)
-               rc = smk_curacc_on_task(p, MAY_WRITE, __func__);
-       return rc;
+       return smk_curacc_on_task(p, MAY_WRITE, __func__);
 }
 
 /**
@@ -2130,7 +2311,7 @@ static void smack_sk_free_security(struct sock *sk)
 }
 
 /**
-* smack_host_label - check host based restrictions
+* smack_ipv4host_label - check host based restrictions
 * @sip: the object end
 *
 * looks for host based access restrictions
@@ -2141,30 +2322,96 @@ static void smack_sk_free_security(struct sock *sk)
 *
 * Returns the label of the far end or NULL if it's not special.
 */
-static struct smack_known *smack_host_label(struct sockaddr_in *sip)
+static struct smack_known *smack_ipv4host_label(struct sockaddr_in *sip)
 {
-       struct smk_netlbladdr *snp;
+       struct smk_net4addr *snp;
        struct in_addr *siap = &sip->sin_addr;
 
        if (siap->s_addr == 0)
                return NULL;
 
-       list_for_each_entry_rcu(snp, &smk_netlbladdr_list, list)
+       list_for_each_entry_rcu(snp, &smk_net4addr_list, list)
+               /*
+                * we break after finding the first match because
+                * the list is sorted from longest to shortest mask
+                * so we have found the most specific match
+                */
+               if (snp->smk_host.s_addr ==
+                   (siap->s_addr & snp->smk_mask.s_addr))
+                       return snp->smk_label;
+
+       return NULL;
+}
+
+#if IS_ENABLED(CONFIG_IPV6)
+/*
+ * smk_ipv6_localhost - Check for local ipv6 host address
+ * @sip: the address
+ *
+ * Returns boolean true if this is the localhost address
+ */
+static bool smk_ipv6_localhost(struct sockaddr_in6 *sip)
+{
+       __be16 *be16p = (__be16 *)&sip->sin6_addr;
+       __be32 *be32p = (__be32 *)&sip->sin6_addr;
+
+       if (be32p[0] == 0 && be32p[1] == 0 && be32p[2] == 0 && be16p[6] == 0 &&
+           ntohs(be16p[7]) == 1)
+               return true;
+       return false;
+}
+
+/**
+* smack_ipv6host_label - check host based restrictions
+* @sip: the object end
+*
+* looks for host based access restrictions
+*
+* This version will only be appropriate for really small sets of single label
+* hosts.  The caller is responsible for ensuring that the RCU read lock is
+* taken before calling this function.
+*
+* Returns the label of the far end or NULL if it's not special.
+*/
+static struct smack_known *smack_ipv6host_label(struct sockaddr_in6 *sip)
+{
+       struct smk_net6addr *snp;
+       struct in6_addr *sap = &sip->sin6_addr;
+       int i;
+       int found = 0;
+
+       /*
+        * It's local. Don't look for a host label.
+        */
+       if (smk_ipv6_localhost(sip))
+               return NULL;
+
+       list_for_each_entry_rcu(snp, &smk_net6addr_list, list) {
                /*
                * we break after finding the first match because
                * the list is sorted from longest to shortest mask
                * so we have found the most specific match
                */
-               if ((&snp->smk_host.sin_addr)->s_addr ==
-                   (siap->s_addr & (&snp->smk_mask)->s_addr)) {
-                       /* we have found the special CIPSO option */
-                       if (snp->smk_label == &smack_cipso_option)
-                               return NULL;
-                       return snp->smk_label;
+               for (found = 1, i = 0; i < 8; i++) {
+                       /*
+                        * If the label is NULL the entry has
+                        * been renounced. Ignore it.
+                        */
+                       if (snp->smk_label == NULL)
+                               continue;
+                       if ((sap->s6_addr16[i] & snp->smk_mask.s6_addr16[i]) !=
+                           snp->smk_host.s6_addr16[i]) {
+                               found = 0;
+                               break;
+                       }
                }
+               if (found)
+                       return snp->smk_label;
+       }
 
        return NULL;
 }
+#endif /* CONFIG_IPV6 */
 
 /**
  * smack_netlabel - Set the secattr on a socket
@@ -2228,7 +2475,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
        struct smk_audit_info ad;
 
        rcu_read_lock();
-       hkp = smack_host_label(sap);
+       hkp = smack_ipv4host_label(sap);
        if (hkp != NULL) {
 #ifdef CONFIG_AUDIT
                struct lsm_network_audit net;
@@ -2253,7 +2500,42 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
        return smack_netlabel(sk, sk_lbl);
 }
 
-#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
+#if IS_ENABLED(CONFIG_IPV6)
+/**
+ * smk_ipv6_check - check Smack access
+ * @subject: subject Smack label
+ * @object: object Smack label
+ * @address: address
+ * @act: the action being taken
+ *
+ * Check an IPv6 access
+ */
+static int smk_ipv6_check(struct smack_known *subject,
+                               struct smack_known *object,
+                               struct sockaddr_in6 *address, int act)
+{
+#ifdef CONFIG_AUDIT
+       struct lsm_network_audit net;
+#endif
+       struct smk_audit_info ad;
+       int rc;
+
+#ifdef CONFIG_AUDIT
+       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+       ad.a.u.net->family = PF_INET6;
+       ad.a.u.net->dport = ntohs(address->sin6_port);
+       if (act == SMK_RECEIVING)
+               ad.a.u.net->v6info.saddr = address->sin6_addr;
+       else
+               ad.a.u.net->v6info.daddr = address->sin6_addr;
+#endif
+       rc = smk_access(subject, object, MAY_WRITE, &ad);
+       rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc);
+       return rc;
+}
+#endif /* CONFIG_IPV6 */
+
+#ifdef SMACK_IPV6_PORT_LABELING
 /**
  * smk_ipv6_port_label - Smack port access table management
  * @sock: socket
@@ -2337,48 +2619,43 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
 static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
                                int act)
 {
-       __be16 *bep;
-       __be32 *be32p;
        struct smk_port_label *spp;
        struct socket_smack *ssp = sk->sk_security;
-       struct smack_known *skp;
-       unsigned short port = 0;
+       struct smack_known *skp = NULL;
+       unsigned short port;
        struct smack_known *object;
-       struct smk_audit_info ad;
-       int rc;
-#ifdef CONFIG_AUDIT
-       struct lsm_network_audit net;
-#endif
 
        if (act == SMK_RECEIVING) {
-               skp = smack_net_ambient;
+               skp = smack_ipv6host_label(address);
                object = ssp->smk_in;
        } else {
                skp = ssp->smk_out;
-               object = smack_net_ambient;
+               object = smack_ipv6host_label(address);
        }
 
        /*
-        * Get the IP address and port from the address.
+        * The other end is a single label host.
         */
-       port = ntohs(address->sin6_port);
-       bep = (__be16 *)(&address->sin6_addr);
-       be32p = (__be32 *)(&address->sin6_addr);
+       if (skp != NULL && object != NULL)
+               return smk_ipv6_check(skp, object, address, act);
+       if (skp == NULL)
+               skp = smack_net_ambient;
+       if (object == NULL)
+               object = smack_net_ambient;
 
        /*
         * It's remote, so port lookup does no good.
         */
-       if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1)
-               goto auditout;
+       if (!smk_ipv6_localhost(address))
+               return smk_ipv6_check(skp, object, address, act);
 
        /*
         * It's local so the send check has to have passed.
         */
-       if (act == SMK_RECEIVING) {
-               skp = &smack_known_web;
-               goto auditout;
-       }
+       if (act == SMK_RECEIVING)
+               return 0;
 
+       port = ntohs(address->sin6_port);
        list_for_each_entry(spp, &smk_ipv6_port_list, list) {
                if (spp->smk_port != port)
                        continue;
@@ -2388,22 +2665,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
                break;
        }
 
-auditout:
-
-#ifdef CONFIG_AUDIT
-       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-       ad.a.u.net->family = sk->sk_family;
-       ad.a.u.net->dport = port;
-       if (act == SMK_RECEIVING)
-               ad.a.u.net->v6info.saddr = address->sin6_addr;
-       else
-               ad.a.u.net->v6info.daddr = address->sin6_addr;
-#endif
-       rc = smk_access(skp, object, MAY_WRITE, &ad);
-       rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
-       return rc;
+       return smk_ipv6_check(skp, object, address, act);
 }
-#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
+#endif /* SMACK_IPV6_PORT_LABELING */
 
 /**
  * smack_inode_setsecurity - set smack xattrs
@@ -2430,8 +2694,8 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
                return -EINVAL;
 
        skp = smk_import_entry(value, size);
-       if (skp == NULL)
-               return -EINVAL;
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
 
        if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
                nsp->smk_inode = skp;
@@ -2464,10 +2728,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
        } else
                return -EOPNOTSUPP;
 
-#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
+#ifdef SMACK_IPV6_PORT_LABELING
        if (sock->sk->sk_family == PF_INET6)
                smk_ipv6_port_label(sock, NULL);
-#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
+#endif
 
        return 0;
 }
@@ -2509,7 +2773,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
        return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
 }
 
-#ifndef CONFIG_SECURITY_SMACK_NETFILTER
+#ifdef SMACK_IPV6_PORT_LABELING
 /**
  * smack_socket_bind - record port binding information.
  * @sock: the socket
@@ -2523,14 +2787,11 @@ static int smack_socket_post_create(struct socket *sock, int family,
 static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
                                int addrlen)
 {
-#if IS_ENABLED(CONFIG_IPV6)
        if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
                smk_ipv6_port_label(sock, address);
-#endif
-
        return 0;
 }
-#endif /* !CONFIG_SECURITY_SMACK_NETFILTER */
+#endif /* SMACK_IPV6_PORT_LABELING */
 
 /**
  * smack_socket_connect - connect access check
@@ -2546,6 +2807,13 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
                                int addrlen)
 {
        int rc = 0;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
+#endif
+#ifdef SMACK_IPV6_SECMARK_LABELING
+       struct smack_known *rsp;
+       struct socket_smack *ssp = sock->sk->sk_security;
+#endif
 
        if (sock->sk == NULL)
                return 0;
@@ -2559,10 +2827,15 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
        case PF_INET6:
                if (addrlen < sizeof(struct sockaddr_in6))
                        return -EINVAL;
-#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
-               rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
+#ifdef SMACK_IPV6_SECMARK_LABELING
+               rsp = smack_ipv6host_label(sip);
+               if (rsp != NULL)
+                       rc = smk_ipv6_check(ssp->smk_out, rsp, sip,
                                                SMK_CONNECTING);
-#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
+#endif
+#ifdef SMACK_IPV6_PORT_LABELING
+               rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING);
+#endif
                break;
        }
        return rc;
@@ -3116,6 +3389,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                         */
                        isp->smk_inode = smk_of_current();
                        break;
+               case PIPEFS_MAGIC:
+                       isp->smk_inode = smk_of_current();
+                       break;
                default:
                        isp->smk_inode = sbsp->smk_root;
                        break;
@@ -3204,7 +3480,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 */
                dp = dget(opt_dentry);
                skp = smk_fetch(XATTR_NAME_SMACK, inode, dp);
-               if (skp != NULL)
+               if (!IS_ERR_OR_NULL(skp))
                        final = skp;
 
                /*
@@ -3241,11 +3517,14 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 * Don't let the exec or mmap label be "*" or "@".
                 */
                skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
-               if (skp == &smack_known_star || skp == &smack_known_web)
+               if (IS_ERR(skp) || skp == &smack_known_star ||
+                   skp == &smack_known_web)
                        skp = NULL;
                isp->smk_task = skp;
+
                skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
-               if (skp == &smack_known_star || skp == &smack_known_web)
+               if (IS_ERR(skp) || skp == &smack_known_star ||
+                   skp == &smack_known_web)
                        skp = NULL;
                isp->smk_mmap = skp;
 
@@ -3308,9 +3587,11 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
 static int smack_setprocattr(struct task_struct *p, char *name,
                             void *value, size_t size)
 {
-       struct task_smack *tsp;
+       struct task_smack *tsp = current_security();
        struct cred *new;
        struct smack_known *skp;
+       struct smack_known_list_elem *sklep;
+       int rc;
 
        /*
         * Changing another process' Smack value is too dangerous
@@ -3319,7 +3600,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
        if (p != current)
                return -EPERM;
 
-       if (!smack_privileged(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel))
                return -EPERM;
 
        if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
@@ -3329,8 +3610,8 @@ static int smack_setprocattr(struct task_struct *p, char *name,
                return -EINVAL;
 
        skp = smk_import_entry(value, size);
-       if (skp == NULL)
-               return -EINVAL;
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
 
        /*
         * No process is ever allowed the web ("@") label.
@@ -3338,12 +3619,27 @@ static int smack_setprocattr(struct task_struct *p, char *name,
        if (skp == &smack_known_web)
                return -EPERM;
 
+       if (!smack_privileged(CAP_MAC_ADMIN)) {
+               rc = -EPERM;
+               list_for_each_entry(sklep, &tsp->smk_relabel, list)
+                       if (sklep->smk_label == skp) {
+                               rc = 0;
+                               break;
+                       }
+               if (rc)
+                       return rc;
+       }
+
        new = prepare_creds();
        if (new == NULL)
                return -ENOMEM;
 
        tsp = new->security;
        tsp->smk_task = skp;
+       /*
+        * process can change its label only once
+        */
+       smk_destroy_label_list(&tsp->smk_relabel);
 
        commit_creds(new);
        return size;
@@ -3445,9 +3741,13 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
                                int size)
 {
        struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
-#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
+#if IS_ENABLED(CONFIG_IPV6)
        struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
-#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
+#endif
+#ifdef SMACK_IPV6_SECMARK_LABELING
+       struct socket_smack *ssp = sock->sk->sk_security;
+       struct smack_known *rsp;
+#endif
        int rc = 0;
 
        /*
@@ -3461,9 +3761,15 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
                rc = smack_netlabel_send(sock->sk, sip);
                break;
        case AF_INET6:
-#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
+#ifdef SMACK_IPV6_SECMARK_LABELING
+               rsp = smack_ipv6host_label(sap);
+               if (rsp != NULL)
+                       rc = smk_ipv6_check(ssp->smk_out, rsp, sap,
+                                               SMK_CONNECTING);
+#endif
+#ifdef SMACK_IPV6_PORT_LABELING
                rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
-#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
+#endif
                break;
        }
        return rc;
@@ -3677,10 +3983,12 @@ access_check:
                proto = smk_skb_to_addr_ipv6(skb, &sadd);
                if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
                        break;
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+#ifdef SMACK_IPV6_SECMARK_LABELING
                if (skb && skb->secmark != 0)
                        skp = smack_from_secid(skb->secmark);
                else
+                       skp = smack_ipv6host_label(&sadd);
+               if (skp == NULL)
                        skp = smack_net_ambient;
 #ifdef CONFIG_AUDIT
                smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
@@ -3691,9 +3999,10 @@ access_check:
                rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
                rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in,
                                        MAY_WRITE, rc);
-#else /* CONFIG_SECURITY_SMACK_NETFILTER */
+#endif /* SMACK_IPV6_SECMARK_LABELING */
+#ifdef SMACK_IPV6_PORT_LABELING
                rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
+#endif /* SMACK_IPV6_PORT_LABELING */
                break;
 #endif /* CONFIG_IPV6 */
        }
@@ -3791,13 +4100,11 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
                }
                netlbl_secattr_destroy(&secattr);
                break;
-#if IS_ENABLED(CONFIG_IPV6)
        case PF_INET6:
-#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+#ifdef SMACK_IPV6_SECMARK_LABELING
                s = skb->secmark;
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
+#endif
                break;
-#endif /* CONFIG_IPV6 */
        }
        *secid = s;
        if (s == 0)
@@ -3920,7 +4227,7 @@ access_check:
        hdr = ip_hdr(skb);
        addr.sin_addr.s_addr = hdr->saddr;
        rcu_read_lock();
-       hskp = smack_host_label(&addr);
+       hskp = smack_ipv4host_label(&addr);
        rcu_read_unlock();
 
        if (hskp == NULL)
@@ -4105,8 +4412,10 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
                return -EINVAL;
 
        skp = smk_import_entry(rulestr, 0);
-       if (skp)
-               *rule = skp->smk_known;
+       if (IS_ERR(skp))
+               return PTR_ERR(skp);
+
+       *rule = skp->smk_known;
 
        return 0;
 }
@@ -4266,147 +4575,147 @@ static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
        return 0;
 }
 
-struct security_operations smack_ops = {
-       .name =                         "smack",
-
-       .ptrace_access_check =          smack_ptrace_access_check,
-       .ptrace_traceme =               smack_ptrace_traceme,
-       .syslog =                       smack_syslog,
-
-       .sb_alloc_security =            smack_sb_alloc_security,
-       .sb_free_security =             smack_sb_free_security,
-       .sb_copy_data =                 smack_sb_copy_data,
-       .sb_kern_mount =                smack_sb_kern_mount,
-       .sb_statfs =                    smack_sb_statfs,
-
-       .bprm_set_creds =               smack_bprm_set_creds,
-       .bprm_committing_creds =        smack_bprm_committing_creds,
-       .bprm_secureexec =              smack_bprm_secureexec,
-
-       .inode_alloc_security =         smack_inode_alloc_security,
-       .inode_free_security =          smack_inode_free_security,
-       .inode_init_security =          smack_inode_init_security,
-       .inode_link =                   smack_inode_link,
-       .inode_unlink =                 smack_inode_unlink,
-       .inode_rmdir =                  smack_inode_rmdir,
-       .inode_rename =                 smack_inode_rename,
-       .inode_permission =             smack_inode_permission,
-       .inode_setattr =                smack_inode_setattr,
-       .inode_getattr =                smack_inode_getattr,
-       .inode_setxattr =               smack_inode_setxattr,
-       .inode_post_setxattr =          smack_inode_post_setxattr,
-       .inode_getxattr =               smack_inode_getxattr,
-       .inode_removexattr =            smack_inode_removexattr,
-       .inode_getsecurity =            smack_inode_getsecurity,
-       .inode_setsecurity =            smack_inode_setsecurity,
-       .inode_listsecurity =           smack_inode_listsecurity,
-       .inode_getsecid =               smack_inode_getsecid,
-
-       .file_permission =              smack_file_permission,
-       .file_alloc_security =          smack_file_alloc_security,
-       .file_free_security =           smack_file_free_security,
-       .file_ioctl =                   smack_file_ioctl,
-       .file_lock =                    smack_file_lock,
-       .file_fcntl =                   smack_file_fcntl,
-       .mmap_file =                    smack_mmap_file,
-       .mmap_addr =                    cap_mmap_addr,
-       .file_set_fowner =              smack_file_set_fowner,
-       .file_send_sigiotask =          smack_file_send_sigiotask,
-       .file_receive =                 smack_file_receive,
-
-       .file_open =                    smack_file_open,
-
-       .cred_alloc_blank =             smack_cred_alloc_blank,
-       .cred_free =                    smack_cred_free,
-       .cred_prepare =                 smack_cred_prepare,
-       .cred_transfer =                smack_cred_transfer,
-       .kernel_act_as =                smack_kernel_act_as,
-       .kernel_create_files_as =       smack_kernel_create_files_as,
-       .task_setpgid =                 smack_task_setpgid,
-       .task_getpgid =                 smack_task_getpgid,
-       .task_getsid =                  smack_task_getsid,
-       .task_getsecid =                smack_task_getsecid,
-       .task_setnice =                 smack_task_setnice,
-       .task_setioprio =               smack_task_setioprio,
-       .task_getioprio =               smack_task_getioprio,
-       .task_setscheduler =            smack_task_setscheduler,
-       .task_getscheduler =            smack_task_getscheduler,
-       .task_movememory =              smack_task_movememory,
-       .task_kill =                    smack_task_kill,
-       .task_wait =                    smack_task_wait,
-       .task_to_inode =                smack_task_to_inode,
-
-       .ipc_permission =               smack_ipc_permission,
-       .ipc_getsecid =                 smack_ipc_getsecid,
-
-       .msg_msg_alloc_security =       smack_msg_msg_alloc_security,
-       .msg_msg_free_security =        smack_msg_msg_free_security,
-
-       .msg_queue_alloc_security =     smack_msg_queue_alloc_security,
-       .msg_queue_free_security =      smack_msg_queue_free_security,
-       .msg_queue_associate =          smack_msg_queue_associate,
-       .msg_queue_msgctl =             smack_msg_queue_msgctl,
-       .msg_queue_msgsnd =             smack_msg_queue_msgsnd,
-       .msg_queue_msgrcv =             smack_msg_queue_msgrcv,
-
-       .shm_alloc_security =           smack_shm_alloc_security,
-       .shm_free_security =            smack_shm_free_security,
-       .shm_associate =                smack_shm_associate,
-       .shm_shmctl =                   smack_shm_shmctl,
-       .shm_shmat =                    smack_shm_shmat,
-
-       .sem_alloc_security =           smack_sem_alloc_security,
-       .sem_free_security =            smack_sem_free_security,
-       .sem_associate =                smack_sem_associate,
-       .sem_semctl =                   smack_sem_semctl,
-       .sem_semop =                    smack_sem_semop,
-
-       .d_instantiate =                smack_d_instantiate,
-
-       .getprocattr =                  smack_getprocattr,
-       .setprocattr =                  smack_setprocattr,
-
-       .unix_stream_connect =          smack_unix_stream_connect,
-       .unix_may_send =                smack_unix_may_send,
-
-       .socket_post_create =           smack_socket_post_create,
-#ifndef CONFIG_SECURITY_SMACK_NETFILTER
-       .socket_bind =                  smack_socket_bind,
-#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
-       .socket_connect =               smack_socket_connect,
-       .socket_sendmsg =               smack_socket_sendmsg,
-       .socket_sock_rcv_skb =          smack_socket_sock_rcv_skb,
-       .socket_getpeersec_stream =     smack_socket_getpeersec_stream,
-       .socket_getpeersec_dgram =      smack_socket_getpeersec_dgram,
-       .sk_alloc_security =            smack_sk_alloc_security,
-       .sk_free_security =             smack_sk_free_security,
-       .sock_graft =                   smack_sock_graft,
-       .inet_conn_request =            smack_inet_conn_request,
-       .inet_csk_clone =               smack_inet_csk_clone,
+static struct security_hook_list smack_hooks[] = {
+       LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme),
+       LSM_HOOK_INIT(syslog, smack_syslog),
+
+       LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security),
+       LSM_HOOK_INIT(sb_free_security, smack_sb_free_security),
+       LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data),
+       LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount),
+       LSM_HOOK_INIT(sb_statfs, smack_sb_statfs),
+       LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts),
+       LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str),
+
+       LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds),
+       LSM_HOOK_INIT(bprm_committing_creds, smack_bprm_committing_creds),
+       LSM_HOOK_INIT(bprm_secureexec, smack_bprm_secureexec),
+
+       LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security),
+       LSM_HOOK_INIT(inode_free_security, smack_inode_free_security),
+       LSM_HOOK_INIT(inode_init_security, smack_inode_init_security),
+       LSM_HOOK_INIT(inode_link, smack_inode_link),
+       LSM_HOOK_INIT(inode_unlink, smack_inode_unlink),
+       LSM_HOOK_INIT(inode_rmdir, smack_inode_rmdir),
+       LSM_HOOK_INIT(inode_rename, smack_inode_rename),
+       LSM_HOOK_INIT(inode_permission, smack_inode_permission),
+       LSM_HOOK_INIT(inode_setattr, smack_inode_setattr),
+       LSM_HOOK_INIT(inode_getattr, smack_inode_getattr),
+       LSM_HOOK_INIT(inode_setxattr, smack_inode_setxattr),
+       LSM_HOOK_INIT(inode_post_setxattr, smack_inode_post_setxattr),
+       LSM_HOOK_INIT(inode_getxattr, smack_inode_getxattr),
+       LSM_HOOK_INIT(inode_removexattr, smack_inode_removexattr),
+       LSM_HOOK_INIT(inode_getsecurity, smack_inode_getsecurity),
+       LSM_HOOK_INIT(inode_setsecurity, smack_inode_setsecurity),
+       LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity),
+       LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid),
+
+       LSM_HOOK_INIT(file_permission, smack_file_permission),
+       LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
+       LSM_HOOK_INIT(file_free_security, smack_file_free_security),
+       LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
+       LSM_HOOK_INIT(file_lock, smack_file_lock),
+       LSM_HOOK_INIT(file_fcntl, smack_file_fcntl),
+       LSM_HOOK_INIT(mmap_file, smack_mmap_file),
+       LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
+       LSM_HOOK_INIT(file_set_fowner, smack_file_set_fowner),
+       LSM_HOOK_INIT(file_send_sigiotask, smack_file_send_sigiotask),
+       LSM_HOOK_INIT(file_receive, smack_file_receive),
+
+       LSM_HOOK_INIT(file_open, smack_file_open),
+
+       LSM_HOOK_INIT(cred_alloc_blank, smack_cred_alloc_blank),
+       LSM_HOOK_INIT(cred_free, smack_cred_free),
+       LSM_HOOK_INIT(cred_prepare, smack_cred_prepare),
+       LSM_HOOK_INIT(cred_transfer, smack_cred_transfer),
+       LSM_HOOK_INIT(kernel_act_as, smack_kernel_act_as),
+       LSM_HOOK_INIT(kernel_create_files_as, smack_kernel_create_files_as),
+       LSM_HOOK_INIT(task_setpgid, smack_task_setpgid),
+       LSM_HOOK_INIT(task_getpgid, smack_task_getpgid),
+       LSM_HOOK_INIT(task_getsid, smack_task_getsid),
+       LSM_HOOK_INIT(task_getsecid, smack_task_getsecid),
+       LSM_HOOK_INIT(task_setnice, smack_task_setnice),
+       LSM_HOOK_INIT(task_setioprio, smack_task_setioprio),
+       LSM_HOOK_INIT(task_getioprio, smack_task_getioprio),
+       LSM_HOOK_INIT(task_setscheduler, smack_task_setscheduler),
+       LSM_HOOK_INIT(task_getscheduler, smack_task_getscheduler),
+       LSM_HOOK_INIT(task_movememory, smack_task_movememory),
+       LSM_HOOK_INIT(task_kill, smack_task_kill),
+       LSM_HOOK_INIT(task_wait, smack_task_wait),
+       LSM_HOOK_INIT(task_to_inode, smack_task_to_inode),
+
+       LSM_HOOK_INIT(ipc_permission, smack_ipc_permission),
+       LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid),
+
+       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_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_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_associate, smack_sem_associate),
+       LSM_HOOK_INIT(sem_semctl, smack_sem_semctl),
+       LSM_HOOK_INIT(sem_semop, smack_sem_semop),
+
+       LSM_HOOK_INIT(d_instantiate, smack_d_instantiate),
+
+       LSM_HOOK_INIT(getprocattr, smack_getprocattr),
+       LSM_HOOK_INIT(setprocattr, smack_setprocattr),
+
+       LSM_HOOK_INIT(unix_stream_connect, smack_unix_stream_connect),
+       LSM_HOOK_INIT(unix_may_send, smack_unix_may_send),
+
+       LSM_HOOK_INIT(socket_post_create, smack_socket_post_create),
+#ifdef SMACK_IPV6_PORT_LABELING
+       LSM_HOOK_INIT(socket_bind, smack_socket_bind),
+#endif
+       LSM_HOOK_INIT(socket_connect, smack_socket_connect),
+       LSM_HOOK_INIT(socket_sendmsg, smack_socket_sendmsg),
+       LSM_HOOK_INIT(socket_sock_rcv_skb, smack_socket_sock_rcv_skb),
+       LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
+       LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
+       LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
+       LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+       LSM_HOOK_INIT(sock_graft, smack_sock_graft),
+       LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
+       LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
 
  /* key management security hooks */
 #ifdef CONFIG_KEYS
-       .key_alloc =                    smack_key_alloc,
-       .key_free =                     smack_key_free,
-       .key_permission =               smack_key_permission,
-       .key_getsecurity =              smack_key_getsecurity,
+       LSM_HOOK_INIT(key_alloc, smack_key_alloc),
+       LSM_HOOK_INIT(key_free, smack_key_free),
+       LSM_HOOK_INIT(key_permission, smack_key_permission),
+       LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity),
 #endif /* CONFIG_KEYS */
 
  /* Audit hooks */
 #ifdef CONFIG_AUDIT
-       .audit_rule_init =              smack_audit_rule_init,
-       .audit_rule_known =             smack_audit_rule_known,
-       .audit_rule_match =             smack_audit_rule_match,
-       .audit_rule_free =              smack_audit_rule_free,
+       LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init),
+       LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known),
+       LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match),
+       LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free),
 #endif /* CONFIG_AUDIT */
 
-       .ismaclabel =                   smack_ismaclabel,
-       .secid_to_secctx =              smack_secid_to_secctx,
-       .secctx_to_secid =              smack_secctx_to_secid,
-       .release_secctx =               smack_release_secctx,
-       .inode_notifysecctx =           smack_inode_notifysecctx,
-       .inode_setsecctx =              smack_inode_setsecctx,
-       .inode_getsecctx =              smack_inode_getsecctx,
+       LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
+       LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
+       LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
+       LSM_HOOK_INIT(release_secctx, smack_release_secctx),
+       LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
+       LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
+       LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),
 };
 
 
@@ -4451,11 +4760,9 @@ static __init int smack_init(void)
        struct cred *cred;
        struct task_smack *tsp;
 
-       if (!security_module_enable(&smack_ops))
+       if (!security_module_enable("smack"))
                return 0;
 
-       smack_enabled = 1;
-
        smack_inode_cache = KMEM_CACHE(inode_smack, 0);
        if (!smack_inode_cache)
                return -ENOMEM;
@@ -4467,7 +4774,18 @@ static __init int smack_init(void)
                return -ENOMEM;
        }
 
-       printk(KERN_INFO "Smack:  Initializing.\n");
+       smack_enabled = 1;
+
+       pr_info("Smack:  Initializing.\n");
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+       pr_info("Smack:  Netfilter enabled.\n");
+#endif
+#ifdef SMACK_IPV6_PORT_LABELING
+       pr_info("Smack:  IPv6 port labeling enabled.\n");
+#endif
+#ifdef SMACK_IPV6_SECMARK_LABELING
+       pr_info("Smack:  IPv6 Netfilter enabled.\n");
+#endif
 
        /*
         * Set the security state for the initial task.
@@ -4481,8 +4799,7 @@ static __init int smack_init(void)
        /*
         * Register with LSM
         */
-       if (register_security(&smack_ops))
-               panic("smack: Unable to register with kernel.\n");
+       security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks));
 
        return 0;
 }