]> Pileus Git - ~andy/linux/blobdiff - security/selinux/hooks.c
SELinux: delay initialization of audit data in selinux_inode_permission
[~andy/linux] / security / selinux / hooks.c
index 15c6c567468b6f4a12d00b8a4f5756311ddbc532..c99027dc0b36f7c7033e21f493231b237df14a23 100644 (file)
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/tracehook.h>
 #include <linux/errno.h>
-#include <linux/ext2_fs.h>
 #include <linux/sched.h>
 #include <linux/security.h>
 #include <linux/xattr.h>
@@ -1421,6 +1420,7 @@ static int cred_has_capability(const struct cred *cred,
                               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);
@@ -1428,6 +1428,7 @@ static int cred_has_capability(const struct cred *cred,
        int rc;
 
        COMMON_AUDIT_DATA_INIT(&ad, CAP);
+       ad.selinux_audit_data = &sad;
        ad.tsk = current;
        ad.u.cap = cap;
 
@@ -1493,9 +1494,11 @@ static int inode_has_perm_noadp(const struct cred *cred,
                                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);
 }
 
@@ -1508,9 +1511,11 @@ static inline int dentry_has_perm(const struct cred *cred,
 {
        struct inode *inode = dentry->d_inode;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
        ad.u.dentry = dentry;
+       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
@@ -1523,9 +1528,11 @@ static inline int path_has_perm(const struct cred *cred,
 {
        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.u.path = *path;
+       ad.selinux_audit_data = &sad;
        return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
@@ -1544,11 +1551,13 @@ static int file_has_perm(const struct cred *cred,
        struct file_security_struct *fsec = file->f_security;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = cred_sid(cred);
        int rc;
 
        COMMON_AUDIT_DATA_INIT(&ad, PATH);
        ad.u.path = file->f_path;
+       ad.selinux_audit_data = &sad;
 
        if (sid != fsec->sid) {
                rc = avc_has_perm(sid, fsec->sid,
@@ -1578,6 +1587,7 @@ 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;
@@ -1588,6 +1598,7 @@ static int may_create(struct inode *dir,
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
        ad.u.dentry = dentry;
+       ad.selinux_audit_data = &sad;
 
        rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
                          DIR__ADD_NAME | DIR__SEARCH,
@@ -1632,6 +1643,7 @@ 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;
@@ -1641,6 +1653,7 @@ static int may_link(struct inode *dir,
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
        ad.u.dentry = dentry;
+       ad.selinux_audit_data = &sad;
 
        av = DIR__SEARCH;
        av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1675,6 +1688,7 @@ static inline int may_rename(struct inode *old_dir,
 {
        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;
@@ -1686,6 +1700,7 @@ static inline int may_rename(struct inode *old_dir,
        new_dsec = new_dir->i_security;
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
 
        ad.u.dentry = old_dentry;
        rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
@@ -1971,6 +1986,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
        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;
 
@@ -2010,6 +2026,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
        }
 
        COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.selinux_audit_data = &sad;
        ad.u.path = bprm->file->f_path;
 
        if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
@@ -2099,6 +2116,7 @@ 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;
@@ -2136,6 +2154,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
        /* Revalidate access to inherited open files. */
 
        COMMON_AUDIT_DATA_INIT(&ad, INODE);
+       ad.selinux_audit_data = &sad;
 
        spin_lock(&files->file_lock);
        for (;;) {
@@ -2473,6 +2492,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        int rc;
 
        rc = superblock_doinit(sb, data);
@@ -2484,6 +2504,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
                return 0;
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
        ad.u.dentry = sb->s_root;
        return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
 }
@@ -2492,8 +2513,10 @@ static int selinux_sb_statfs(struct dentry *dentry)
 {
        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.u.dentry = dentry->d_sb->s_root;
        return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
@@ -2657,9 +2680,15 @@ static int selinux_inode_permission(struct inode *inode, int mask)
 {
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        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);
@@ -2668,21 +2697,42 @@ static int selinux_inode_permission(struct inode *inode, int mask)
        if (!mask)
                return 0;
 
+       validate_creds(cred);
+
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+
+       perms = file_mask_to_av(inode->i_mode, mask);
+
+       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;
+
        COMMON_AUDIT_DATA_INIT(&ad, INODE);
+       ad.selinux_audit_data = &sad;
        ad.u.inode = inode;
 
        if (from_access)
-               ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
-
-       perms = file_mask_to_av(inode->i_mode, mask);
+               ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
 
-       return inode_has_perm(cred, inode, perms, &ad, flags);
+       rc2 = slow_avc_audit(sid, isec->sid, isec->sclass, perms,
+                            audited, denied, &ad, 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) {
@@ -2696,7 +2746,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
                        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)
@@ -2738,6 +2791,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
        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;
 
@@ -2752,6 +2806,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
                return -EPERM;
 
        COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.selinux_audit_data = &sad;
        ad.u.dentry = dentry;
 
        rc = avc_has_perm(sid, isec->sid, isec->sclass,
@@ -2761,8 +2816,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
 
        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)
@@ -2942,7 +3014,7 @@ static int selinux_file_permission(struct file *file, int mask)
 
        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);
@@ -2971,15 +3043,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
        /* fall through */
        case FIGETBSZ:
        /* fall through */
-       case EXT2_IOC_GETFLAGS:
+       case FS_IOC_GETFLAGS:
        /* fall through */
-       case EXT2_IOC_GETVERSION:
+       case FS_IOC_GETVERSION:
                error = file_has_perm(cred, file, FILE__GETATTR);
                break;
 
-       case EXT2_IOC_SETFLAGS:
+       case FS_IOC_SETFLAGS:
        /* fall through */
-       case EXT2_IOC_SETVERSION:
+       case FS_IOC_SETVERSION:
                error = file_has_perm(cred, file, FILE__SETATTR);
                break;
 
@@ -3201,7 +3273,7 @@ static int selinux_file_receive(struct file *file)
        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;
@@ -3346,10 +3418,12 @@ static int selinux_kernel_module_request(char *kmod_name)
 {
        u32 sid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
 
        sid = task_sid(current);
 
        COMMON_AUDIT_DATA_INIT(&ad, KMOD);
+       ad.selinux_audit_data = &sad;
        ad.u.kmod_name = kmod_name;
 
        return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
@@ -3488,8 +3562,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
        if (ihlen < sizeof(_iph))
                goto out;
 
-       ad->u.net.v4info.saddr = ih->saddr;
-       ad->u.net.v4info.daddr = ih->daddr;
+       ad->u.net->v4info.saddr = ih->saddr;
+       ad->u.net->v4info.daddr = ih->daddr;
        ret = 0;
 
        if (proto)
@@ -3507,8 +3581,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                if (th == NULL)
                        break;
 
-               ad->u.net.sport = th->source;
-               ad->u.net.dport = th->dest;
+               ad->u.net->sport = th->source;
+               ad->u.net->dport = th->dest;
                break;
        }
 
@@ -3523,8 +3597,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                if (uh == NULL)
                        break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
+               ad->u.net->sport = uh->source;
+               ad->u.net->dport = uh->dest;
                break;
        }
 
@@ -3539,8 +3613,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                if (dh == NULL)
                        break;
 
-               ad->u.net.sport = dh->dccph_sport;
-               ad->u.net.dport = dh->dccph_dport;
+               ad->u.net->sport = dh->dccph_sport;
+               ad->u.net->dport = dh->dccph_dport;
                break;
        }
 
@@ -3567,8 +3641,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
        if (ip6 == NULL)
                goto out;
 
-       ad->u.net.v6info.saddr = ip6->saddr;
-       ad->u.net.v6info.daddr = ip6->daddr;
+       ad->u.net->v6info.saddr = ip6->saddr;
+       ad->u.net->v6info.daddr = ip6->daddr;
        ret = 0;
 
        nexthdr = ip6->nexthdr;
@@ -3588,8 +3662,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                if (th == NULL)
                        break;
 
-               ad->u.net.sport = th->source;
-               ad->u.net.dport = th->dest;
+               ad->u.net->sport = th->source;
+               ad->u.net->dport = th->dest;
                break;
        }
 
@@ -3600,8 +3674,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                if (uh == NULL)
                        break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
+               ad->u.net->sport = uh->source;
+               ad->u.net->dport = uh->dest;
                break;
        }
 
@@ -3612,8 +3686,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                if (dh == NULL)
                        break;
 
-               ad->u.net.sport = dh->dccph_sport;
-               ad->u.net.dport = dh->dccph_dport;
+               ad->u.net->sport = dh->dccph_sport;
+               ad->u.net->dport = dh->dccph_dport;
                break;
        }
 
@@ -3633,13 +3707,13 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
        char *addrp;
        int ret;
 
-       switch (ad->u.net.family) {
+       switch (ad->u.net->family) {
        case PF_INET:
                ret = selinux_parse_skb_ipv4(skb, ad, proto);
                if (ret)
                        goto parse_error;
-               addrp = (char *)(src ? &ad->u.net.v4info.saddr :
-                                      &ad->u.net.v4info.daddr);
+               addrp = (char *)(src ? &ad->u.net->v4info.saddr :
+                                      &ad->u.net->v4info.daddr);
                goto okay;
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -3647,8 +3721,8 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
                ret = selinux_parse_skb_ipv6(skb, ad, proto);
                if (ret)
                        goto parse_error;
-               addrp = (char *)(src ? &ad->u.net.v6info.saddr :
-                                      &ad->u.net.v6info.daddr);
+               addrp = (char *)(src ? &ad->u.net->v6info.saddr :
+                                      &ad->u.net->v6info.daddr);
                goto okay;
 #endif /* IPV6 */
        default:
@@ -3722,13 +3796,17 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
 {
        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.u.net.sk = sk;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->sk = sk;
 
        return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
 }
@@ -3806,6 +3884,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                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;
                unsigned short snum;
@@ -3832,8 +3912,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                if (err)
                                        goto out;
                                COMMON_AUDIT_DATA_INIT(&ad, NET);
-                               ad.u.net.sport = htons(snum);
-                               ad.u.net.family = family;
+                               ad.selinux_audit_data = &sad;
+                               ad.u.net = &net;
+                               ad.u.net->sport = htons(snum);
+                               ad.u.net->family = family;
                                err = avc_has_perm(sksec->sid, sid,
                                                   sksec->sclass,
                                                   SOCKET__NAME_BIND, &ad);
@@ -3865,13 +3947,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                        goto out;
 
                COMMON_AUDIT_DATA_INIT(&ad, NET);
-               ad.u.net.sport = htons(snum);
-               ad.u.net.family = family;
+               ad.selinux_audit_data = &sad;
+               ad.u.net = &net;
+               ad.u.net->sport = htons(snum);
+               ad.u.net->family = family;
 
                if (family == PF_INET)
-                       ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
+                       ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
                else
-                       ad.u.net.v6info.saddr = addr6->sin6_addr;
+                       ad.u.net->v6info.saddr = addr6->sin6_addr;
 
                err = avc_has_perm(sksec->sid, sid,
                                   sksec->sclass, node_perm, &ad);
@@ -3898,6 +3982,8 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
        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;
                unsigned short snum;
@@ -3923,8 +4009,10 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
                       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
 
                COMMON_AUDIT_DATA_INIT(&ad, NET);
-               ad.u.net.dport = htons(snum);
-               ad.u.net.family = sk->sk_family;
+               ad.selinux_audit_data = &sad;
+               ad.u.net = &net;
+               ad.u.net->dport = htons(snum);
+               ad.u.net->family = sk->sk_family;
                err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
                if (err)
                        goto out;
@@ -4013,10 +4101,14 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
        struct sk_security_struct *sksec_other = other->sk_security;
        struct sk_security_struct *sksec_new = newsk->sk_security;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        int err;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.sk = other;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->sk = other;
 
        err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
                           sksec_other->sclass,
@@ -4043,9 +4135,13 @@ static int selinux_socket_unix_may_send(struct socket *sock,
        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.u.net.sk = other->sk;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->sk = other->sk;
 
        return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
                            &ad);
@@ -4081,11 +4177,15 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
        struct sk_security_struct *sksec = sk->sk_security;
        u32 sk_sid = sksec->sid;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
+       struct lsm_network_audit net = {0,};
        char *addrp;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = skb->skb_iif;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = skb->skb_iif;
+       ad.u.net->family = family;
        err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
        if (err)
                return err;
@@ -4112,6 +4212,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *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;
        u8 peerlbl_active;
@@ -4136,8 +4238,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                return 0;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = skb->skb_iif;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = skb->skb_iif;
+       ad.u.net->family = family;
        err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
        if (err)
                return err;
@@ -4472,6 +4576,8 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
        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;
        u8 peerlbl_active;
@@ -4489,8 +4595,10 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
                return NF_DROP;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = ifindex;
+       ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
                return NF_DROP;
 
@@ -4577,6 +4685,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
        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;
 
@@ -4585,8 +4695,10 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
        sksec = sk->sk_security;
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = ifindex;
+       ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
                return NF_DROP;
 
@@ -4608,6 +4720,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
        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;
        u8 peerlbl_active;
@@ -4654,8 +4768,10 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
        }
 
        COMMON_AUDIT_DATA_INIT(&ad, NET);
-       ad.u.net.netif = ifindex;
-       ad.u.net.family = family;
+       ad.selinux_audit_data = &sad;
+       ad.u.net = &net;
+       ad.u.net->netif = ifindex;
+       ad.u.net->family = family;
        if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
                return NF_DROP;
 
@@ -4770,11 +4886,13 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
 {
        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.u.ipc_id = ipc_perms->key;
 
        return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@ -4795,6 +4913,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -4805,6 +4924,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
        isec = msq->q_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4825,11 +4945,13 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
 {
        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.u.ipc_id = msq->q_perm.key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4869,6 +4991,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        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;
 
@@ -4890,6 +5013,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
        }
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        /* Can this process write to the queue? */
@@ -4914,6 +5038,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
        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;
 
@@ -4921,6 +5046,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
        msec = msg->security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = msq->q_perm.key;
 
        rc = avc_has_perm(sid, isec->sid,
@@ -4936,6 +5062,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -4946,6 +5073,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
        isec = shp->shm_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = shp->shm_perm.key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -4966,11 +5094,13 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
 {
        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.u.ipc_id = shp->shm_perm.key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -5028,6 +5158,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
 {
        struct ipc_security_struct *isec;
        struct common_audit_data ad;
+       struct selinux_audit_data sad = {0,};
        u32 sid = current_sid();
        int rc;
 
@@ -5038,6 +5169,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
        isec = sma->sem_perm.security;
 
        COMMON_AUDIT_DATA_INIT(&ad, IPC);
+       ad.selinux_audit_data = &sad;
        ad.u.ipc_id = sma->sem_perm.key;
 
        rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5058,11 +5190,13 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
 {
        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.u.ipc_id = sma->sem_perm.key;
 
        return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5242,8 +5376,23 @@ static int selinux_setprocattr(struct task_struct *p,
                }
                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);
                }
@@ -5503,7 +5652,7 @@ static struct security_operations selinux_ops = {
        .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,