diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 212 |
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 | ||
176 | static 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 | |||
403 | static 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 | |||
413 | static inline int inode_doinit(struct inode *inode) | 413 | static 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 | ||
965 | static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | 970 | static 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); |
1043 | out: | ||
1016 | mutex_unlock(&newsbsec->lock); | 1044 | mutex_unlock(&newsbsec->lock); |
1017 | return 0; | 1045 | return rc; |
1018 | } | 1046 | } |
1019 | 1047 | ||
1020 | static int selinux_parse_opts_str(char *options, | 1048 | static int selinux_parse_opts_str(char *options, |
@@ -2062,8 +2090,9 @@ static inline u32 file_to_av(struct file *file) | |||
2062 | static inline u32 open_file_to_av(struct file *file) | 2090 | static 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) | |||
3058 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 3087 | static 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 | ||
3141 | static 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 | |||
3109 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | 3153 | static 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) | |||
3549 | static int selinux_mmap_file(struct file *file, unsigned long reqprot, | 3588 | static 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 | ||
3712 | static int selinux_task_create(unsigned long clone_flags) | 3763 | static 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 | ||
6185 | static 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 | |||
6206 | static 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 | |||
6229 | static 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 | |||
6242 | static void selinux_ib_free_security(void *ib_sec) | ||
6243 | { | ||
6244 | kfree(ib_sec); | ||
6245 | } | ||
6131 | #endif | 6246 | #endif |
6132 | 6247 | ||
6133 | static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | 6248 | static 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 | ||
6574 | static 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 | |||
6580 | static 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 | |||
6586 | static struct pernet_operations selinux_net_ops = { | ||
6587 | .init = selinux_nf_register, | ||
6588 | .exit = selinux_nf_unregister, | ||
6589 | }; | ||
6590 | |||
6450 | static int __init selinux_nf_ip_init(void) | 6591 | static 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 | ||