|
@@ -17,6 +17,7 @@
|
|
* Paul Moore <paul@paul-moore.com>
|
|
* Paul Moore <paul@paul-moore.com>
|
|
* Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
|
|
* Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
|
|
* Yuichi Nakamura <ynakam@hitachisoft.jp>
|
|
* Yuichi Nakamura <ynakam@hitachisoft.jp>
|
|
|
|
+ * Copyright (C) 2016 Mellanox Technologies
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2,
|
|
* it under the terms of the GNU General Public License version 2,
|
|
@@ -90,6 +91,7 @@
|
|
#include "netif.h"
|
|
#include "netif.h"
|
|
#include "netnode.h"
|
|
#include "netnode.h"
|
|
#include "netport.h"
|
|
#include "netport.h"
|
|
|
|
+#include "ibpkey.h"
|
|
#include "xfrm.h"
|
|
#include "xfrm.h"
|
|
#include "netlabel.h"
|
|
#include "netlabel.h"
|
|
#include "audit.h"
|
|
#include "audit.h"
|
|
@@ -171,6 +173,16 @@ static int selinux_netcache_avc_callback(u32 event)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int selinux_lsm_notifier_avc_callback(u32 event)
|
|
|
|
+{
|
|
|
|
+ if (event == AVC_CALLBACK_RESET) {
|
|
|
|
+ sel_ib_pkey_flush();
|
|
|
|
+ call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* initialise the security for the init task
|
|
* initialise the security for the init task
|
|
*/
|
|
*/
|
|
@@ -398,18 +410,6 @@ static void superblock_free_security(struct super_block *sb)
|
|
kfree(sbsec);
|
|
kfree(sbsec);
|
|
}
|
|
}
|
|
|
|
|
|
-/* The file system's label must be initialized prior to use. */
|
|
|
|
-
|
|
|
|
-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 inline int inode_doinit(struct inode *inode)
|
|
static inline int inode_doinit(struct inode *inode)
|
|
{
|
|
{
|
|
return inode_doinit_with_dentry(inode, NULL);
|
|
return inode_doinit_with_dentry(inode, NULL);
|
|
@@ -524,13 +524,17 @@ static int sb_finish_set_opts(struct super_block *sb)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
|
|
|
|
- printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
|
|
|
|
- sb->s_id, sb->s_type->name);
|
|
|
|
-
|
|
|
|
sbsec->flags |= SE_SBINITIALIZED;
|
|
sbsec->flags |= SE_SBINITIALIZED;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
|
|
|
|
+ * leave the flag untouched because sb_clone_mnt_opts might be handing
|
|
|
|
+ * us a superblock that needs the flag to be cleared.
|
|
|
|
+ */
|
|
if (selinux_is_sblabel_mnt(sb))
|
|
if (selinux_is_sblabel_mnt(sb))
|
|
sbsec->flags |= SBLABEL_MNT;
|
|
sbsec->flags |= SBLABEL_MNT;
|
|
|
|
+ else
|
|
|
|
+ sbsec->flags &= ~SBLABEL_MNT;
|
|
|
|
|
|
/* Initialize the root inode. */
|
|
/* Initialize the root inode. */
|
|
rc = inode_doinit_with_dentry(root_inode, root);
|
|
rc = inode_doinit_with_dentry(root_inode, root);
|
|
@@ -809,6 +813,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
|
|
sbsec->flags |= SE_SBPROC | SE_SBGENFS;
|
|
sbsec->flags |= SE_SBPROC | SE_SBGENFS;
|
|
|
|
|
|
if (!strcmp(sb->s_type->name, "debugfs") ||
|
|
if (!strcmp(sb->s_type->name, "debugfs") ||
|
|
|
|
+ !strcmp(sb->s_type->name, "tracefs") ||
|
|
!strcmp(sb->s_type->name, "sysfs") ||
|
|
!strcmp(sb->s_type->name, "sysfs") ||
|
|
!strcmp(sb->s_type->name, "pstore"))
|
|
!strcmp(sb->s_type->name, "pstore"))
|
|
sbsec->flags |= SE_SBGENFS;
|
|
sbsec->flags |= SE_SBGENFS;
|
|
@@ -963,8 +968,11 @@ mismatch:
|
|
}
|
|
}
|
|
|
|
|
|
static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
- struct super_block *newsb)
|
|
|
|
|
|
+ struct super_block *newsb,
|
|
|
|
+ unsigned long kern_flags,
|
|
|
|
+ unsigned long *set_kern_flags)
|
|
{
|
|
{
|
|
|
|
+ int rc = 0;
|
|
const struct superblock_security_struct *oldsbsec = oldsb->s_security;
|
|
const struct superblock_security_struct *oldsbsec = oldsb->s_security;
|
|
struct superblock_security_struct *newsbsec = newsb->s_security;
|
|
struct superblock_security_struct *newsbsec = newsb->s_security;
|
|
|
|
|
|
@@ -979,6 +987,13 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
if (!ss_initialized)
|
|
if (!ss_initialized)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Specifying internal flags without providing a place to
|
|
|
|
+ * place the results is not allowed.
|
|
|
|
+ */
|
|
|
|
+ if (kern_flags && !set_kern_flags)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
/* how can we clone if the old one wasn't set up?? */
|
|
/* how can we clone if the old one wasn't set up?? */
|
|
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
|
|
BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
|
|
|
|
|
|
@@ -994,6 +1009,18 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
newsbsec->def_sid = oldsbsec->def_sid;
|
|
newsbsec->def_sid = oldsbsec->def_sid;
|
|
newsbsec->behavior = oldsbsec->behavior;
|
|
newsbsec->behavior = oldsbsec->behavior;
|
|
|
|
|
|
|
|
+ if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
|
|
|
|
+ !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
|
|
|
|
+ rc = security_fs_use(newsb);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
|
|
|
|
+ newsbsec->behavior = SECURITY_FS_USE_NATIVE;
|
|
|
|
+ *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (set_context) {
|
|
if (set_context) {
|
|
u32 sid = oldsbsec->mntpoint_sid;
|
|
u32 sid = oldsbsec->mntpoint_sid;
|
|
|
|
|
|
@@ -1013,8 +1040,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
|
|
}
|
|
}
|
|
|
|
|
|
sb_finish_set_opts(newsb);
|
|
sb_finish_set_opts(newsb);
|
|
|
|
+out:
|
|
mutex_unlock(&newsbsec->lock);
|
|
mutex_unlock(&newsbsec->lock);
|
|
- return 0;
|
|
|
|
|
|
+ return rc;
|
|
}
|
|
}
|
|
|
|
|
|
static int selinux_parse_opts_str(char *options,
|
|
static int selinux_parse_opts_str(char *options,
|
|
@@ -2063,8 +2091,9 @@ static inline u32 file_to_av(struct file *file)
|
|
static inline u32 open_file_to_av(struct file *file)
|
|
static inline u32 open_file_to_av(struct file *file)
|
|
{
|
|
{
|
|
u32 av = file_to_av(file);
|
|
u32 av = file_to_av(file);
|
|
|
|
+ struct inode *inode = file_inode(file);
|
|
|
|
|
|
- if (selinux_policycap_openperm)
|
|
|
|
|
|
+ if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
|
|
av |= FILE__OPEN;
|
|
av |= FILE__OPEN;
|
|
|
|
|
|
return av;
|
|
return av;
|
|
@@ -3059,6 +3088,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
|
|
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
|
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
|
{
|
|
{
|
|
const struct cred *cred = current_cred();
|
|
const struct cred *cred = current_cred();
|
|
|
|
+ struct inode *inode = d_backing_inode(dentry);
|
|
unsigned int ia_valid = iattr->ia_valid;
|
|
unsigned int ia_valid = iattr->ia_valid;
|
|
__u32 av = FILE__WRITE;
|
|
__u32 av = FILE__WRITE;
|
|
|
|
|
|
@@ -3074,8 +3104,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
|
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
|
|
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
|
|
return dentry_has_perm(cred, dentry, FILE__SETATTR);
|
|
return dentry_has_perm(cred, dentry, FILE__SETATTR);
|
|
|
|
|
|
- if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE)
|
|
|
|
- && !(ia_valid & ATTR_FILE))
|
|
|
|
|
|
+ if (selinux_policycap_openperm &&
|
|
|
|
+ inode->i_sb->s_magic != SOCKFS_MAGIC &&
|
|
|
|
+ (ia_valid & ATTR_SIZE) &&
|
|
|
|
+ !(ia_valid & ATTR_FILE))
|
|
av |= FILE__OPEN;
|
|
av |= FILE__OPEN;
|
|
|
|
|
|
return dentry_has_perm(cred, dentry, av);
|
|
return dentry_has_perm(cred, dentry, av);
|
|
@@ -3107,6 +3139,18 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
|
|
return dentry_has_perm(cred, dentry, FILE__SETATTR);
|
|
return dentry_has_perm(cred, dentry, FILE__SETATTR);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool has_cap_mac_admin(bool audit)
|
|
|
|
+{
|
|
|
|
+ const struct cred *cred = current_cred();
|
|
|
|
+ int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
|
|
|
|
+
|
|
|
|
+ if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
|
|
|
|
+ return false;
|
|
|
|
+ if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
|
|
|
|
+ return false;
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
|
static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
|
const void *value, size_t size, int flags)
|
|
const void *value, size_t size, int flags)
|
|
{
|
|
{
|
|
@@ -3138,7 +3182,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
|
|
|
|
|
|
rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
|
|
rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
|
|
if (rc == -EINVAL) {
|
|
if (rc == -EINVAL) {
|
|
- if (!capable(CAP_MAC_ADMIN)) {
|
|
|
|
|
|
+ if (!has_cap_mac_admin(true)) {
|
|
struct audit_buffer *ab;
|
|
struct audit_buffer *ab;
|
|
size_t audit_size;
|
|
size_t audit_size;
|
|
const char *str;
|
|
const char *str;
|
|
@@ -3264,13 +3308,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
|
|
* and lack of permission just means that we fall back to the
|
|
* and lack of permission just means that we fall back to the
|
|
* in-core context value, not a denial.
|
|
* in-core context value, not a denial.
|
|
*/
|
|
*/
|
|
- error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
|
|
|
|
- SECURITY_CAP_NOAUDIT);
|
|
|
|
- if (!error)
|
|
|
|
- error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
|
|
|
|
- SECURITY_CAP_NOAUDIT, true);
|
|
|
|
isec = inode_security(inode);
|
|
isec = inode_security(inode);
|
|
- if (!error)
|
|
|
|
|
|
+ if (has_cap_mac_admin(false))
|
|
error = security_sid_to_context_force(isec->sid, &context,
|
|
error = security_sid_to_context_force(isec->sid, &context,
|
|
&size);
|
|
&size);
|
|
else
|
|
else
|
|
@@ -3550,6 +3589,18 @@ static int selinux_mmap_addr(unsigned long addr)
|
|
static int selinux_mmap_file(struct file *file, unsigned long reqprot,
|
|
static int selinux_mmap_file(struct file *file, unsigned long reqprot,
|
|
unsigned long prot, unsigned long flags)
|
|
unsigned long prot, unsigned long flags)
|
|
{
|
|
{
|
|
|
|
+ struct common_audit_data ad;
|
|
|
|
+ int rc;
|
|
|
|
+
|
|
|
|
+ if (file) {
|
|
|
|
+ ad.type = LSM_AUDIT_DATA_FILE;
|
|
|
|
+ ad.u.file = file;
|
|
|
|
+ rc = inode_has_perm(current_cred(), file_inode(file),
|
|
|
|
+ FILE__MAP, &ad);
|
|
|
|
+ if (rc)
|
|
|
|
+ return rc;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (selinux_checkreqprot)
|
|
if (selinux_checkreqprot)
|
|
prot = reqprot;
|
|
prot = reqprot;
|
|
|
|
|
|
@@ -3710,7 +3761,8 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
|
|
|
|
|
|
/* task security operations */
|
|
/* task security operations */
|
|
|
|
|
|
-static int selinux_task_create(unsigned long clone_flags)
|
|
|
|
|
|
+static int selinux_task_alloc(struct task_struct *task,
|
|
|
|
+ unsigned long clone_flags)
|
|
{
|
|
{
|
|
u32 sid = current_sid();
|
|
u32 sid = current_sid();
|
|
|
|
|
|
@@ -5918,7 +5970,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
|
|
}
|
|
}
|
|
error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
|
|
error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
|
|
if (error == -EINVAL && !strcmp(name, "fscreate")) {
|
|
if (error == -EINVAL && !strcmp(name, "fscreate")) {
|
|
- if (!capable(CAP_MAC_ADMIN)) {
|
|
|
|
|
|
+ if (!has_cap_mac_admin(true)) {
|
|
struct audit_buffer *ab;
|
|
struct audit_buffer *ab;
|
|
size_t audit_size;
|
|
size_t audit_size;
|
|
|
|
|
|
@@ -6128,7 +6180,70 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
|
|
*_buffer = context;
|
|
*_buffer = context;
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_SECURITY_INFINIBAND
|
|
|
|
+static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
|
|
|
|
+{
|
|
|
|
+ struct common_audit_data ad;
|
|
|
|
+ int err;
|
|
|
|
+ u32 sid = 0;
|
|
|
|
+ struct ib_security_struct *sec = ib_sec;
|
|
|
|
+ struct lsm_ibpkey_audit ibpkey;
|
|
|
|
+
|
|
|
|
+ err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ ad.type = LSM_AUDIT_DATA_IBPKEY;
|
|
|
|
+ ibpkey.subnet_prefix = subnet_prefix;
|
|
|
|
+ ibpkey.pkey = pkey_val;
|
|
|
|
+ ad.u.ibpkey = &ibpkey;
|
|
|
|
+ return avc_has_perm(sec->sid, sid,
|
|
|
|
+ SECCLASS_INFINIBAND_PKEY,
|
|
|
|
+ INFINIBAND_PKEY__ACCESS, &ad);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
|
|
|
|
+ u8 port_num)
|
|
|
|
+{
|
|
|
|
+ struct common_audit_data ad;
|
|
|
|
+ int err;
|
|
|
|
+ u32 sid = 0;
|
|
|
|
+ struct ib_security_struct *sec = ib_sec;
|
|
|
|
+ struct lsm_ibendport_audit ibendport;
|
|
|
|
+
|
|
|
|
+ err = security_ib_endport_sid(dev_name, port_num, &sid);
|
|
|
|
+
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ ad.type = LSM_AUDIT_DATA_IBENDPORT;
|
|
|
|
+ strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
|
|
|
|
+ ibendport.port = port_num;
|
|
|
|
+ ad.u.ibendport = &ibendport;
|
|
|
|
+ return avc_has_perm(sec->sid, sid,
|
|
|
|
+ SECCLASS_INFINIBAND_ENDPORT,
|
|
|
|
+ INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int selinux_ib_alloc_security(void **ib_sec)
|
|
|
|
+{
|
|
|
|
+ struct ib_security_struct *sec;
|
|
|
|
|
|
|
|
+ sec = kzalloc(sizeof(*sec), GFP_KERNEL);
|
|
|
|
+ if (!sec)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+ sec->sid = current_sid();
|
|
|
|
+
|
|
|
|
+ *ib_sec = sec;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void selinux_ib_free_security(void *ib_sec)
|
|
|
|
+{
|
|
|
|
+ kfree(ib_sec);
|
|
|
|
+}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
|
static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
|
@@ -6213,7 +6328,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
|
|
|
|
|
LSM_HOOK_INIT(file_open, selinux_file_open),
|
|
LSM_HOOK_INIT(file_open, selinux_file_open),
|
|
|
|
|
|
- LSM_HOOK_INIT(task_create, selinux_task_create),
|
|
|
|
|
|
+ LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
|
|
LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
|
|
LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
|
|
LSM_HOOK_INIT(cred_free, selinux_cred_free),
|
|
LSM_HOOK_INIT(cred_free, selinux_cred_free),
|
|
LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
|
|
LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
|
|
@@ -6315,7 +6430,13 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
|
|
LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
|
|
LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
|
|
LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
|
|
LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
|
|
LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
|
|
LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
|
|
-
|
|
|
|
|
|
+#ifdef CONFIG_SECURITY_INFINIBAND
|
|
|
|
+ LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
|
|
|
|
+ LSM_HOOK_INIT(ib_endport_manage_subnet,
|
|
|
|
+ selinux_ib_endport_manage_subnet),
|
|
|
|
+ LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
|
|
|
|
+ LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
|
|
|
|
+#endif
|
|
#ifdef CONFIG_SECURITY_NETWORK_XFRM
|
|
#ifdef CONFIG_SECURITY_NETWORK_XFRM
|
|
LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
|
|
LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
|
|
LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
|
|
LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
|
|
@@ -6379,6 +6500,9 @@ static __init int selinux_init(void)
|
|
if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
|
|
if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
|
|
panic("SELinux: Unable to register AVC netcache callback\n");
|
|
panic("SELinux: Unable to register AVC netcache callback\n");
|
|
|
|
|
|
|
|
+ if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
|
|
|
|
+ panic("SELinux: Unable to register AVC LSM notifier callback\n");
|
|
|
|
+
|
|
if (selinux_enforcing)
|
|
if (selinux_enforcing)
|
|
printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
|
|
printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
|
|
else
|
|
else
|
|
@@ -6448,6 +6572,23 @@ static struct nf_hook_ops selinux_nf_ops[] = {
|
|
#endif /* IPV6 */
|
|
#endif /* IPV6 */
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static int __net_init selinux_nf_register(struct net *net)
|
|
|
|
+{
|
|
|
|
+ return nf_register_net_hooks(net, selinux_nf_ops,
|
|
|
|
+ ARRAY_SIZE(selinux_nf_ops));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void __net_exit selinux_nf_unregister(struct net *net)
|
|
|
|
+{
|
|
|
|
+ nf_unregister_net_hooks(net, selinux_nf_ops,
|
|
|
|
+ ARRAY_SIZE(selinux_nf_ops));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct pernet_operations selinux_net_ops = {
|
|
|
|
+ .init = selinux_nf_register,
|
|
|
|
+ .exit = selinux_nf_unregister,
|
|
|
|
+};
|
|
|
|
+
|
|
static int __init selinux_nf_ip_init(void)
|
|
static int __init selinux_nf_ip_init(void)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
@@ -6457,13 +6598,12 @@ static int __init selinux_nf_ip_init(void)
|
|
|
|
|
|
printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
|
|
printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
|
|
|
|
|
|
- err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
|
|
|
|
|
|
+ err = register_pernet_subsys(&selinux_net_ops);
|
|
if (err)
|
|
if (err)
|
|
- panic("SELinux: nf_register_hooks: error %d\n", err);
|
|
|
|
|
|
+ panic("SELinux: register_pernet_subsys: error %d\n", err);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
-
|
|
|
|
__initcall(selinux_nf_ip_init);
|
|
__initcall(selinux_nf_ip_init);
|
|
|
|
|
|
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
|
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
|
|
@@ -6471,7 +6611,7 @@ static void selinux_nf_ip_exit(void)
|
|
{
|
|
{
|
|
printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
|
|
printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
|
|
|
|
|
|
- nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
|
|
|
|
|
|
+ unregister_pernet_subsys(&selinux_net_ops);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|