aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 14:26:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 14:26:35 -0400
commite24dd9ee5399747b71c1d982a484fc7601795f31 (patch)
tree14fcec8728916092a9f6dbeb0f2b8d5c5a4e5c9a /security/selinux/hooks.c
parent7391786a64dcfe9c609a1f8e2204c1abf42ded23 (diff)
parentc4758fa59285fe4dbfeab4364a6957936d040fbf (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris: - a major update for AppArmor. From JJ: * several bug fixes and cleanups * the patch to add symlink support to securityfs that was floated on the list earlier and the apparmorfs changes that make use of securityfs symlinks * it introduces the domain labeling base code that Ubuntu has been carrying for several years, with several cleanups applied. And it converts the current mediation over to using the domain labeling base, which brings domain stacking support with it. This finally will bring the base upstream code in line with Ubuntu and provide a base to upstream the new feature work that Ubuntu carries. * This does _not_ contain any of the newer apparmor mediation features/controls (mount, signals, network, keys, ...) that Ubuntu is currently carrying, all of which will be RFC'd on top of this. - Notable also is the Infiniband work in SELinux, and the new file:map permission. From Paul: "While we're down to 21 patches for v4.13 (it was 31 for v4.12), the diffstat jumps up tremendously with over 2k of line changes. Almost all of these changes are the SELinux/IB work done by Daniel Jurgens; some other noteworthy changes include a NFS v4.2 labeling fix, a new file:map permission, and reporting of policy capabilities on policy load" There's also now genfscon labeling support for tracefs, which was lost in v4.1 with the separation from debugfs. - Smack incorporates a safer socket check in file_receive, and adds a cap_capable call in privilege check. - TPM as usual has a bunch of fixes and enhancements. - Multiple calls to security_add_hooks() can now be made for the same LSM, to allow LSMs to have hook declarations across multiple files. - IMA now supports different "ima_appraise=" modes (eg. log, fix) from the boot command line. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (126 commits) apparmor: put back designators in struct initialisers seccomp: Switch from atomic_t to recount_t seccomp: Adjust selftests to avoid double-join seccomp: Clean up core dump logic IMA: update IMA policy documentation to include pcr= option ima: Log the same audit cause whenever a file has no signature ima: Simplify policy_func_show. integrity: Small code improvements ima: fix get_binary_runtime_size() ima: use ima_parse_buf() to parse template data ima: use ima_parse_buf() to parse measurements headers ima: introduce ima_parse_buf() ima: Add cgroups2 to the defaults list ima: use memdup_user_nul ima: fix up #endif comments IMA: Correct Kconfig dependencies for hash selection ima: define is_ima_appraise_enabled() ima: define Kconfig IMA_APPRAISE_BOOTPARAM option ima: define a set of appraisal rules requiring file signatures ima: extend the "ima_policy" boot command line to support multiple policies ...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c212
1 files changed, 176 insertions, 36 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 819fd6858b49..33fd061305c4 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -17,6 +17,7 @@
17 * Paul Moore <paul@paul-moore.com> 17 * Paul Moore <paul@paul-moore.com>
18 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. 18 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
19 * Yuichi Nakamura <ynakam@hitachisoft.jp> 19 * Yuichi Nakamura <ynakam@hitachisoft.jp>
20 * Copyright (C) 2016 Mellanox Technologies
20 * 21 *
21 * This program is free software; you can redistribute it and/or modify 22 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2, 23 * it under the terms of the GNU General Public License version 2,
@@ -90,6 +91,7 @@
90#include "netif.h" 91#include "netif.h"
91#include "netnode.h" 92#include "netnode.h"
92#include "netport.h" 93#include "netport.h"
94#include "ibpkey.h"
93#include "xfrm.h" 95#include "xfrm.h"
94#include "netlabel.h" 96#include "netlabel.h"
95#include "audit.h" 97#include "audit.h"
@@ -171,6 +173,16 @@ static int selinux_netcache_avc_callback(u32 event)
171 return 0; 173 return 0;
172} 174}
173 175
176static int selinux_lsm_notifier_avc_callback(u32 event)
177{
178 if (event == AVC_CALLBACK_RESET) {
179 sel_ib_pkey_flush();
180 call_lsm_notifier(LSM_POLICY_CHANGE, NULL);
181 }
182
183 return 0;
184}
185
174/* 186/*
175 * initialise the security for the init task 187 * initialise the security for the init task
176 */ 188 */
@@ -398,18 +410,6 @@ static void superblock_free_security(struct super_block *sb)
398 kfree(sbsec); 410 kfree(sbsec);
399} 411}
400 412
401/* The file system's label must be initialized prior to use. */
402
403static const char *labeling_behaviors[7] = {
404 "uses xattr",
405 "uses transition SIDs",
406 "uses task SIDs",
407 "uses genfs_contexts",
408 "not configured for labeling",
409 "uses mountpoint labeling",
410 "uses native labeling",
411};
412
413static inline int inode_doinit(struct inode *inode) 413static inline int inode_doinit(struct inode *inode)
414{ 414{
415 return inode_doinit_with_dentry(inode, NULL); 415 return inode_doinit_with_dentry(inode, NULL);
@@ -524,13 +524,17 @@ static int sb_finish_set_opts(struct super_block *sb)
524 } 524 }
525 } 525 }
526 526
527 if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
528 printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
529 sb->s_id, sb->s_type->name);
530
531 sbsec->flags |= SE_SBINITIALIZED; 527 sbsec->flags |= SE_SBINITIALIZED;
528
529 /*
530 * Explicitly set or clear SBLABEL_MNT. It's not sufficient to simply
531 * leave the flag untouched because sb_clone_mnt_opts might be handing
532 * us a superblock that needs the flag to be cleared.
533 */
532 if (selinux_is_sblabel_mnt(sb)) 534 if (selinux_is_sblabel_mnt(sb))
533 sbsec->flags |= SBLABEL_MNT; 535 sbsec->flags |= SBLABEL_MNT;
536 else
537 sbsec->flags &= ~SBLABEL_MNT;
534 538
535 /* Initialize the root inode. */ 539 /* Initialize the root inode. */
536 rc = inode_doinit_with_dentry(root_inode, root); 540 rc = inode_doinit_with_dentry(root_inode, root);
@@ -809,6 +813,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
809 sbsec->flags |= SE_SBPROC | SE_SBGENFS; 813 sbsec->flags |= SE_SBPROC | SE_SBGENFS;
810 814
811 if (!strcmp(sb->s_type->name, "debugfs") || 815 if (!strcmp(sb->s_type->name, "debugfs") ||
816 !strcmp(sb->s_type->name, "tracefs") ||
812 !strcmp(sb->s_type->name, "sysfs") || 817 !strcmp(sb->s_type->name, "sysfs") ||
813 !strcmp(sb->s_type->name, "pstore")) 818 !strcmp(sb->s_type->name, "pstore"))
814 sbsec->flags |= SE_SBGENFS; 819 sbsec->flags |= SE_SBGENFS;
@@ -963,8 +968,11 @@ mismatch:
963} 968}
964 969
965static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, 970static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
966 struct super_block *newsb) 971 struct super_block *newsb,
972 unsigned long kern_flags,
973 unsigned long *set_kern_flags)
967{ 974{
975 int rc = 0;
968 const struct superblock_security_struct *oldsbsec = oldsb->s_security; 976 const struct superblock_security_struct *oldsbsec = oldsb->s_security;
969 struct superblock_security_struct *newsbsec = newsb->s_security; 977 struct superblock_security_struct *newsbsec = newsb->s_security;
970 978
@@ -979,6 +987,13 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
979 if (!ss_initialized) 987 if (!ss_initialized)
980 return 0; 988 return 0;
981 989
990 /*
991 * Specifying internal flags without providing a place to
992 * place the results is not allowed.
993 */
994 if (kern_flags && !set_kern_flags)
995 return -EINVAL;
996
982 /* how can we clone if the old one wasn't set up?? */ 997 /* how can we clone if the old one wasn't set up?? */
983 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); 998 BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
984 999
@@ -994,6 +1009,18 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
994 newsbsec->def_sid = oldsbsec->def_sid; 1009 newsbsec->def_sid = oldsbsec->def_sid;
995 newsbsec->behavior = oldsbsec->behavior; 1010 newsbsec->behavior = oldsbsec->behavior;
996 1011
1012 if (newsbsec->behavior == SECURITY_FS_USE_NATIVE &&
1013 !(kern_flags & SECURITY_LSM_NATIVE_LABELS) && !set_context) {
1014 rc = security_fs_use(newsb);
1015 if (rc)
1016 goto out;
1017 }
1018
1019 if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !set_context) {
1020 newsbsec->behavior = SECURITY_FS_USE_NATIVE;
1021 *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
1022 }
1023
997 if (set_context) { 1024 if (set_context) {
998 u32 sid = oldsbsec->mntpoint_sid; 1025 u32 sid = oldsbsec->mntpoint_sid;
999 1026
@@ -1013,8 +1040,9 @@ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
1013 } 1040 }
1014 1041
1015 sb_finish_set_opts(newsb); 1042 sb_finish_set_opts(newsb);
1043out:
1016 mutex_unlock(&newsbsec->lock); 1044 mutex_unlock(&newsbsec->lock);
1017 return 0; 1045 return rc;
1018} 1046}
1019 1047
1020static int selinux_parse_opts_str(char *options, 1048static int selinux_parse_opts_str(char *options,
@@ -2062,8 +2090,9 @@ static inline u32 file_to_av(struct file *file)
2062static inline u32 open_file_to_av(struct file *file) 2090static inline u32 open_file_to_av(struct file *file)
2063{ 2091{
2064 u32 av = file_to_av(file); 2092 u32 av = file_to_av(file);
2093 struct inode *inode = file_inode(file);
2065 2094
2066 if (selinux_policycap_openperm) 2095 if (selinux_policycap_openperm && inode->i_sb->s_magic != SOCKFS_MAGIC)
2067 av |= FILE__OPEN; 2096 av |= FILE__OPEN;
2068 2097
2069 return av; 2098 return av;
@@ -3058,6 +3087,7 @@ static int selinux_inode_permission(struct inode *inode, int mask)
3058static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) 3087static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3059{ 3088{
3060 const struct cred *cred = current_cred(); 3089 const struct cred *cred = current_cred();
3090 struct inode *inode = d_backing_inode(dentry);
3061 unsigned int ia_valid = iattr->ia_valid; 3091 unsigned int ia_valid = iattr->ia_valid;
3062 __u32 av = FILE__WRITE; 3092 __u32 av = FILE__WRITE;
3063 3093
@@ -3073,8 +3103,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
3073 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) 3103 ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
3074 return dentry_has_perm(cred, dentry, FILE__SETATTR); 3104 return dentry_has_perm(cred, dentry, FILE__SETATTR);
3075 3105
3076 if (selinux_policycap_openperm && (ia_valid & ATTR_SIZE) 3106 if (selinux_policycap_openperm &&
3077 && !(ia_valid & ATTR_FILE)) 3107 inode->i_sb->s_magic != SOCKFS_MAGIC &&
3108 (ia_valid & ATTR_SIZE) &&
3109 !(ia_valid & ATTR_FILE))
3078 av |= FILE__OPEN; 3110 av |= FILE__OPEN;
3079 3111
3080 return dentry_has_perm(cred, dentry, av); 3112 return dentry_has_perm(cred, dentry, av);
@@ -3106,6 +3138,18 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
3106 return dentry_has_perm(cred, dentry, FILE__SETATTR); 3138 return dentry_has_perm(cred, dentry, FILE__SETATTR);
3107} 3139}
3108 3140
3141static bool has_cap_mac_admin(bool audit)
3142{
3143 const struct cred *cred = current_cred();
3144 int cap_audit = audit ? SECURITY_CAP_AUDIT : SECURITY_CAP_NOAUDIT;
3145
3146 if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, cap_audit))
3147 return false;
3148 if (cred_has_capability(cred, CAP_MAC_ADMIN, cap_audit, true))
3149 return false;
3150 return true;
3151}
3152
3109static int selinux_inode_setxattr(struct dentry *dentry, const char *name, 3153static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3110 const void *value, size_t size, int flags) 3154 const void *value, size_t size, int flags)
3111{ 3155{
@@ -3137,7 +3181,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3137 3181
3138 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL); 3182 rc = security_context_to_sid(value, size, &newsid, GFP_KERNEL);
3139 if (rc == -EINVAL) { 3183 if (rc == -EINVAL) {
3140 if (!capable(CAP_MAC_ADMIN)) { 3184 if (!has_cap_mac_admin(true)) {
3141 struct audit_buffer *ab; 3185 struct audit_buffer *ab;
3142 size_t audit_size; 3186 size_t audit_size;
3143 const char *str; 3187 const char *str;
@@ -3263,13 +3307,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
3263 * and lack of permission just means that we fall back to the 3307 * and lack of permission just means that we fall back to the
3264 * in-core context value, not a denial. 3308 * in-core context value, not a denial.
3265 */ 3309 */
3266 error = cap_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
3267 SECURITY_CAP_NOAUDIT);
3268 if (!error)
3269 error = cred_has_capability(current_cred(), CAP_MAC_ADMIN,
3270 SECURITY_CAP_NOAUDIT, true);
3271 isec = inode_security(inode); 3310 isec = inode_security(inode);
3272 if (!error) 3311 if (has_cap_mac_admin(false))
3273 error = security_sid_to_context_force(isec->sid, &context, 3312 error = security_sid_to_context_force(isec->sid, &context,
3274 &size); 3313 &size);
3275 else 3314 else
@@ -3549,6 +3588,18 @@ static int selinux_mmap_addr(unsigned long addr)
3549static int selinux_mmap_file(struct file *file, unsigned long reqprot, 3588static int selinux_mmap_file(struct file *file, unsigned long reqprot,
3550 unsigned long prot, unsigned long flags) 3589 unsigned long prot, unsigned long flags)
3551{ 3590{
3591 struct common_audit_data ad;
3592 int rc;
3593
3594 if (file) {
3595 ad.type = LSM_AUDIT_DATA_FILE;
3596 ad.u.file = file;
3597 rc = inode_has_perm(current_cred(), file_inode(file),
3598 FILE__MAP, &ad);
3599 if (rc)
3600 return rc;
3601 }
3602
3552 if (selinux_checkreqprot) 3603 if (selinux_checkreqprot)
3553 prot = reqprot; 3604 prot = reqprot;
3554 3605
@@ -3709,7 +3760,8 @@ static int selinux_file_open(struct file *file, const struct cred *cred)
3709 3760
3710/* task security operations */ 3761/* task security operations */
3711 3762
3712static int selinux_task_create(unsigned long clone_flags) 3763static int selinux_task_alloc(struct task_struct *task,
3764 unsigned long clone_flags)
3713{ 3765{
3714 u32 sid = current_sid(); 3766 u32 sid = current_sid();
3715 3767
@@ -5917,7 +5969,7 @@ static int selinux_setprocattr(const char *name, void *value, size_t size)
5917 } 5969 }
5918 error = security_context_to_sid(value, size, &sid, GFP_KERNEL); 5970 error = security_context_to_sid(value, size, &sid, GFP_KERNEL);
5919 if (error == -EINVAL && !strcmp(name, "fscreate")) { 5971 if (error == -EINVAL && !strcmp(name, "fscreate")) {
5920 if (!capable(CAP_MAC_ADMIN)) { 5972 if (!has_cap_mac_admin(true)) {
5921 struct audit_buffer *ab; 5973 struct audit_buffer *ab;
5922 size_t audit_size; 5974 size_t audit_size;
5923 5975
@@ -6127,7 +6179,70 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
6127 *_buffer = context; 6179 *_buffer = context;
6128 return rc; 6180 return rc;
6129} 6181}
6182#endif
6183
6184#ifdef CONFIG_SECURITY_INFINIBAND
6185static int selinux_ib_pkey_access(void *ib_sec, u64 subnet_prefix, u16 pkey_val)
6186{
6187 struct common_audit_data ad;
6188 int err;
6189 u32 sid = 0;
6190 struct ib_security_struct *sec = ib_sec;
6191 struct lsm_ibpkey_audit ibpkey;
6192
6193 err = sel_ib_pkey_sid(subnet_prefix, pkey_val, &sid);
6194 if (err)
6195 return err;
6196
6197 ad.type = LSM_AUDIT_DATA_IBPKEY;
6198 ibpkey.subnet_prefix = subnet_prefix;
6199 ibpkey.pkey = pkey_val;
6200 ad.u.ibpkey = &ibpkey;
6201 return avc_has_perm(sec->sid, sid,
6202 SECCLASS_INFINIBAND_PKEY,
6203 INFINIBAND_PKEY__ACCESS, &ad);
6204}
6205
6206static int selinux_ib_endport_manage_subnet(void *ib_sec, const char *dev_name,
6207 u8 port_num)
6208{
6209 struct common_audit_data ad;
6210 int err;
6211 u32 sid = 0;
6212 struct ib_security_struct *sec = ib_sec;
6213 struct lsm_ibendport_audit ibendport;
6214
6215 err = security_ib_endport_sid(dev_name, port_num, &sid);
6216
6217 if (err)
6218 return err;
6219
6220 ad.type = LSM_AUDIT_DATA_IBENDPORT;
6221 strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
6222 ibendport.port = port_num;
6223 ad.u.ibendport = &ibendport;
6224 return avc_has_perm(sec->sid, sid,
6225 SECCLASS_INFINIBAND_ENDPORT,
6226 INFINIBAND_ENDPORT__MANAGE_SUBNET, &ad);
6227}
6228
6229static int selinux_ib_alloc_security(void **ib_sec)
6230{
6231 struct ib_security_struct *sec;
6130 6232
6233 sec = kzalloc(sizeof(*sec), GFP_KERNEL);
6234 if (!sec)
6235 return -ENOMEM;
6236 sec->sid = current_sid();
6237
6238 *ib_sec = sec;
6239 return 0;
6240}
6241
6242static void selinux_ib_free_security(void *ib_sec)
6243{
6244 kfree(ib_sec);
6245}
6131#endif 6246#endif
6132 6247
6133static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { 6248static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
@@ -6212,7 +6327,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6212 6327
6213 LSM_HOOK_INIT(file_open, selinux_file_open), 6328 LSM_HOOK_INIT(file_open, selinux_file_open),
6214 6329
6215 LSM_HOOK_INIT(task_create, selinux_task_create), 6330 LSM_HOOK_INIT(task_alloc, selinux_task_alloc),
6216 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank), 6331 LSM_HOOK_INIT(cred_alloc_blank, selinux_cred_alloc_blank),
6217 LSM_HOOK_INIT(cred_free, selinux_cred_free), 6332 LSM_HOOK_INIT(cred_free, selinux_cred_free),
6218 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare), 6333 LSM_HOOK_INIT(cred_prepare, selinux_cred_prepare),
@@ -6314,7 +6429,13 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6314 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue), 6429 LSM_HOOK_INIT(tun_dev_attach_queue, selinux_tun_dev_attach_queue),
6315 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach), 6430 LSM_HOOK_INIT(tun_dev_attach, selinux_tun_dev_attach),
6316 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open), 6431 LSM_HOOK_INIT(tun_dev_open, selinux_tun_dev_open),
6317 6432#ifdef CONFIG_SECURITY_INFINIBAND
6433 LSM_HOOK_INIT(ib_pkey_access, selinux_ib_pkey_access),
6434 LSM_HOOK_INIT(ib_endport_manage_subnet,
6435 selinux_ib_endport_manage_subnet),
6436 LSM_HOOK_INIT(ib_alloc_security, selinux_ib_alloc_security),
6437 LSM_HOOK_INIT(ib_free_security, selinux_ib_free_security),
6438#endif
6318#ifdef CONFIG_SECURITY_NETWORK_XFRM 6439#ifdef CONFIG_SECURITY_NETWORK_XFRM
6319 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc), 6440 LSM_HOOK_INIT(xfrm_policy_alloc_security, selinux_xfrm_policy_alloc),
6320 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone), 6441 LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
@@ -6378,6 +6499,9 @@ static __init int selinux_init(void)
6378 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) 6499 if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
6379 panic("SELinux: Unable to register AVC netcache callback\n"); 6500 panic("SELinux: Unable to register AVC netcache callback\n");
6380 6501
6502 if (avc_add_callback(selinux_lsm_notifier_avc_callback, AVC_CALLBACK_RESET))
6503 panic("SELinux: Unable to register AVC LSM notifier callback\n");
6504
6381 if (selinux_enforcing) 6505 if (selinux_enforcing)
6382 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); 6506 printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n");
6383 else 6507 else
@@ -6447,6 +6571,23 @@ static struct nf_hook_ops selinux_nf_ops[] = {
6447#endif /* IPV6 */ 6571#endif /* IPV6 */
6448}; 6572};
6449 6573
6574static int __net_init selinux_nf_register(struct net *net)
6575{
6576 return nf_register_net_hooks(net, selinux_nf_ops,
6577 ARRAY_SIZE(selinux_nf_ops));
6578}
6579
6580static void __net_exit selinux_nf_unregister(struct net *net)
6581{
6582 nf_unregister_net_hooks(net, selinux_nf_ops,
6583 ARRAY_SIZE(selinux_nf_ops));
6584}
6585
6586static struct pernet_operations selinux_net_ops = {
6587 .init = selinux_nf_register,
6588 .exit = selinux_nf_unregister,
6589};
6590
6450static int __init selinux_nf_ip_init(void) 6591static int __init selinux_nf_ip_init(void)
6451{ 6592{
6452 int err; 6593 int err;
@@ -6456,13 +6597,12 @@ static int __init selinux_nf_ip_init(void)
6456 6597
6457 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 6598 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
6458 6599
6459 err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); 6600 err = register_pernet_subsys(&selinux_net_ops);
6460 if (err) 6601 if (err)
6461 panic("SELinux: nf_register_hooks: error %d\n", err); 6602 panic("SELinux: register_pernet_subsys: error %d\n", err);
6462 6603
6463 return 0; 6604 return 0;
6464} 6605}
6465
6466__initcall(selinux_nf_ip_init); 6606__initcall(selinux_nf_ip_init);
6467 6607
6468#ifdef CONFIG_SECURITY_SELINUX_DISABLE 6608#ifdef CONFIG_SECURITY_SELINUX_DISABLE
@@ -6470,7 +6610,7 @@ static void selinux_nf_ip_exit(void)
6470{ 6610{
6471 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 6611 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
6472 6612
6473 nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); 6613 unregister_pernet_subsys(&selinux_net_ops);
6474} 6614}
6475#endif 6615#endif
6476 6616