summaryrefslogtreecommitdiff
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c356
1 files changed, 230 insertions, 126 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 94c45a1531a4..5b5231068516 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -51,6 +51,7 @@
#include <linux/tty.h>
#include <net/icmp.h>
#include <net/ip.h> /* for local_port_range[] */
+#include <net/sock.h>
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
#include <net/net_namespace.h>
#include <net/netlabel.h>
@@ -60,7 +61,7 @@
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h> /* for network interface checks */
-#include <linux/netlink.h>
+#include <net/netlink.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/dccp.h>
@@ -80,6 +81,7 @@
#include <linux/syslog.h>
#include <linux/user_namespace.h>
#include <linux/export.h>
+#include <linux/security.h>
#include <linux/msg.h>
#include <linux/shm.h>
@@ -283,13 +285,14 @@ static void superblock_free_security(struct super_block *sb)
/* The file system's label must be initialized prior to use. */
-static const char *labeling_behaviors[6] = {
+static const char *labeling_behaviors[7] = {
"uses xattr",
"uses transition SIDs",
"uses task SIDs",
"uses genfs_contexts",
"not configured for labeling",
"uses mountpoint labeling",
+ "uses native labeling",
};
static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@ -551,7 +554,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
* labeling information.
*/
static int selinux_set_mnt_opts(struct super_block *sb,
- struct security_mnt_opts *opts)
+ struct security_mnt_opts *opts,
+ unsigned long kern_flags,
+ unsigned long *set_kern_flags)
{
const struct cred *cred = current_cred();
int rc = 0, i;
@@ -579,6 +584,12 @@ static int selinux_set_mnt_opts(struct super_block *sb,
"before the security server is initialized\n");
goto out;
}
+ if (kern_flags && !set_kern_flags) {
+ /* Specifying internal flags without providing a place to
+ * place the results is not allowed */
+ rc = -EINVAL;
+ goto out;
+ }
/*
* Binary mount data FS will come through this function twice. Once
@@ -669,14 +680,21 @@ static int selinux_set_mnt_opts(struct super_block *sb,
if (strcmp(sb->s_type->name, "proc") == 0)
sbsec->flags |= SE_SBPROC;
- /* Determine the labeling behavior to use for this filesystem type. */
- rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid);
- if (rc) {
- printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
- __func__, sb->s_type->name, rc);
- goto out;
+ if (!sbsec->behavior) {
+ /*
+ * Determine the labeling behavior to use for this
+ * filesystem type.
+ */
+ rc = security_fs_use((sbsec->flags & SE_SBPROC) ?
+ "proc" : sb->s_type->name,
+ &sbsec->behavior, &sbsec->sid);
+ if (rc) {
+ printk(KERN_WARNING
+ "%s: security_fs_use(%s) returned %d\n",
+ __func__, sb->s_type->name, rc);
+ goto out;
+ }
}
-
/* sets the context of the superblock for the fs being mounted. */
if (fscontext_sid) {
rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
@@ -691,6 +709,11 @@ static int selinux_set_mnt_opts(struct super_block *sb,
* sets the label used on all file below the mountpoint, and will set
* the superblock context if not already set.
*/
+ if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
+ sbsec->behavior = SECURITY_FS_USE_NATIVE;
+ *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
+ }
+
if (context_sid) {
if (!fscontext_sid) {
rc = may_context_mount_sb_relabel(context_sid, sbsec,
@@ -722,7 +745,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
}
if (defcontext_sid) {
- if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
+ if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
+ sbsec->behavior != SECURITY_FS_USE_NATIVE) {
rc = -EINVAL;
printk(KERN_WARNING "SELinux: defcontext option is "
"invalid for this filesystem type\n");
@@ -750,7 +774,37 @@ out_double_mount:
goto out;
}
-static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
+static int selinux_cmp_sb_context(const struct super_block *oldsb,
+ const struct super_block *newsb)
+{
+ struct superblock_security_struct *old = oldsb->s_security;
+ struct superblock_security_struct *new = newsb->s_security;
+ char oldflags = old->flags & SE_MNTMASK;
+ char newflags = new->flags & SE_MNTMASK;
+
+ if (oldflags != newflags)
+ goto mismatch;
+ if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
+ goto mismatch;
+ if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
+ goto mismatch;
+ if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
+ goto mismatch;
+ if (oldflags & ROOTCONTEXT_MNT) {
+ struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
+ struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
+ if (oldroot->sid != newroot->sid)
+ goto mismatch;
+ }
+ return 0;
+mismatch:
+ printk(KERN_WARNING "SELinux: mount invalid. Same superblock, "
+ "different security settings for (dev %s, "
+ "type %s)\n", newsb->s_id, newsb->s_type->name);
+ return -EBUSY;
+}
+
+static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb)
{
const struct superblock_security_struct *oldsbsec = oldsb->s_security;
@@ -765,14 +819,14 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
* mount options. thus we can safely deal with this superblock later
*/
if (!ss_initialized)
- return;
+ return 0;
/* how can we clone if the old one wasn't set up?? */
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
- /* if fs is reusing a sb, just let its options stand... */
+ /* if fs is reusing a sb, make sure that the contexts match */
if (newsbsec->flags & SE_SBINITIALIZED)
- return;
+ return selinux_cmp_sb_context(oldsb, newsb);
mutex_lock(&newsbsec->lock);
@@ -805,6 +859,7 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
sb_finish_set_opts(newsb);
mutex_unlock(&newsbsec->lock);
+ return 0;
}
static int selinux_parse_opts_str(char *options,
@@ -948,7 +1003,7 @@ static int superblock_doinit(struct super_block *sb, void *data)
goto out_err;
out:
- rc = selinux_set_mnt_opts(sb, &opts);
+ rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
out_err:
security_free_mnt_opts(&opts);
@@ -1190,6 +1245,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
}
switch (sbsec->behavior) {
+ case SECURITY_FS_USE_NATIVE:
+ break;
case SECURITY_FS_USE_XATTR:
if (!inode->i_op->getxattr) {
isec->sid = sbsec->def_sid;
@@ -1445,7 +1502,7 @@ static int cred_has_capability(const struct cred *cred,
rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
if (audit == SECURITY_CAP_AUDIT) {
- int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
+ int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
if (rc2)
return rc2;
}
@@ -1468,8 +1525,7 @@ static int task_has_system(struct task_struct *tsk,
static int inode_has_perm(const struct cred *cred,
struct inode *inode,
u32 perms,
- struct common_audit_data *adp,
- unsigned flags)
+ struct common_audit_data *adp)
{
struct inode_security_struct *isec;
u32 sid;
@@ -1482,7 +1538,7 @@ static int inode_has_perm(const struct cred *cred,
sid = cred_sid(cred);
isec = inode->i_security;
- return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
+ return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1497,7 +1553,7 @@ static inline int dentry_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
- return inode_has_perm(cred, inode, av, &ad, 0);
+ return inode_has_perm(cred, inode, av, &ad);
}
/* Same as inode_has_perm, but pass explicit audit data containing
@@ -1512,7 +1568,19 @@ static inline int path_has_perm(const struct cred *cred,
ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = *path;
- return inode_has_perm(cred, inode, av, &ad, 0);
+ return inode_has_perm(cred, inode, av, &ad);
+}
+
+/* Same as path_has_perm, but uses the inode from the file struct. */
+static inline int file_path_has_perm(const struct cred *cred,
+ struct file *file,
+ u32 av)
+{
+ struct common_audit_data ad;
+
+ ad.type = LSM_AUDIT_DATA_PATH;
+ ad.u.path = file->f_path;
+ return inode_has_perm(cred, file_inode(file), av, &ad);
}
/* Check whether a task can use an open file descriptor to
@@ -1528,7 +1596,7 @@ static int file_has_perm(const struct cred *cred,
u32 av)
{
struct file_security_struct *fsec = file->f_security;
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
struct common_audit_data ad;
u32 sid = cred_sid(cred);
int rc;
@@ -1548,7 +1616,7 @@ static int file_has_perm(const struct cred *cred,
/* av is zero if only checking access to the descriptor. */
rc = 0;
if (av)
- rc = inode_has_perm(cred, inode, av, &ad, 0);
+ rc = inode_has_perm(cred, inode, av, &ad);
out:
return rc;
@@ -1957,7 +2025,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 inode *inode = bprm->file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(bprm->file);
int rc;
rc = cap_bprm_set_creds(bprm);
@@ -2088,15 +2156,19 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
return (atsecure || cap_bprm_secureexec(bprm));
}
+static int match_file(const void *p, struct file *file, unsigned fd)
+{
+ return file_has_perm(p, file, file_to_av(file)) ? fd + 1 : 0;
+}
+
/* Derived from fs/exec.c:flush_old_files. */
static inline void flush_unauthorized_files(const struct cred *cred,
struct files_struct *files)
{
struct file *file, *devnull = NULL;
struct tty_struct *tty;
- struct fdtable *fdt;
- long j = -1;
int drop_tty = 0;
+ unsigned n;
tty = get_current_tty();
if (tty) {
@@ -2105,14 +2177,14 @@ static inline void flush_unauthorized_files(const struct cred *cred,
struct tty_file_private *file_priv;
/* Revalidate access to controlling tty.
- 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. */
+ Use file_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;
- if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
+ if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
drop_tty = 1;
}
spin_unlock(&tty_files_lock);
@@ -2123,58 +2195,19 @@ static inline void flush_unauthorized_files(const struct cred *cred,
no_tty();
/* Revalidate access to inherited open files. */
- spin_lock(&files->file_lock);
- for (;;) {
- unsigned long set, i;
- int fd;
-
- j++;
- i = j * BITS_PER_LONG;
- fdt = files_fdtable(files);
- if (i >= fdt->max_fds)
- break;
- set = fdt->open_fds[j];
- if (!set)
- continue;
- spin_unlock(&files->file_lock);
- for ( ; set ; i++, set >>= 1) {
- if (set & 1) {
- file = fget(i);
- if (!file)
- continue;
- if (file_has_perm(cred,
- file,
- file_to_av(file))) {
- sys_close(i);
- fd = get_unused_fd();
- if (fd != i) {
- if (fd >= 0)
- put_unused_fd(fd);
- fput(file);
- continue;
- }
- if (devnull) {
- get_file(devnull);
- } else {
- devnull = dentry_open(
- &selinux_null,
- O_RDWR, cred);
- if (IS_ERR(devnull)) {
- devnull = NULL;
- put_unused_fd(fd);
- fput(file);
- continue;
- }
- }
- fd_install(fd, devnull);
- }
- fput(file);
- }
- }
- spin_lock(&files->file_lock);
+ n = iterate_fd(files, 0, match_file, cred);
+ if (!n) /* none found? */
+ return;
- }
- spin_unlock(&files->file_lock);
+ devnull = dentry_open(&selinux_null, O_RDWR, cred);
+ if (IS_ERR(devnull))
+ devnull = NULL;
+ /* replace all the matching ones with this */
+ do {
+ replace_fd(n - 1, devnull, 0);
+ } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
+ if (devnull)
+ fput(devnull);
}
/*
@@ -2483,9 +2516,9 @@ static int selinux_sb_statfs(struct dentry *dentry)
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
}
-static int selinux_mount(char *dev_name,
+static int selinux_mount(const char *dev_name,
struct path *path,
- char *type,
+ const char *type,
unsigned long flags,
void *data)
{
@@ -2518,8 +2551,43 @@ static void selinux_inode_free_security(struct inode *inode)
inode_free_security(inode);
}
+static int selinux_dentry_init_security(struct dentry *dentry, int mode,
+ struct qstr *name, void **ctx,
+ u32 *ctxlen)
+{
+ const struct cred *cred = current_cred();
+ struct task_security_struct *tsec;
+ struct inode_security_struct *dsec;
+ struct superblock_security_struct *sbsec;
+ struct inode *dir = dentry->d_parent->d_inode;
+ u32 newsid;
+ int rc;
+
+ tsec = cred->security;
+ dsec = dir->i_security;
+ sbsec = dir->i_sb->s_security;
+
+ if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
+ newsid = tsec->create_sid;
+ } else {
+ rc = security_transition_sid(tsec->sid, dsec->sid,
+ inode_mode_to_security_class(mode),
+ name,
+ &newsid);
+ if (rc) {
+ printk(KERN_WARNING
+ "%s: security_transition_sid failed, rc=%d\n",
+ __func__, -rc);
+ return rc;
+ }
+ }
+
+ return security_sid_to_context(newsid, (char **)ctx, ctxlen);
+}
+
static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
- const struct qstr *qstr, char **name,
+ const struct qstr *qstr,
+ const char **name,
void **value, size_t *len)
{
const struct task_security_struct *tsec = current_security();
@@ -2527,7 +2595,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
struct superblock_security_struct *sbsec;
u32 sid, newsid, clen;
int rc;
- char *namep = NULL, *context;
+ char *context;
dsec = dir->i_security;
sbsec = dir->i_sb->s_security;
@@ -2563,19 +2631,13 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
return -EOPNOTSUPP;
- if (name) {
- namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
- if (!namep)
- return -ENOMEM;
- *name = namep;
- }
+ if (name)
+ *name = XATTR_SELINUX_SUFFIX;
if (value && len) {
rc = security_sid_to_context_force(newsid, &context, &clen);
- if (rc) {
- kfree(namep);
+ if (rc)
return rc;
- }
*value = context;
*len = clen;
}
@@ -2791,11 +2853,16 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
/* 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;
+ if (value) {
+ str = value;
+ if (str[size - 1] == '\0')
+ audit_size = size - 1;
+ else
+ audit_size = size;
+ } else {
+ str = "";
+ audit_size = 0;
+ }
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);
@@ -2847,7 +2914,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
return;
}
+ isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
+ isec->initialized = 1;
+
return;
}
@@ -2935,6 +3005,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
if (rc)
return rc;
+ isec->sclass = inode_mode_to_security_class(inode->i_mode);
isec->sid = newsid;
isec->initialized = 1;
return 0;
@@ -2959,7 +3030,7 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
static int selinux_revalidate_file_permission(struct file *file, int mask)
{
const struct cred *cred = current_cred();
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
/* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */
if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
@@ -2971,7 +3042,7 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
static int selinux_file_permission(struct file *file, int mask)
{
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
struct file_security_struct *fsec = file->f_security;
struct inode_security_struct *isec = inode->i_security;
u32 sid = current_sid();
@@ -3165,11 +3236,6 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
switch (cmd) {
case F_SETFL:
- if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
- err = -EINVAL;
- break;
- }
-
if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
err = file_has_perm(cred, file, FILE__WRITE);
break;
@@ -3180,6 +3246,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_GETFL:
case F_GETOWN:
case F_GETSIG:
+ case F_GETOWNER_UIDS:
/* Just check FD__USE permission */
err = file_has_perm(cred, file, 0);
break;
@@ -3191,10 +3258,6 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
case F_SETLK64:
case F_SETLKW64:
#endif
- if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
- err = -EINVAL;
- break;
- }
err = file_has_perm(cred, file, FILE__LOCK);
break;
}
@@ -3247,7 +3310,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
struct inode_security_struct *isec;
fsec = file->f_security;
- isec = file->f_path.dentry->d_inode->i_security;
+ isec = file_inode(file)->i_security;
/*
* Save inode label and policy sequence number
* at open-time so that selinux_file_permission
@@ -3265,7 +3328,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
* new inode label or new policy.
* This check is not redundant - do not remove.
*/
- return path_has_perm(cred, &file->f_path, open_file_to_av(file));
+ return file_path_has_perm(cred, file, open_file_to_av(file));
}
/* task security operations */
@@ -4401,6 +4464,11 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
}
+static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+ skb_set_owner_w(skb, sk);
+}
+
static int selinux_secmark_relabel_packet(u32 sid)
{
const struct task_security_struct *__tsec;
@@ -4428,6 +4496,24 @@ static void selinux_req_classify_flow(const struct request_sock *req,
fl->flowi_secid = req->secid;
}
+static int selinux_tun_dev_alloc_security(void **security)
+{
+ struct tun_security_struct *tunsec;
+
+ tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
+ if (!tunsec)
+ return -ENOMEM;
+ tunsec->sid = current_sid();
+
+ *security = tunsec;
+ return 0;
+}
+
+static void selinux_tun_dev_free_security(void *security)
+{
+ kfree(security);
+}
+
static int selinux_tun_dev_create(void)
{
u32 sid = current_sid();
@@ -4443,8 +4529,17 @@ static int selinux_tun_dev_create(void)
NULL);
}
-static void selinux_tun_dev_post_create(struct sock *sk)
+static int selinux_tun_dev_attach_queue(void *security)
{
+ struct tun_security_struct *tunsec = security;
+
+ return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
+ TUN_SOCKET__ATTACH_QUEUE, NULL);
+}
+
+static int selinux_tun_dev_attach(struct sock *sk, void *security)
+{
+ struct tun_security_struct *tunsec = security;
struct sk_security_struct *sksec = sk->sk_security;
/* we don't currently perform any NetLabel based labeling here and it
@@ -4454,20 +4549,19 @@ static void selinux_tun_dev_post_create(struct sock *sk)
* cause confusion to the TUN user that had no idea network labeling
* protocols were being used */
- /* see the comments in selinux_tun_dev_create() about why we don't use
- * the sockcreate SID here */
-
- sksec->sid = current_sid();
+ sksec->sid = tunsec->sid;
sksec->sclass = SECCLASS_TUN_SOCKET;
+
+ return 0;
}
-static int selinux_tun_dev_attach(struct sock *sk)
+static int selinux_tun_dev_open(void *security)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct tun_security_struct *tunsec = security;
u32 sid = current_sid();
int err;
- err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
+ err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
TUN_SOCKET__RELABELFROM, NULL);
if (err)
return err;
@@ -4475,8 +4569,7 @@ static int selinux_tun_dev_attach(struct sock *sk)
TUN_SOCKET__RELABELTO, NULL);
if (err)
return err;
-
- sksec->sid = sid;
+ tunsec->sid = sid;
return 0;
}
@@ -4488,7 +4581,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
struct nlmsghdr *nlh;
struct sk_security_struct *sksec = sk->sk_security;
- if (skb->len < NLMSG_SPACE(0)) {
+ if (skb->len < NLMSG_HDRLEN) {
err = -EINVAL;
goto out;
}
@@ -5396,6 +5489,11 @@ abort_change:
return error;
}
+static int selinux_ismaclabel(const char *name)
+{
+ return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
+}
+
static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
{
return security_sid_to_context(secid, secdata, seclen);
@@ -5538,6 +5636,7 @@ static struct security_operations selinux_ops = {
.sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
.sb_parse_opts_str = selinux_parse_opts_str,
+ .dentry_init_security = selinux_dentry_init_security,
.inode_alloc_security = selinux_inode_alloc_security,
.inode_free_security = selinux_inode_free_security,
@@ -5633,6 +5732,7 @@ static struct security_operations selinux_ops = {
.getprocattr = selinux_getprocattr,
.setprocattr = selinux_setprocattr,
+ .ismaclabel = selinux_ismaclabel,
.secid_to_secctx = selinux_secid_to_secctx,
.secctx_to_secid = selinux_secctx_to_secid,
.release_secctx = selinux_release_secctx,
@@ -5671,9 +5771,13 @@ static struct security_operations selinux_ops = {
.secmark_refcount_inc = selinux_secmark_refcount_inc,
.secmark_refcount_dec = selinux_secmark_refcount_dec,
.req_classify_flow = selinux_req_classify_flow,
+ .tun_dev_alloc_security = selinux_tun_dev_alloc_security,
+ .tun_dev_free_security = selinux_tun_dev_free_security,
.tun_dev_create = selinux_tun_dev_create,
- .tun_dev_post_create = selinux_tun_dev_post_create,
+ .tun_dev_attach_queue = selinux_tun_dev_attach_queue,
.tun_dev_attach = selinux_tun_dev_attach,
+ .tun_dev_open = selinux_tun_dev_open,
+ .skb_owned_by = selinux_skb_owned_by,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,