Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next
James Morris [Tue, 22 May 2012 01:21:06 +0000 (11:21 +1000)]
Per pull request, for 3.5.

1  2 
include/linux/security.h
security/apparmor/policy.c
security/selinux/hooks.c
security/smack/smack.h
security/smack/smack_lsm.c

diff --combined include/linux/security.h
@@@ -144,7 -144,6 +144,7 @@@ struct request_sock
  #define LSM_UNSAFE_SHARE      1
  #define LSM_UNSAFE_PTRACE     2
  #define LSM_UNSAFE_PTRACE_CAP 4
 +#define LSM_UNSAFE_NO_NEW_PRIVS       8
  
  #ifdef CONFIG_MMU
  extern int mmap_min_addr_handler(struct ctl_table *table, int write,
@@@ -640,10 -639,7 +640,7 @@@ static inline void security_free_mnt_op
   *    to receive an open file descriptor via socket IPC.
   *    @file contains the file structure being received.
   *    Return 0 if permission is granted.
-  *
-  * Security hook for dentry
-  *
-  * @dentry_open
+  * @file_open
   *    Save open-time permission checking state for later use upon
   *    file_permission, and recheck access if anything has changed
   *    since inode_permission.
@@@ -1498,7 -1494,7 +1495,7 @@@ struct security_operations 
        int (*file_send_sigiotask) (struct task_struct *tsk,
                                    struct fown_struct *fown, int sig);
        int (*file_receive) (struct file *file);
-       int (*dentry_open) (struct file *file, const struct cred *cred);
+       int (*file_open) (struct file *file, const struct cred *cred);
  
        int (*task_create) (unsigned long clone_flags);
        void (*task_free) (struct task_struct *task);
@@@ -1757,7 -1753,7 +1754,7 @@@ int security_file_set_fowner(struct fil
  int security_file_send_sigiotask(struct task_struct *tsk,
                                 struct fown_struct *fown, int sig);
  int security_file_receive(struct file *file);
- int security_dentry_open(struct file *file, const struct cred *cred);
+ int security_file_open(struct file *file, const struct cred *cred);
  int security_task_create(unsigned long clone_flags);
  void security_task_free(struct task_struct *task);
  int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
@@@ -2228,8 -2224,8 +2225,8 @@@ static inline int security_file_receive
        return 0;
  }
  
- static inline int security_dentry_open(struct file *file,
-                                      const struct cred *cred)
+ static inline int security_file_open(struct file *file,
+                                    const struct cred *cred)
  {
        return 0;
  }
@@@ -903,10 -903,6 +903,10 @@@ struct aa_profile *aa_lookup_profile(st
        profile = aa_get_profile(__lookup_profile(&ns->base, hname));
        read_unlock(&ns->lock);
  
 +      /* the unconfined profile is not in the regular profile list */
 +      if (!profile && strcmp(hname, "unconfined") == 0)
 +              profile = aa_get_profile(ns->unconfined);
 +
        /* refcount released by caller */
        return profile;
  }
@@@ -969,7 -965,7 +969,7 @@@ static int audit_policy(int op, gfp_t g
  {
        struct common_audit_data sa;
        struct apparmor_audit_data aad = {0,};
-       COMMON_AUDIT_DATA_INIT(&sa, NONE);
+       sa.type = LSM_AUDIT_DATA_NONE;
        sa.aad = &aad;
        aad.op = op;
        aad.name = name;
diff --combined security/selinux/hooks.c
@@@ -1420,16 -1420,13 +1420,13 @@@ static int cred_has_capability(const st
                               int cap, int audit)
  {
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct av_decision avd;
        u16 sclass;
        u32 sid = cred_sid(cred);
        u32 av = CAP_TO_MASK(cap);
        int rc;
  
-       COMMON_AUDIT_DATA_INIT(&ad, CAP);
-       ad.selinux_audit_data = &sad;
-       ad.tsk = current;
+       ad.type = LSM_AUDIT_DATA_CAP;
        ad.u.cap = cap;
  
        switch (CAP_TO_INDEX(cap)) {
@@@ -1488,20 -1485,6 +1485,6 @@@ static int inode_has_perm(const struct 
        return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
  }
  
- static int inode_has_perm_noadp(const struct cred *cred,
-                               struct inode *inode,
-                               u32 perms,
-                               unsigned flags)
- {
-       struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
-       COMMON_AUDIT_DATA_INIT(&ad, INODE);
-       ad.u.inode = inode;
-       ad.selinux_audit_data = &sad;
-       return inode_has_perm(cred, inode, perms, &ad, flags);
- }
  /* Same as inode_has_perm, but pass explicit audit data containing
     the dentry to help the auditing code to more easily generate the
     pathname if needed. */
@@@ -1511,11 -1494,9 +1494,9 @@@ static inline int dentry_has_perm(cons
  {
        struct inode *inode = dentry->d_inode;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
-       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, av, &ad, 0);
  }
  
@@@ -1528,11 -1509,9 +1509,9 @@@ static inline int path_has_perm(const s
  {
        struct inode *inode = path->dentry->d_inode;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
  
-       COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.type = LSM_AUDIT_DATA_PATH;
        ad.u.path = *path;
-       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, av, &ad, 0);
  }
  
@@@ -1551,13 -1530,11 +1530,11 @@@ static int file_has_perm(const struct c
        struct file_security_struct *fsec = file->f_security;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct common_audit_data ad;
        u32 sid = cred_sid(cred);
        int rc;
  
-       COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.type = LSM_AUDIT_DATA_PATH;
        ad.u.path = file->f_path;
-       ad.selinux_audit_data = &sad;
  
        if (sid != fsec->sid) {
                rc = avc_has_perm(sid, fsec->sid,
@@@ -1587,7 -1564,6 +1564,6 @@@ static int may_create(struct inode *dir
        struct superblock_security_struct *sbsec;
        u32 sid, newsid;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        int rc;
  
        dsec = dir->i_security;
        sid = tsec->sid;
        newsid = tsec->create_sid;
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
-       ad.selinux_audit_data = &sad;
  
        rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
                          DIR__ADD_NAME | DIR__SEARCH,
@@@ -1643,7 -1618,6 +1618,6 @@@ static int may_link(struct inode *dir
  {
        struct inode_security_struct *dsec, *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        u32 av;
        int rc;
        dsec = dir->i_security;
        isec = dentry->d_inode->i_security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
-       ad.selinux_audit_data = &sad;
  
        av = DIR__SEARCH;
        av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@@ -1688,7 -1661,6 +1661,6 @@@ static inline int may_rename(struct ino
  {
        struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        u32 av;
        int old_is_dir, new_is_dir;
        old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
        new_dsec = new_dir->i_security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_DENTRY;
  
        ad.u.dentry = old_dentry;
        rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
@@@ -1986,7 -1957,6 +1957,6 @@@ static int selinux_bprm_set_creds(struc
        struct task_security_struct *new_tsec;
        struct inode_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct inode *inode = bprm->file->f_path.dentry->d_inode;
        int rc;
  
                new_tsec->sid = old_tsec->exec_sid;
                /* Reset exec SID on execve. */
                new_tsec->exec_sid = 0;
 +
 +              /*
 +               * Minimize confusion: if no_new_privs and a transition is
 +               * explicitly requested, then fail the exec.
 +               */
 +              if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
 +                      return -EPERM;
        } else {
                /* Check for a default transition on this program. */
                rc = security_transition_sid(old_tsec->sid, isec->sid,
                        return rc;
        }
  
-       COMMON_AUDIT_DATA_INIT(&ad, PATH);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_PATH;
        ad.u.path = bprm->file->f_path;
  
 -      if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
 +      if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
 +          (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
                new_tsec->sid = old_tsec->sid;
  
        if (new_tsec->sid == old_tsec->sid) {
@@@ -2123,8 -2084,6 +2092,6 @@@ static int selinux_bprm_secureexec(stru
  static inline void flush_unauthorized_files(const struct cred *cred,
                                            struct files_struct *files)
  {
-       struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct file *file, *devnull = NULL;
        struct tty_struct *tty;
        struct fdtable *fdt;
                spin_lock(&tty_files_lock);
                if (!list_empty(&tty->tty_files)) {
                        struct tty_file_private *file_priv;
-                       struct inode *inode;
  
                        /* Revalidate access to controlling tty.
-                          Use inode_has_perm on the tty inode directly rather
+                          Use path_has_perm on the tty path directly rather
                           than using file_has_perm, as this particular open
                           file may belong to another process and we are only
                           interested in the inode-based check here. */
                        file_priv = list_first_entry(&tty->tty_files,
                                                struct tty_file_private, list);
                        file = file_priv->file;
-                       inode = file->f_path.dentry->d_inode;
-                       if (inode_has_perm_noadp(cred, inode,
-                                          FILE__READ | FILE__WRITE, 0)) {
+                       if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
                                drop_tty = 1;
-                       }
                }
                spin_unlock(&tty_files_lock);
                tty_kref_put(tty);
                no_tty();
  
        /* Revalidate access to inherited open files. */
-       COMMON_AUDIT_DATA_INIT(&ad, INODE);
-       ad.selinux_audit_data = &sad;
        spin_lock(&files->file_lock);
        for (;;) {
                unsigned long set, i;
@@@ -2500,7 -2451,6 +2459,6 @@@ static int selinux_sb_kern_mount(struc
  {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        int rc;
  
        rc = superblock_doinit(sb, data);
        if (flags & MS_KERNMOUNT)
                return 0;
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = sb->s_root;
        return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
  }
@@@ -2521,10 -2470,8 +2478,8 @@@ static int selinux_sb_statfs(struct den
  {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry->d_sb->s_root;
        return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
  }
@@@ -2684,14 -2631,35 +2639,35 @@@ static int selinux_inode_follow_link(st
        return dentry_has_perm(cred, dentry, FILE__READ);
  }
  
+ static noinline int audit_inode_permission(struct inode *inode,
+                                          u32 perms, u32 audited, u32 denied,
+                                          unsigned flags)
+ {
+       struct common_audit_data ad;
+       struct inode_security_struct *isec = inode->i_security;
+       int rc;
+       ad.type = LSM_AUDIT_DATA_INODE;
+       ad.u.inode = inode;
+       rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
+                           audited, denied, &ad, flags);
+       if (rc)
+               return rc;
+       return 0;
+ }
  static int selinux_inode_permission(struct inode *inode, int mask)
  {
        const struct cred *cred = current_cred();
        u32 perms;
        bool from_access;
        unsigned flags = mask & MAY_NOT_BLOCK;
+       struct inode_security_struct *isec;
+       u32 sid;
+       struct av_decision avd;
+       int rc, rc2;
+       u32 audited, denied;
  
        from_access = mask & MAY_ACCESS;
        mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
        if (!mask)
                return 0;
  
-       COMMON_AUDIT_DATA_INIT(&ad, INODE);
-       ad.selinux_audit_data = &sad;
-       ad.u.inode = inode;
+       validate_creds(cred);
  
-       if (from_access)
-               ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
  
        perms = file_mask_to_av(inode->i_mode, mask);
  
-       return inode_has_perm(cred, inode, perms, &ad, flags);
+       sid = cred_sid(cred);
+       isec = inode->i_security;
+       rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
+       audited = avc_audit_required(perms, &avd, rc,
+                                    from_access ? FILE__AUDIT_ACCESS : 0,
+                                    &denied);
+       if (likely(!audited))
+               return rc;
+       rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
+       if (rc2)
+               return rc2;
+       return rc;
  }
  
  static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
  {
        const struct cred *cred = current_cred();
        unsigned int ia_valid = iattr->ia_valid;
+       __u32 av = FILE__WRITE;
  
        /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
        if (ia_valid & ATTR_FORCE) {
                        ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
                return dentry_has_perm(cred, dentry, FILE__SETATTR);
  
-       return dentry_has_perm(cred, dentry, FILE__WRITE);
+       if (ia_valid & ATTR_SIZE)
+               av |= FILE__OPEN;
+       return dentry_has_perm(cred, dentry, av);
  }
  
  static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
@@@ -2771,7 -2754,6 +2762,6 @@@ static int selinux_inode_setxattr(struc
        struct inode_security_struct *isec = inode->i_security;
        struct superblock_security_struct *sbsec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 newsid, sid = current_sid();
        int rc = 0;
  
        if (!inode_owner_or_capable(inode))
                return -EPERM;
  
-       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
  
        rc = avc_has_perm(sid, isec->sid, isec->sclass,
  
        rc = security_context_to_sid(value, size, &newsid);
        if (rc == -EINVAL) {
-               if (!capable(CAP_MAC_ADMIN))
+               if (!capable(CAP_MAC_ADMIN)) {
+                       struct audit_buffer *ab;
+                       size_t audit_size;
+                       const char *str;
+                       /* We strip a nul only if it is at the end, otherwise the
+                        * context contains a nul and we should audit that */
+                       str = value;
+                       if (str[size - 1] == '\0')
+                               audit_size = size - 1;
+                       else
+                               audit_size = size;
+                       ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+                       audit_log_format(ab, "op=setxattr invalid_context=");
+                       audit_log_n_untrustedstring(ab, value, audit_size);
+                       audit_log_end(ab);
                        return rc;
+               }
                rc = security_context_to_sid_force(value, size, &newsid);
        }
        if (rc)
@@@ -2977,7 -2975,7 +2983,7 @@@ static int selinux_file_permission(stru
  
        if (sid == fsec->sid && fsec->isid == isec->sid &&
            fsec->pseqno == avc_policy_seqno())
-               /* No change since dentry_open check. */
+               /* No change since file_open check. */
                return 0;
  
        return selinux_revalidate_file_permission(file, mask);
@@@ -3236,15 -3234,13 +3242,13 @@@ static int selinux_file_receive(struct 
        return file_has_perm(cred, file, file_to_av(file));
  }
  
- static int selinux_dentry_open(struct file *file, const struct cred *cred)
+ static int selinux_file_open(struct file *file, const struct cred *cred)
  {
        struct file_security_struct *fsec;
-       struct inode *inode;
        struct inode_security_struct *isec;
  
-       inode = file->f_path.dentry->d_inode;
        fsec = file->f_security;
-       isec = inode->i_security;
+       isec = file->f_path.dentry->d_inode->i_security;
        /*
         * Save inode label and policy sequence number
         * at open-time so that selinux_file_permission
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
-       return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
+       return path_has_perm(cred, &file->f_path, open_file_to_av(file));
  }
  
  /* task security operations */
@@@ -3381,12 -3377,10 +3385,10 @@@ static int selinux_kernel_module_reques
  {
        u32 sid;
        struct common_audit_data ad;
  
        sid = task_sid(current);
  
-       COMMON_AUDIT_DATA_INIT(&ad, KMOD);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_KMOD;
        ad.u.kmod_name = kmod_name;
  
        return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
@@@ -3759,15 -3753,13 +3761,13 @@@ static int sock_has_perm(struct task_st
  {
        struct sk_security_struct *sksec = sk->sk_security;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct lsm_network_audit net = {0,};
        u32 tsid = task_sid(task);
  
        if (sksec->sid == SECINITSID_KERNEL)
                return 0;
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->sk = sk;
  
@@@ -3847,7 -3839,6 +3847,6 @@@ static int selinux_socket_bind(struct s
                char *addrp;
                struct sk_security_struct *sksec = sk->sk_security;
                struct common_audit_data ad;
-               struct selinux_audit_data sad = {0,};
                struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
                                                      snum, &sid);
                                if (err)
                                        goto out;
-                               COMMON_AUDIT_DATA_INIT(&ad, NET);
-                               ad.selinux_audit_data = &sad;
+                               ad.type = LSM_AUDIT_DATA_NET;
                                ad.u.net = &net;
                                ad.u.net->sport = htons(snum);
                                ad.u.net->family = family;
                if (err)
                        goto out;
  
-               COMMON_AUDIT_DATA_INIT(&ad, NET);
-               ad.selinux_audit_data = &sad;
+               ad.type = LSM_AUDIT_DATA_NET;
                ad.u.net = &net;
                ad.u.net->sport = htons(snum);
                ad.u.net->family = family;
@@@ -3945,7 -3934,6 +3942,6 @@@ static int selinux_socket_connect(struc
        if (sksec->sclass == SECCLASS_TCP_SOCKET ||
            sksec->sclass == SECCLASS_DCCP_SOCKET) {
                struct common_audit_data ad;
-               struct selinux_audit_data sad = {0,};
                struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
                perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
                       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
  
-               COMMON_AUDIT_DATA_INIT(&ad, NET);
-               ad.selinux_audit_data = &sad;
+               ad.type = LSM_AUDIT_DATA_NET;
                ad.u.net = &net;
                ad.u.net->dport = htons(snum);
                ad.u.net->family = sk->sk_family;
@@@ -4064,12 -4051,10 +4059,10 @@@ static int selinux_socket_unix_stream_c
        struct sk_security_struct *sksec_other = other->sk_security;
        struct sk_security_struct *sksec_new = newsk->sk_security;
        struct common_audit_data ad;
        struct lsm_network_audit net = {0,};
        int err;
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->sk = other;
  
@@@ -4098,11 -4083,9 +4091,9 @@@ static int selinux_socket_unix_may_send
        struct sk_security_struct *ssec = sock->sk->sk_security;
        struct sk_security_struct *osec = other->sk->sk_security;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct lsm_network_audit net = {0,};
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->sk = other->sk;
  
@@@ -4140,12 -4123,10 +4131,10 @@@ static int selinux_sock_rcv_skb_compat(
        struct sk_security_struct *sksec = sk->sk_security;
        u32 sk_sid = sksec->sid;
        struct common_audit_data ad;
        struct lsm_network_audit net = {0,};
        char *addrp;
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->netif = skb->skb_iif;
        ad.u.net->family = family;
@@@ -4175,7 -4156,6 +4164,6 @@@ static int selinux_socket_sock_rcv_skb(
        u16 family = sk->sk_family;
        u32 sk_sid = sksec->sid;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct lsm_network_audit net = {0,};
        char *addrp;
        u8 secmark_active;
        if (!secmark_active && !peerlbl_active)
                return 0;
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->netif = skb->skb_iif;
        ad.u.net->family = family;
@@@ -4539,7 -4518,6 +4526,6 @@@ static unsigned int selinux_ip_forward(
        char *addrp;
        u32 peer_sid;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct lsm_network_audit net = {0,};
        u8 secmark_active;
        u8 netlbl_active;
        if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
                return NF_DROP;
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->netif = ifindex;
        ad.u.net->family = family;
@@@ -4648,7 -4625,6 +4633,6 @@@ static unsigned int selinux_ip_postrout
        struct sock *sk = skb->sk;
        struct sk_security_struct *sksec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct lsm_network_audit net = {0,};
        char *addrp;
        u8 proto;
                return NF_ACCEPT;
        sksec = sk->sk_security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->netif = ifindex;
        ad.u.net->family = family;
@@@ -4683,7 -4658,6 +4666,6 @@@ static unsigned int selinux_ip_postrout
        u32 peer_sid;
        struct sock *sk;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        struct lsm_network_audit net = {0,};
        char *addrp;
        u8 secmark_active;
                secmark_perm = PACKET__SEND;
        }
  
-       COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_NET;
        ad.u.net = &net;
        ad.u.net->netif = ifindex;
        ad.u.net->family = family;
@@@ -4849,13 -4822,11 +4830,11 @@@ static int ipc_has_perm(struct kern_ipc
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
  
        isec = ipc_perms->security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = ipc_perms->key;
  
        return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@@ -4876,7 -4847,6 +4855,6 @@@ static int selinux_msg_queue_alloc_secu
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
  
  
        isec = msq->q_perm.security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->q_perm.key;
  
        rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@@ -4908,13 -4877,11 +4885,11 @@@ static int selinux_msg_queue_associate(
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
  
        isec = msq->q_perm.security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->q_perm.key;
  
        return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@@ -4954,7 -4921,6 +4929,6 @@@ static int selinux_msg_queue_msgsnd(str
        struct ipc_security_struct *isec;
        struct msg_security_struct *msec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
  
                        return rc;
        }
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->q_perm.key;
  
        /* Can this process write to the queue? */
@@@ -5001,15 -4966,13 +4974,13 @@@ static int selinux_msg_queue_msgrcv(str
        struct ipc_security_struct *isec;
        struct msg_security_struct *msec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = task_sid(target);
        int rc;
  
        isec = msq->q_perm.security;
        msec = msg->security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = msq->q_perm.key;
  
        rc = avc_has_perm(sid, isec->sid,
@@@ -5025,7 -4988,6 +4996,6 @@@ static int selinux_shm_alloc_security(s
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
  
  
        isec = shp->shm_perm.security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->shm_perm.key;
  
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@@ -5057,13 -5018,11 +5026,11 @@@ static int selinux_shm_associate(struc
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
  
        isec = shp->shm_perm.security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = shp->shm_perm.key;
  
        return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@@ -5121,7 -5080,6 +5088,6 @@@ static int selinux_sem_alloc_security(s
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
  
  
        isec = sma->sem_perm.security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->sem_perm.key;
  
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@@ -5153,13 -5110,11 +5118,11 @@@ static int selinux_sem_associate(struc
  {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
-       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
  
        isec = sma->sem_perm.security;
  
-       COMMON_AUDIT_DATA_INIT(&ad, IPC);
-       ad.selinux_audit_data = &sad;
+       ad.type = LSM_AUDIT_DATA_IPC;
        ad.u.ipc_id = sma->sem_perm.key;
  
        return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@@ -5339,8 -5294,23 +5302,23 @@@ static int selinux_setprocattr(struct t
                }
                error = security_context_to_sid(value, size, &sid);
                if (error == -EINVAL && !strcmp(name, "fscreate")) {
-                       if (!capable(CAP_MAC_ADMIN))
+                       if (!capable(CAP_MAC_ADMIN)) {
+                               struct audit_buffer *ab;
+                               size_t audit_size;
+                               /* We strip a nul only if it is at the end, otherwise the
+                                * context contains a nul and we should audit that */
+                               if (str[size - 1] == '\0')
+                                       audit_size = size - 1;
+                               else
+                                       audit_size = size;
+                               ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
+                               audit_log_format(ab, "op=fscreate invalid_context=");
+                               audit_log_n_untrustedstring(ab, value, audit_size);
+                               audit_log_end(ab);
                                return error;
+                       }
                        error = security_context_to_sid_force(value, size,
                                                              &sid);
                }
@@@ -5600,7 -5570,7 +5578,7 @@@ static struct security_operations selin
        .file_send_sigiotask =          selinux_file_send_sigiotask,
        .file_receive =                 selinux_file_receive,
  
-       .dentry_open =                  selinux_dentry_open,
+       .file_open =                    selinux_file_open,
  
        .task_create =                  selinux_task_create,
        .cred_alloc_blank =             selinux_cred_alloc_blank,
diff --combined security/smack/smack.h
  #include <linux/lsm_audit.h>
  
  /*
 + * Smack labels were limited to 23 characters for a long time.
 + */
 +#define SMK_LABELLEN  24
 +#define SMK_LONGLABEL 256
 +
 +/*
 + * Maximum number of bytes for the levels in a CIPSO IP option.
   * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
   * bigger than can be used, and 24 is the next lower multiple
   * of 8, and there are too many issues if there isn't space set
   * aside for the terminating null byte.
   */
 -#define SMK_MAXLEN    23
 -#define SMK_LABELLEN  (SMK_MAXLEN+1)
 +#define SMK_CIPSOLEN  24
  
  struct superblock_smack {
        char            *smk_root;
@@@ -72,7 -66,6 +72,7 @@@ struct task_smack 
  
  #define       SMK_INODE_INSTANT       0x01    /* inode is instantiated */
  #define       SMK_INODE_TRANSMUTE     0x02    /* directory is transmuting */
 +#define       SMK_INODE_CHANGED       0x04    /* smack was transmuted */
  
  /*
   * A label access rule.
@@@ -85,6 -78,15 +85,6 @@@ struct smack_rule 
  };
  
  /*
 - * An entry in the table mapping smack values to
 - * CIPSO level/category-set values.
 - */
 -struct smack_cipso {
 -      int     smk_level;
 -      char    smk_catset[SMK_LABELLEN];
 -};
 -
 -/*
   * An entry in the table identifying hosts.
   */
  struct smk_netlbladdr {
   * interfaces don't. The secid should go away when all of
   * these components have been repaired.
   *
 - * If there is a cipso value associated with the label it
 - * gets stored here, too. This will most likely be rare as
 - * the cipso direct mapping in used internally.
 + * The cipso value associated with the label gets stored here, too.
   *
   * Keep the access rules for this subject label here so that
   * the entire set of rules does not need to be examined every
   * time.
   */
  struct smack_known {
 -      struct list_head        list;
 -      char                    smk_known[SMK_LABELLEN];
 -      u32                     smk_secid;
 -      struct smack_cipso      *smk_cipso;
 -      spinlock_t              smk_cipsolock;  /* for changing cipso map */
 -      struct list_head        smk_rules;      /* access rules */
 -      struct mutex            smk_rules_lock; /* lock for the rules */
 +      struct list_head                list;
 +      char                            *smk_known;
 +      u32                             smk_secid;
 +      struct netlbl_lsm_secattr       smk_netlabel;   /* on wire labels */
 +      struct list_head                smk_rules;      /* access rules */
 +      struct mutex                    smk_rules_lock; /* lock for rules */
  };
  
  /*
  #define SMACK_CIPSO_DOI_DEFAULT               3       /* Historical */
  #define SMACK_CIPSO_DOI_INVALID               -1      /* Not a DOI */
  #define SMACK_CIPSO_DIRECT_DEFAULT    250     /* Arbitrary */
 +#define SMACK_CIPSO_MAPPED_DEFAULT    251     /* Also arbitrary */
  #define SMACK_CIPSO_MAXCATVAL         63      /* Bigger gets harder */
  #define SMACK_CIPSO_MAXLEVEL            255     /* CIPSO 2.2 standard */
  #define SMACK_CIPSO_MAXCATNUM           239     /* CIPSO 2.2 standard */
@@@ -211,9 -215,10 +211,9 @@@ struct inode_smack *new_inode_smack(cha
  int smk_access_entry(char *, char *, struct list_head *);
  int smk_access(char *, char *, int, struct smk_audit_info *);
  int smk_curacc(char *, u32, struct smk_audit_info *);
 -int smack_to_cipso(const char *, struct smack_cipso *);
 -char *smack_from_cipso(u32, char *);
  char *smack_from_secid(const u32);
 -void smk_parse_smack(const char *string, int len, char *smack);
 +char *smk_parse_smack(const char *string, int len);
 +int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int);
  char *smk_import(const char *, int);
  struct smack_known *smk_import_entry(const char *, int);
  struct smack_known *smk_find_entry(const char *);
@@@ -223,7 -228,6 +223,7 @@@ u32 smack_to_secid(const char *)
   * Shared data.
   */
  extern int smack_cipso_direct;
 +extern int smack_cipso_mapped;
  extern char *smack_net_ambient;
  extern char *smack_onlycap;
  extern const char *smack_cipso_option;
@@@ -235,13 -239,24 +235,13 @@@ extern struct smack_known smack_known_i
  extern struct smack_known smack_known_star;
  extern struct smack_known smack_known_web;
  
 +extern struct mutex   smack_known_lock;
  extern struct list_head smack_known_list;
  extern struct list_head smk_netlbladdr_list;
  
  extern struct security_operations smack_ops;
  
  /*
 - * Stricly for CIPSO level manipulation.
 - * Set the category bit number in a smack label sized buffer.
 - */
 -static inline void smack_catset_bit(int cat, char *catsetp)
 -{
 -      if (cat > SMK_LABELLEN * 8)
 -              return;
 -
 -      catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
 -}
 -
 -/*
   * Is the directory transmuting?
   */
  static inline int smk_inode_transmutable(const struct inode *isp)
@@@ -304,7 -319,7 +304,7 @@@ void smack_log(char *subject_label, cha
  static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
                               char type)
  {
-       memset(a, 0, sizeof(*a));
+       memset(&a->sad, 0, sizeof(a->sad));
        a->a.type = type;
        a->a.smack_audit_data = &a->sad;
        a->a.smack_audit_data->function = func;
@@@ -30,6 -30,7 +30,6 @@@
  #include <linux/slab.h>
  #include <linux/mutex.h>
  #include <linux/pipe_fs_i.h>
 -#include <net/netlabel.h>
  #include <net/cipso_ipv4.h>
  #include <linux/audit.h>
  #include <linux/magic.h>
  static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp)
  {
        int rc;
 -      char in[SMK_LABELLEN];
 +      char *buffer;
 +      char *result = NULL;
  
        if (ip->i_op->getxattr == NULL)
                return NULL;
  
 -      rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN);
 -      if (rc < 0)
 +      buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
 +      if (buffer == NULL)
                return NULL;
  
 -      return smk_import(in, rc);
 +      rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL);
 +      if (rc > 0)
 +              result = smk_import(buffer, rc);
 +
 +      kfree(buffer);
 +
 +      return result;
  }
  
  /**
@@@ -85,7 -79,7 +85,7 @@@ struct inode_smack *new_inode_smack(cha
  {
        struct inode_smack *isp;
  
 -      isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL);
 +      isp = kzalloc(sizeof(struct inode_smack), GFP_NOFS);
        if (isp == NULL)
                return NULL;
  
@@@ -562,14 -556,13 +562,14 @@@ static int smack_inode_init_security(st
                                     void **value, size_t *len)
  {
        struct smack_known *skp;
 +      struct inode_smack *issp = inode->i_security;
        char *csp = smk_of_current();
        char *isp = smk_of_inode(inode);
        char *dsp = smk_of_inode(dir);
        int may;
  
        if (name) {
 -              *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
 +              *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS);
                if (*name == NULL)
                        return -ENOMEM;
        }
                 * If the access rule allows transmutation and
                 * the directory requests transmutation then
                 * by all means transmute.
 +               * Mark the inode as changed.
                 */
                if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
 -                  smk_inode_transmutable(dir))
 +                  smk_inode_transmutable(dir)) {
                        isp = dsp;
 +                      issp->smk_flags |= SMK_INODE_CHANGED;
 +              }
  
 -              *value = kstrdup(isp, GFP_KERNEL);
 +              *value = kstrdup(isp, GFP_NOFS);
                if (*value == NULL)
                        return -ENOMEM;
        }
@@@ -831,7 -821,7 +831,7 @@@ static int smack_inode_setxattr(struct 
                 * check label validity here so import wont fail on
                 * post_setxattr
                 */
 -              if (size == 0 || size >= SMK_LABELLEN ||
 +              if (size == 0 || size >= SMK_LONGLABEL ||
                    smk_import(value, size) == NULL)
                        rc = -EINVAL;
        } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
@@@ -1359,7 -1349,7 +1359,7 @@@ static int smack_file_receive(struct fi
  }
  
  /**
-  * smack_dentry_open - Smack dentry open processing
+  * smack_file_open - Smack dentry open processing
   * @file: the object
   * @cred: unused
   *
   *
   * Returns 0
   */
- static int smack_dentry_open(struct file *file, const struct cred *cred)
+ static int smack_file_open(struct file *file, const struct cred *cred)
  {
        struct inode_smack *isp = file->f_path.dentry->d_inode->i_security;
  
@@@ -1830,6 -1820,65 +1830,6 @@@ static char *smack_host_label(struct so
  }
  
  /**
 - * smack_set_catset - convert a capset to netlabel mls categories
 - * @catset: the Smack categories
 - * @sap: where to put the netlabel categories
 - *
 - * Allocates and fills attr.mls.cat
 - */
 -static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
 -{
 -      unsigned char *cp;
 -      unsigned char m;
 -      int cat;
 -      int rc;
 -      int byte;
 -
 -      if (!catset)
 -              return;
 -
 -      sap->flags |= NETLBL_SECATTR_MLS_CAT;
 -      sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
 -      sap->attr.mls.cat->startbit = 0;
 -
 -      for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
 -              for (m = 0x80; m != 0; m >>= 1, cat++) {
 -                      if ((m & *cp) == 0)
 -                              continue;
 -                      rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
 -                                                        cat, GFP_ATOMIC);
 -              }
 -}
 -
 -/**
 - * smack_to_secattr - fill a secattr from a smack value
 - * @smack: the smack value
 - * @nlsp: where the result goes
 - *
 - * Casey says that CIPSO is good enough for now.
 - * It can be used to effect.
 - * It can also be abused to effect when necessary.
 - * Apologies to the TSIG group in general and GW in particular.
 - */
 -static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
 -{
 -      struct smack_cipso cipso;
 -      int rc;
 -
 -      nlsp->domain = smack;
 -      nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
 -
 -      rc = smack_to_cipso(smack, &cipso);
 -      if (rc == 0) {
 -              nlsp->attr.mls.lvl = cipso.smk_level;
 -              smack_set_catset(cipso.smk_catset, nlsp);
 -      } else {
 -              nlsp->attr.mls.lvl = smack_cipso_direct;
 -              smack_set_catset(smack, nlsp);
 -      }
 -}
 -
 -/**
   * smack_netlabel - Set the secattr on a socket
   * @sk: the socket
   * @labeled: socket label scheme
   */
  static int smack_netlabel(struct sock *sk, int labeled)
  {
 +      struct smack_known *skp;
        struct socket_smack *ssp = sk->sk_security;
 -      struct netlbl_lsm_secattr secattr;
        int rc = 0;
  
        /*
            labeled == SMACK_UNLABELED_SOCKET)
                netlbl_sock_delattr(sk);
        else {
 -              netlbl_secattr_init(&secattr);
 -              smack_to_secattr(ssp->smk_out, &secattr);
 -              rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr);
 -              netlbl_secattr_destroy(&secattr);
 +              skp = smk_find_entry(ssp->smk_out);
 +              rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel);
        }
  
        bh_unlock_sock(sk);
@@@ -1888,19 -1939,18 +1888,19 @@@ static int smack_netlabel_send(struct s
        char *hostsp;
        struct socket_smack *ssp = sk->sk_security;
        struct smk_audit_info ad;
 -      struct lsm_network_audit net;
  
        rcu_read_lock();
        hostsp = smack_host_label(sap);
        if (hostsp != NULL) {
 -              sk_lbl = SMACK_UNLABELED_SOCKET;
  #ifdef CONFIG_AUDIT
 +              struct lsm_network_audit net;
 +
                smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
                ad.a.u.net->family = sap->sin_family;
                ad.a.u.net->dport = sap->sin_port;
                ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
  #endif
 +              sk_lbl = SMACK_UNLABELED_SOCKET;
                rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
        } else {
                sk_lbl = SMACK_CIPSO_SOCKET;
@@@ -1934,7 -1984,7 +1934,7 @@@ static int smack_inode_setsecurity(stru
        struct socket *sock;
        int rc = 0;
  
 -      if (value == NULL || size > SMK_LABELLEN || size == 0)
 +      if (value == NULL || size > SMK_LONGLABEL || size == 0)
                return -EACCES;
  
        sp = smk_import(value, size);
@@@ -2501,7 -2551,6 +2501,7 @@@ static void smack_d_instantiate(struct 
        char *final;
        char trattr[TRANS_TRUE_SIZE];
        int transflag = 0;
 +      int rc;
        struct dentry *dp;
  
        if (inode == NULL)
                 */
                dp = dget(opt_dentry);
                fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp);
 -              if (fetched != NULL) {
 +              if (fetched != NULL)
                        final = fetched;
 -                      if (S_ISDIR(inode->i_mode)) {
 -                              trattr[0] = '\0';
 -                              inode->i_op->getxattr(dp,
 +
 +              /*
 +               * Transmuting directory
 +               */
 +              if (S_ISDIR(inode->i_mode)) {
 +                      /*
 +                       * If this is a new directory and the label was
 +                       * transmuted when the inode was initialized
 +                       * set the transmute attribute on the directory
 +                       * and mark the inode.
 +                       *
 +                       * If there is a transmute attribute on the
 +                       * directory mark the inode.
 +                       */
 +                      if (isp->smk_flags & SMK_INODE_CHANGED) {
 +                              isp->smk_flags &= ~SMK_INODE_CHANGED;
 +                              rc = inode->i_op->setxattr(dp,
                                        XATTR_NAME_SMACKTRANSMUTE,
 -                                      trattr, TRANS_TRUE_SIZE);
 -                              if (strncmp(trattr, TRANS_TRUE,
 -                                          TRANS_TRUE_SIZE) == 0)
 -                                      transflag = SMK_INODE_TRANSMUTE;
 +                                      TRANS_TRUE, TRANS_TRUE_SIZE,
 +                                      0);
 +                      } else {
 +                              rc = inode->i_op->getxattr(dp,
 +                                      XATTR_NAME_SMACKTRANSMUTE, trattr,
 +                                      TRANS_TRUE_SIZE);
 +                              if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
 +                                                     TRANS_TRUE_SIZE) != 0)
 +                                      rc = -EINVAL;
                        }
 +                      if (rc >= 0)
 +                              transflag = SMK_INODE_TRANSMUTE;
                }
                isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
                isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
@@@ -2730,7 -2758,7 +2730,7 @@@ static int smack_setprocattr(struct tas
        if (!capable(CAP_MAC_ADMIN))
                return -EPERM;
  
 -      if (value == NULL || size == 0 || size >= SMK_LABELLEN)
 +      if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
                return -EINVAL;
  
        if (strcmp(name, "current") != 0)
@@@ -2781,14 -2809,11 +2781,14 @@@ static int smack_unix_stream_connect(st
        struct socket_smack *osp = other->sk_security;
        struct socket_smack *nsp = newsk->sk_security;
        struct smk_audit_info ad;
 -      struct lsm_network_audit net;
        int rc = 0;
  
 +#ifdef CONFIG_AUDIT
 +      struct lsm_network_audit net;
 +
        smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
        smk_ad_setfield_u_net_sk(&ad, other);
 +#endif
  
        if (!capable(CAP_MAC_OVERRIDE))
                rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
@@@ -2817,14 -2842,11 +2817,14 @@@ static int smack_unix_may_send(struct s
        struct socket_smack *ssp = sock->sk->sk_security;
        struct socket_smack *osp = other->sk->sk_security;
        struct smk_audit_info ad;
 -      struct lsm_network_audit net;
        int rc = 0;
  
 +#ifdef CONFIG_AUDIT
 +      struct lsm_network_audit net;
 +
        smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
        smk_ad_setfield_u_net_sk(&ad, other->sk);
 +#endif
  
        if (!capable(CAP_MAC_OVERRIDE))
                rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
@@@ -2866,9 -2888,10 +2866,9 @@@ static int smack_socket_sendmsg(struct 
  static char *smack_from_secattr(struct netlbl_lsm_secattr *sap,
                                struct socket_smack *ssp)
  {
 -      struct smack_known *skp;
 -      char smack[SMK_LABELLEN];
 +      struct smack_known *kp;
        char *sp;
 -      int pcat;
 +      int found = 0;
  
        if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) {
                /*
                 * If there are flags but no level netlabel isn't
                 * behaving the way we expect it to.
                 *
 -               * Get the categories, if any
 +               * Look it up in the label table
                 * Without guidance regarding the smack value
                 * for the packet fall back on the network
                 * ambient value.
                 */
 -              memset(smack, '\0', SMK_LABELLEN);
 -              if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
 -                      for (pcat = -1;;) {
 -                              pcat = netlbl_secattr_catmap_walk(
 -                                      sap->attr.mls.cat, pcat + 1);
 -                              if (pcat < 0)
 -                                      break;
 -                              smack_catset_bit(pcat, smack);
 -                      }
 -              /*
 -               * If it is CIPSO using smack direct mapping
 -               * we are already done. WeeHee.
 -               */
 -              if (sap->attr.mls.lvl == smack_cipso_direct) {
 -                      /*
 -                       * The label sent is usually on the label list.
 -                       *
 -                       * If it is not we may still want to allow the
 -                       * delivery.
 -                       *
 -                       * If the recipient is accepting all packets
 -                       * because it is using the star ("*") label
 -                       * for SMACK64IPIN provide the web ("@") label
 -                       * so that a directed response will succeed.
 -                       * This is not very correct from a MAC point
 -                       * of view, but gets around the problem that
 -                       * locking prevents adding the newly discovered
 -                       * label to the list.
 -                       * The case where the recipient is not using
 -                       * the star label should obviously fail.
 -                       * The easy way to do this is to provide the
 -                       * star label as the subject label.
 -                       */
 -                      skp = smk_find_entry(smack);
 -                      if (skp != NULL)
 -                              return skp->smk_known;
 -                      if (ssp != NULL &&
 -                          ssp->smk_in == smack_known_star.smk_known)
 -                              return smack_known_web.smk_known;
 -                      return smack_known_star.smk_known;
 +              rcu_read_lock();
 +              list_for_each_entry(kp, &smack_known_list, list) {
 +                      if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl)
 +                              continue;
 +                      if (memcmp(sap->attr.mls.cat,
 +                              kp->smk_netlabel.attr.mls.cat,
 +                              SMK_CIPSOLEN) != 0)
 +                              continue;
 +                      found = 1;
 +                      break;
                }
 -              /*
 -               * Look it up in the supplied table if it is not
 -               * a direct mapping.
 -               */
 -              sp = smack_from_cipso(sap->attr.mls.lvl, smack);
 -              if (sp != NULL)
 -                      return sp;
 +              rcu_read_unlock();
 +
 +              if (found)
 +                      return kp->smk_known;
 +
                if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
                        return smack_known_web.smk_known;
                return smack_known_star.smk_known;
@@@ -2938,9 -2993,7 +2938,9 @@@ static int smack_socket_sock_rcv_skb(st
        char *csp;
        int rc;
        struct smk_audit_info ad;
 +#ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
 +#endif
        if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
                return 0;
  
@@@ -3096,18 -3149,14 +3096,18 @@@ static int smack_inet_conn_request(stru
                                   struct request_sock *req)
  {
        u16 family = sk->sk_family;
 +      struct smack_known *skp;
        struct socket_smack *ssp = sk->sk_security;
        struct netlbl_lsm_secattr secattr;
        struct sockaddr_in addr;
        struct iphdr *hdr;
        char *sp;
 +      char *hsp;
        int rc;
        struct smk_audit_info ad;
 +#ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
 +#endif
  
        /* handle mapped IPv4 packets arriving via IPv6 sockets */
        if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
        hdr = ip_hdr(skb);
        addr.sin_addr.s_addr = hdr->saddr;
        rcu_read_lock();
 -      if (smack_host_label(&addr) == NULL) {
 -              rcu_read_unlock();
 -              netlbl_secattr_init(&secattr);
 -              smack_to_secattr(sp, &secattr);
 -              rc = netlbl_req_setattr(req, &secattr);
 -              netlbl_secattr_destroy(&secattr);
 -      } else {
 -              rcu_read_unlock();
 +      hsp = smack_host_label(&addr);
 +      rcu_read_unlock();
 +
 +      if (hsp == NULL) {
 +              skp = smk_find_entry(sp);
 +              rc = netlbl_req_setattr(req, &skp->smk_netlabel);
 +      } else
                netlbl_req_delattr(req);
 -      }
  
        return rc;
  }
@@@ -3338,7 -3389,7 +3338,7 @@@ static int smack_audit_rule_match(u32 s
        char *rule = vrule;
  
        if (!rule) {
 -              audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR,
 +              audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR,
                          "Smack: missing rule\n");
                return -ENOENT;
        }
@@@ -3487,7 -3538,7 +3487,7 @@@ struct security_operations smack_ops = 
        .file_send_sigiotask =          smack_file_send_sigiotask,
        .file_receive =                 smack_file_receive,
  
-       .dentry_open =                  smack_dentry_open,
+       .file_open =                    smack_file_open,
  
        .cred_alloc_blank =             smack_cred_alloc_blank,
        .cred_free =                    smack_cred_free,
  };
  
  
 -static __init void init_smack_know_list(void)
 +static __init void init_smack_known_list(void)
  {
 +      /*
 +       * Initialize rule list locks
 +       */
 +      mutex_init(&smack_known_huh.smk_rules_lock);
 +      mutex_init(&smack_known_hat.smk_rules_lock);
 +      mutex_init(&smack_known_floor.smk_rules_lock);
 +      mutex_init(&smack_known_star.smk_rules_lock);
 +      mutex_init(&smack_known_invalid.smk_rules_lock);
 +      mutex_init(&smack_known_web.smk_rules_lock);
 +      /*
 +       * Initialize rule lists
 +       */
 +      INIT_LIST_HEAD(&smack_known_huh.smk_rules);
 +      INIT_LIST_HEAD(&smack_known_hat.smk_rules);
 +      INIT_LIST_HEAD(&smack_known_star.smk_rules);
 +      INIT_LIST_HEAD(&smack_known_floor.smk_rules);
 +      INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
 +      INIT_LIST_HEAD(&smack_known_web.smk_rules);
 +      /*
 +       * Create the known labels list
 +       */
        list_add(&smack_known_huh.list, &smack_known_list);
        list_add(&smack_known_hat.list, &smack_known_list);
        list_add(&smack_known_star.list, &smack_known_list);
@@@ -3635,8 -3665,16 +3635,8 @@@ static __init int smack_init(void
        cred = (struct cred *) current->cred;
        cred->security = tsp;
  
 -      /* initialize the smack_know_list */
 -      init_smack_know_list();
 -      /*
 -       * Initialize locks
 -       */
 -      spin_lock_init(&smack_known_huh.smk_cipsolock);
 -      spin_lock_init(&smack_known_hat.smk_cipsolock);
 -      spin_lock_init(&smack_known_star.smk_cipsolock);
 -      spin_lock_init(&smack_known_floor.smk_cipsolock);
 -      spin_lock_init(&smack_known_invalid.smk_cipsolock);
 +      /* initialize the smack_known_list */
 +      init_smack_known_list();
  
        /*
         * Register with LSM