diff options
| author | James Morris <james.l.morris@oracle.com> | 2017-12-11 01:01:08 -0500 |
|---|---|---|
| committer | James Morris <james.l.morris@oracle.com> | 2017-12-11 01:01:08 -0500 |
| commit | d21bd6898336a7892914d308d5e0868f0b863571 (patch) | |
| tree | f5f756c25348b5a6c1ce9ddbaa7d1ecd1bef40b0 /security/selinux | |
| parent | 34d8751fd4ffa34e85ee7e85d34168b3f3f62b42 (diff) | |
| parent | 50c4c4e268a2d7a3e58ebb698ac74da0de40ae36 (diff) | |
Sync to v4.15-rc3 for security subsystem developers to work against.
Diffstat (limited to 'security/selinux')
25 files changed, 234 insertions, 36 deletions
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index ff5895ede96f..c7161f8792b2 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 1 | # | 2 | # |
| 2 | # Makefile for building the SELinux module as part of the kernel tree. | 3 | # Makefile for building the SELinux module as part of the kernel tree. |
| 3 | # | 4 | # |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index f5d304736852..8644d864e3c1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -85,6 +85,7 @@ | |||
| 85 | #include <linux/export.h> | 85 | #include <linux/export.h> |
| 86 | #include <linux/msg.h> | 86 | #include <linux/msg.h> |
| 87 | #include <linux/shm.h> | 87 | #include <linux/shm.h> |
| 88 | #include <linux/bpf.h> | ||
| 88 | 89 | ||
| 89 | #include "avc.h" | 90 | #include "avc.h" |
| 90 | #include "objsec.h" | 91 | #include "objsec.h" |
| @@ -1814,6 +1815,10 @@ static inline int file_path_has_perm(const struct cred *cred, | |||
| 1814 | return inode_has_perm(cred, file_inode(file), av, &ad); | 1815 | return inode_has_perm(cred, file_inode(file), av, &ad); |
| 1815 | } | 1816 | } |
| 1816 | 1817 | ||
| 1818 | #ifdef CONFIG_BPF_SYSCALL | ||
| 1819 | static int bpf_fd_pass(struct file *file, u32 sid); | ||
| 1820 | #endif | ||
| 1821 | |||
| 1817 | /* Check whether a task can use an open file descriptor to | 1822 | /* Check whether a task can use an open file descriptor to |
| 1818 | access an inode in a given way. Check access to the | 1823 | access an inode in a given way. Check access to the |
| 1819 | descriptor itself, and then use dentry_has_perm to | 1824 | descriptor itself, and then use dentry_has_perm to |
| @@ -1844,6 +1849,12 @@ static int file_has_perm(const struct cred *cred, | |||
| 1844 | goto out; | 1849 | goto out; |
| 1845 | } | 1850 | } |
| 1846 | 1851 | ||
| 1852 | #ifdef CONFIG_BPF_SYSCALL | ||
| 1853 | rc = bpf_fd_pass(file, cred_sid(cred)); | ||
| 1854 | if (rc) | ||
| 1855 | return rc; | ||
| 1856 | #endif | ||
| 1857 | |||
| 1847 | /* av is zero if only checking access to the descriptor. */ | 1858 | /* av is zero if only checking access to the descriptor. */ |
| 1848 | rc = 0; | 1859 | rc = 0; |
| 1849 | if (av) | 1860 | if (av) |
| @@ -2164,6 +2175,12 @@ static int selinux_binder_transfer_file(struct task_struct *from, | |||
| 2164 | return rc; | 2175 | return rc; |
| 2165 | } | 2176 | } |
| 2166 | 2177 | ||
| 2178 | #ifdef CONFIG_BPF_SYSCALL | ||
| 2179 | rc = bpf_fd_pass(file, sid); | ||
| 2180 | if (rc) | ||
| 2181 | return rc; | ||
| 2182 | #endif | ||
| 2183 | |||
| 2167 | if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) | 2184 | if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) |
| 2168 | return 0; | 2185 | return 0; |
| 2169 | 2186 | ||
| @@ -2918,13 +2935,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
| 2918 | { | 2935 | { |
| 2919 | const struct task_security_struct *tsec = current_security(); | 2936 | const struct task_security_struct *tsec = current_security(); |
| 2920 | struct superblock_security_struct *sbsec; | 2937 | struct superblock_security_struct *sbsec; |
| 2921 | u32 sid, newsid, clen; | 2938 | u32 newsid, clen; |
| 2922 | int rc; | 2939 | int rc; |
| 2923 | char *context; | 2940 | char *context; |
| 2924 | 2941 | ||
| 2925 | sbsec = dir->i_sb->s_security; | 2942 | sbsec = dir->i_sb->s_security; |
| 2926 | 2943 | ||
| 2927 | sid = tsec->sid; | ||
| 2928 | newsid = tsec->create_sid; | 2944 | newsid = tsec->create_sid; |
| 2929 | 2945 | ||
| 2930 | rc = selinux_determine_inode_label(current_security(), | 2946 | rc = selinux_determine_inode_label(current_security(), |
| @@ -3124,27 +3140,6 @@ static int selinux_inode_getattr(const struct path *path) | |||
| 3124 | return path_has_perm(current_cred(), path, FILE__GETATTR); | 3140 | return path_has_perm(current_cred(), path, FILE__GETATTR); |
| 3125 | } | 3141 | } |
| 3126 | 3142 | ||
| 3127 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) | ||
| 3128 | { | ||
| 3129 | const struct cred *cred = current_cred(); | ||
| 3130 | |||
| 3131 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | ||
| 3132 | sizeof XATTR_SECURITY_PREFIX - 1)) { | ||
| 3133 | if (!strcmp(name, XATTR_NAME_CAPS)) { | ||
| 3134 | if (!capable(CAP_SETFCAP)) | ||
| 3135 | return -EPERM; | ||
| 3136 | } else if (!capable(CAP_SYS_ADMIN)) { | ||
| 3137 | /* A different attribute in the security namespace. | ||
| 3138 | Restrict to administrator. */ | ||
| 3139 | return -EPERM; | ||
| 3140 | } | ||
| 3141 | } | ||
| 3142 | |||
| 3143 | /* Not an attribute we recognize, so just check the | ||
| 3144 | ordinary setattr permission. */ | ||
| 3145 | return dentry_has_perm(cred, dentry, FILE__SETATTR); | ||
| 3146 | } | ||
| 3147 | |||
| 3148 | static bool has_cap_mac_admin(bool audit) | 3143 | static bool has_cap_mac_admin(bool audit) |
| 3149 | { | 3144 | { |
| 3150 | const struct cred *cred = current_cred(); | 3145 | const struct cred *cred = current_cred(); |
| @@ -3167,8 +3162,15 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 3167 | u32 newsid, sid = current_sid(); | 3162 | u32 newsid, sid = current_sid(); |
| 3168 | int rc = 0; | 3163 | int rc = 0; |
| 3169 | 3164 | ||
| 3170 | if (strcmp(name, XATTR_NAME_SELINUX)) | 3165 | if (strcmp(name, XATTR_NAME_SELINUX)) { |
| 3171 | return selinux_inode_setotherxattr(dentry, name); | 3166 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
| 3167 | if (rc) | ||
| 3168 | return rc; | ||
| 3169 | |||
| 3170 | /* Not an attribute we recognize, so just check the | ||
| 3171 | ordinary setattr permission. */ | ||
| 3172 | return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); | ||
| 3173 | } | ||
| 3172 | 3174 | ||
| 3173 | sbsec = inode->i_sb->s_security; | 3175 | sbsec = inode->i_sb->s_security; |
| 3174 | if (!(sbsec->flags & SBLABEL_MNT)) | 3176 | if (!(sbsec->flags & SBLABEL_MNT)) |
| @@ -3191,18 +3193,17 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 3191 | if (!has_cap_mac_admin(true)) { | 3193 | if (!has_cap_mac_admin(true)) { |
| 3192 | struct audit_buffer *ab; | 3194 | struct audit_buffer *ab; |
| 3193 | size_t audit_size; | 3195 | size_t audit_size; |
| 3194 | const char *str; | ||
| 3195 | 3196 | ||
| 3196 | /* We strip a nul only if it is at the end, otherwise the | 3197 | /* We strip a nul only if it is at the end, otherwise the |
| 3197 | * context contains a nul and we should audit that */ | 3198 | * context contains a nul and we should audit that */ |
| 3198 | if (value) { | 3199 | if (value) { |
| 3199 | str = value; | 3200 | const char *str = value; |
| 3201 | |||
| 3200 | if (str[size - 1] == '\0') | 3202 | if (str[size - 1] == '\0') |
| 3201 | audit_size = size - 1; | 3203 | audit_size = size - 1; |
| 3202 | else | 3204 | else |
| 3203 | audit_size = size; | 3205 | audit_size = size; |
| 3204 | } else { | 3206 | } else { |
| 3205 | str = ""; | ||
| 3206 | audit_size = 0; | 3207 | audit_size = 0; |
| 3207 | } | 3208 | } |
| 3208 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); | 3209 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); |
| @@ -3282,8 +3283,15 @@ static int selinux_inode_listxattr(struct dentry *dentry) | |||
| 3282 | 3283 | ||
| 3283 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) | 3284 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) |
| 3284 | { | 3285 | { |
| 3285 | if (strcmp(name, XATTR_NAME_SELINUX)) | 3286 | if (strcmp(name, XATTR_NAME_SELINUX)) { |
| 3286 | return selinux_inode_setotherxattr(dentry, name); | 3287 | int rc = cap_inode_removexattr(dentry, name); |
| 3288 | if (rc) | ||
| 3289 | return rc; | ||
| 3290 | |||
| 3291 | /* Not an attribute we recognize, so just check the | ||
| 3292 | ordinary setattr permission. */ | ||
| 3293 | return dentry_has_perm(current_cred(), dentry, FILE__SETATTR); | ||
| 3294 | } | ||
| 3287 | 3295 | ||
| 3288 | /* No one is allowed to remove a SELinux security label. | 3296 | /* No one is allowed to remove a SELinux security label. |
| 3289 | You can change the label, but all data must be labeled. */ | 3297 | You can change the label, but all data must be labeled. */ |
| @@ -3978,8 +3986,8 @@ static int selinux_task_getioprio(struct task_struct *p) | |||
| 3978 | PROCESS__GETSCHED, NULL); | 3986 | PROCESS__GETSCHED, NULL); |
| 3979 | } | 3987 | } |
| 3980 | 3988 | ||
| 3981 | int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred, | 3989 | static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred, |
| 3982 | unsigned int flags) | 3990 | unsigned int flags) |
| 3983 | { | 3991 | { |
| 3984 | u32 av = 0; | 3992 | u32 av = 0; |
| 3985 | 3993 | ||
| @@ -6252,6 +6260,139 @@ static void selinux_ib_free_security(void *ib_sec) | |||
| 6252 | } | 6260 | } |
| 6253 | #endif | 6261 | #endif |
| 6254 | 6262 | ||
| 6263 | #ifdef CONFIG_BPF_SYSCALL | ||
| 6264 | static int selinux_bpf(int cmd, union bpf_attr *attr, | ||
| 6265 | unsigned int size) | ||
| 6266 | { | ||
| 6267 | u32 sid = current_sid(); | ||
| 6268 | int ret; | ||
| 6269 | |||
| 6270 | switch (cmd) { | ||
| 6271 | case BPF_MAP_CREATE: | ||
| 6272 | ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE, | ||
| 6273 | NULL); | ||
| 6274 | break; | ||
| 6275 | case BPF_PROG_LOAD: | ||
| 6276 | ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD, | ||
| 6277 | NULL); | ||
| 6278 | break; | ||
| 6279 | default: | ||
| 6280 | ret = 0; | ||
| 6281 | break; | ||
| 6282 | } | ||
| 6283 | |||
| 6284 | return ret; | ||
| 6285 | } | ||
| 6286 | |||
| 6287 | static u32 bpf_map_fmode_to_av(fmode_t fmode) | ||
| 6288 | { | ||
| 6289 | u32 av = 0; | ||
| 6290 | |||
| 6291 | if (fmode & FMODE_READ) | ||
| 6292 | av |= BPF__MAP_READ; | ||
| 6293 | if (fmode & FMODE_WRITE) | ||
| 6294 | av |= BPF__MAP_WRITE; | ||
| 6295 | return av; | ||
| 6296 | } | ||
| 6297 | |||
| 6298 | /* This function will check the file pass through unix socket or binder to see | ||
| 6299 | * if it is a bpf related object. And apply correspinding checks on the bpf | ||
| 6300 | * object based on the type. The bpf maps and programs, not like other files and | ||
| 6301 | * socket, are using a shared anonymous inode inside the kernel as their inode. | ||
| 6302 | * So checking that inode cannot identify if the process have privilege to | ||
| 6303 | * access the bpf object and that's why we have to add this additional check in | ||
| 6304 | * selinux_file_receive and selinux_binder_transfer_files. | ||
| 6305 | */ | ||
| 6306 | static int bpf_fd_pass(struct file *file, u32 sid) | ||
| 6307 | { | ||
| 6308 | struct bpf_security_struct *bpfsec; | ||
| 6309 | struct bpf_prog *prog; | ||
| 6310 | struct bpf_map *map; | ||
| 6311 | int ret; | ||
| 6312 | |||
| 6313 | if (file->f_op == &bpf_map_fops) { | ||
| 6314 | map = file->private_data; | ||
| 6315 | bpfsec = map->security; | ||
| 6316 | ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | ||
| 6317 | bpf_map_fmode_to_av(file->f_mode), NULL); | ||
| 6318 | if (ret) | ||
| 6319 | return ret; | ||
| 6320 | } else if (file->f_op == &bpf_prog_fops) { | ||
| 6321 | prog = file->private_data; | ||
| 6322 | bpfsec = prog->aux->security; | ||
| 6323 | ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | ||
| 6324 | BPF__PROG_RUN, NULL); | ||
| 6325 | if (ret) | ||
| 6326 | return ret; | ||
| 6327 | } | ||
| 6328 | return 0; | ||
| 6329 | } | ||
| 6330 | |||
| 6331 | static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) | ||
| 6332 | { | ||
| 6333 | u32 sid = current_sid(); | ||
| 6334 | struct bpf_security_struct *bpfsec; | ||
| 6335 | |||
| 6336 | bpfsec = map->security; | ||
| 6337 | return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | ||
| 6338 | bpf_map_fmode_to_av(fmode), NULL); | ||
| 6339 | } | ||
| 6340 | |||
| 6341 | static int selinux_bpf_prog(struct bpf_prog *prog) | ||
| 6342 | { | ||
| 6343 | u32 sid = current_sid(); | ||
| 6344 | struct bpf_security_struct *bpfsec; | ||
| 6345 | |||
| 6346 | bpfsec = prog->aux->security; | ||
| 6347 | return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF, | ||
| 6348 | BPF__PROG_RUN, NULL); | ||
| 6349 | } | ||
| 6350 | |||
| 6351 | static int selinux_bpf_map_alloc(struct bpf_map *map) | ||
| 6352 | { | ||
| 6353 | struct bpf_security_struct *bpfsec; | ||
| 6354 | |||
| 6355 | bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL); | ||
| 6356 | if (!bpfsec) | ||
| 6357 | return -ENOMEM; | ||
| 6358 | |||
| 6359 | bpfsec->sid = current_sid(); | ||
| 6360 | map->security = bpfsec; | ||
| 6361 | |||
| 6362 | return 0; | ||
| 6363 | } | ||
| 6364 | |||
| 6365 | static void selinux_bpf_map_free(struct bpf_map *map) | ||
| 6366 | { | ||
| 6367 | struct bpf_security_struct *bpfsec = map->security; | ||
| 6368 | |||
| 6369 | map->security = NULL; | ||
| 6370 | kfree(bpfsec); | ||
| 6371 | } | ||
| 6372 | |||
| 6373 | static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux) | ||
| 6374 | { | ||
| 6375 | struct bpf_security_struct *bpfsec; | ||
| 6376 | |||
| 6377 | bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL); | ||
| 6378 | if (!bpfsec) | ||
| 6379 | return -ENOMEM; | ||
| 6380 | |||
| 6381 | bpfsec->sid = current_sid(); | ||
| 6382 | aux->security = bpfsec; | ||
| 6383 | |||
| 6384 | return 0; | ||
| 6385 | } | ||
| 6386 | |||
| 6387 | static void selinux_bpf_prog_free(struct bpf_prog_aux *aux) | ||
| 6388 | { | ||
| 6389 | struct bpf_security_struct *bpfsec = aux->security; | ||
| 6390 | |||
| 6391 | aux->security = NULL; | ||
| 6392 | kfree(bpfsec); | ||
| 6393 | } | ||
| 6394 | #endif | ||
| 6395 | |||
| 6255 | static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | 6396 | static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { |
| 6256 | LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), | 6397 | LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), |
| 6257 | LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), | 6398 | LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), |
| @@ -6471,6 +6612,16 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
| 6471 | LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match), | 6612 | LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match), |
| 6472 | LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free), | 6613 | LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free), |
| 6473 | #endif | 6614 | #endif |
| 6615 | |||
| 6616 | #ifdef CONFIG_BPF_SYSCALL | ||
| 6617 | LSM_HOOK_INIT(bpf, selinux_bpf), | ||
| 6618 | LSM_HOOK_INIT(bpf_map, selinux_bpf_map), | ||
| 6619 | LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog), | ||
| 6620 | LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc), | ||
| 6621 | LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc), | ||
| 6622 | LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free), | ||
| 6623 | LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free), | ||
| 6624 | #endif | ||
| 6474 | }; | 6625 | }; |
| 6475 | 6626 | ||
| 6476 | static __init int selinux_init(void) | 6627 | static __init int selinux_init(void) |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index a5004e9de11a..57d61cf36500 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Access vector cache interface for object managers. | 3 | * Access vector cache interface for object managers. |
| 3 | * | 4 | * |
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index 37d57dadd476..3bcc72769b87 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Access vector cache interface for the security server. | 3 | * Access vector cache interface for the security server. |
| 3 | * | 4 | * |
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 35ffb29a69cb..acdee7795297 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | #include <linux/capability.h> | 2 | #include <linux/capability.h> |
| 2 | 3 | ||
| 3 | #define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ | 4 | #define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ |
| @@ -237,6 +238,8 @@ struct security_class_mapping secclass_map[] = { | |||
| 237 | { "access", NULL } }, | 238 | { "access", NULL } }, |
| 238 | { "infiniband_endport", | 239 | { "infiniband_endport", |
| 239 | { "manage_subnet", NULL } }, | 240 | { "manage_subnet", NULL } }, |
| 241 | { "bpf", | ||
| 242 | {"map_create", "map_read", "map_write", "prog_load", "prog_run"} }, | ||
| 240 | { NULL } | 243 | { NULL } |
| 241 | }; | 244 | }; |
| 242 | 245 | ||
diff --git a/security/selinux/include/initial_sid_to_string.h b/security/selinux/include/initial_sid_to_string.h index a59b64e3fd02..4f93f697f71c 100644 --- a/security/selinux/include/initial_sid_to_string.h +++ b/security/selinux/include/initial_sid_to_string.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* This file is automatically generated. Do not edit. */ | 2 | /* This file is automatically generated. Do not edit. */ |
| 2 | static const char *initial_sid_to_string[] = | 3 | static const char *initial_sid_to_string[] = |
| 3 | { | 4 | { |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 1649cd18eb0b..3d54468ce334 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -150,6 +150,10 @@ struct pkey_security_struct { | |||
| 150 | u32 sid; /* SID of pkey */ | 150 | u32 sid; /* SID of pkey */ |
| 151 | }; | 151 | }; |
| 152 | 152 | ||
| 153 | struct bpf_security_struct { | ||
| 154 | u32 sid; /*SID of bpf obj creater*/ | ||
| 155 | }; | ||
| 156 | |||
| 153 | extern unsigned int selinux_checkreqprot; | 157 | extern unsigned int selinux_checkreqprot; |
| 154 | 158 | ||
| 155 | #endif /* _SELINUX_OBJSEC_H_ */ | 159 | #endif /* _SELINUX_OBJSEC_H_ */ |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 28dfb2f93e4d..02f0412d42f2 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Security server interface. | 3 | * Security server interface. |
| 3 | * | 4 | * |
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 36a7ce9e11ff..1f173a7a4daa 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * SELinux support for the XFRM LSM hooks | 3 | * SELinux support for the XFRM LSM hooks |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 771c96afe1d5..c91543a617ac 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c | |||
| @@ -361,7 +361,6 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * | |||
| 361 | 361 | ||
| 362 | *ret_list = NULL; | 362 | *ret_list = NULL; |
| 363 | 363 | ||
| 364 | len = 0; | ||
| 365 | rc = next_entry(buf, fp, sizeof(u32)); | 364 | rc = next_entry(buf, fp, sizeof(u32)); |
| 366 | if (rc) | 365 | if (rc) |
| 367 | return rc; | 366 | return rc; |
diff --git a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h index 33ae2aec4f36..4e563be9ef5f 100644 --- a/security/selinux/ss/constraint.h +++ b/security/selinux/ss/constraint.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * A constraint is a condition that must be satisfied in | 3 | * A constraint is a condition that must be satisfied in |
| 3 | * order for one or more permissions to be granted. | 4 | * order for one or more permissions to be granted. |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index a2c0f37c42ae..2260c44a568c 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * A security context is a set of security attributes | 3 | * A security context is a set of security attributes |
| 3 | * associated with each subject and object controlled | 4 | * associated with each subject and object controlled |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index fc28149a4f2e..b6a78b09235c 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Implementation of the extensible bitmap type. | 3 | * Implementation of the extensible bitmap type. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index da1325dda550..edf4fa39c60a 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * An extensible bitmap is a bitmap that supports an | 3 | * An extensible bitmap is a bitmap that supports an |
| 3 | * arbitrary number of bits. Extensible bitmaps are | 4 | * arbitrary number of bits. Extensible bitmaps are |
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index 686c3917064c..fe25b3fb2154 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Implementation of the hash table type. | 3 | * Implementation of the hash table type. |
| 3 | * | 4 | * |
| @@ -9,6 +10,8 @@ | |||
| 9 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
| 10 | #include "hashtab.h" | 11 | #include "hashtab.h" |
| 11 | 12 | ||
| 13 | static struct kmem_cache *hashtab_node_cachep; | ||
| 14 | |||
| 12 | struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key), | 15 | struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key), |
| 13 | int (*keycmp)(struct hashtab *h, const void *key1, const void *key2), | 16 | int (*keycmp)(struct hashtab *h, const void *key1, const void *key2), |
| 14 | u32 size) | 17 | u32 size) |
| @@ -57,7 +60,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum) | |||
| 57 | if (cur && (h->keycmp(h, key, cur->key) == 0)) | 60 | if (cur && (h->keycmp(h, key, cur->key) == 0)) |
| 58 | return -EEXIST; | 61 | return -EEXIST; |
| 59 | 62 | ||
| 60 | newnode = kzalloc(sizeof(*newnode), GFP_KERNEL); | 63 | newnode = kmem_cache_zalloc(hashtab_node_cachep, GFP_KERNEL); |
| 61 | if (!newnode) | 64 | if (!newnode) |
| 62 | return -ENOMEM; | 65 | return -ENOMEM; |
| 63 | newnode->key = key; | 66 | newnode->key = key; |
| @@ -106,7 +109,7 @@ void hashtab_destroy(struct hashtab *h) | |||
| 106 | while (cur) { | 109 | while (cur) { |
| 107 | temp = cur; | 110 | temp = cur; |
| 108 | cur = cur->next; | 111 | cur = cur->next; |
| 109 | kfree(temp); | 112 | kmem_cache_free(hashtab_node_cachep, temp); |
| 110 | } | 113 | } |
| 111 | h->htable[i] = NULL; | 114 | h->htable[i] = NULL; |
| 112 | } | 115 | } |
| @@ -148,7 +151,7 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) | |||
| 148 | 151 | ||
| 149 | slots_used = 0; | 152 | slots_used = 0; |
| 150 | max_chain_len = 0; | 153 | max_chain_len = 0; |
| 151 | for (slots_used = max_chain_len = i = 0; i < h->size; i++) { | 154 | for (i = 0; i < h->size; i++) { |
| 152 | cur = h->htable[i]; | 155 | cur = h->htable[i]; |
| 153 | if (cur) { | 156 | if (cur) { |
| 154 | slots_used++; | 157 | slots_used++; |
| @@ -166,3 +169,14 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) | |||
| 166 | info->slots_used = slots_used; | 169 | info->slots_used = slots_used; |
| 167 | info->max_chain_len = max_chain_len; | 170 | info->max_chain_len = max_chain_len; |
| 168 | } | 171 | } |
| 172 | void hashtab_cache_init(void) | ||
| 173 | { | ||
| 174 | hashtab_node_cachep = kmem_cache_create("hashtab_node", | ||
| 175 | sizeof(struct hashtab_node), | ||
| 176 | 0, SLAB_PANIC, NULL); | ||
| 177 | } | ||
| 178 | |||
| 179 | void hashtab_cache_destroy(void) | ||
| 180 | { | ||
| 181 | kmem_cache_destroy(hashtab_node_cachep); | ||
| 182 | } | ||
diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 009fb5e06172..6183ee2a2e7a 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * A hash table (hashtab) maintains associations between | 3 | * A hash table (hashtab) maintains associations between |
| 3 | * key values and datum values. The type of the key values | 4 | * key values and datum values. The type of the key values |
| @@ -84,4 +85,8 @@ int hashtab_map(struct hashtab *h, | |||
| 84 | /* Fill info with some hash table statistics */ | 85 | /* Fill info with some hash table statistics */ |
| 85 | void hashtab_stat(struct hashtab *h, struct hashtab_info *info); | 86 | void hashtab_stat(struct hashtab *h, struct hashtab_info *info); |
| 86 | 87 | ||
| 88 | /* Use kmem_cache for hashtab_node */ | ||
| 89 | void hashtab_cache_init(void); | ||
| 90 | void hashtab_cache_destroy(void); | ||
| 91 | |||
| 87 | #endif /* _SS_HASHTAB_H */ | 92 | #endif /* _SS_HASHTAB_H */ |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index d9dc34f4fade..ad982ce8bfa4 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Implementation of the multi-level security (MLS) policy. | 3 | * Implementation of the multi-level security (MLS) policy. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 0f0a1d65b2ce..131d76266ea5 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Multi-level security (MLS) policy operations. | 3 | * Multi-level security (MLS) policy operations. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index 47f3702cd596..068e0d7809db 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Type definitions for the multi-level security (MLS) policy. | 3 | * Type definitions for the multi-level security (MLS) policy. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index e4a1c0dc561a..33cfe5d3d6cb 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
| @@ -2060,10 +2060,12 @@ int security_load_policy(void *data, size_t len) | |||
| 2060 | if (!ss_initialized) { | 2060 | if (!ss_initialized) { |
| 2061 | avtab_cache_init(); | 2061 | avtab_cache_init(); |
| 2062 | ebitmap_cache_init(); | 2062 | ebitmap_cache_init(); |
| 2063 | hashtab_cache_init(); | ||
| 2063 | rc = policydb_read(&policydb, fp); | 2064 | rc = policydb_read(&policydb, fp); |
| 2064 | if (rc) { | 2065 | if (rc) { |
| 2065 | avtab_cache_destroy(); | 2066 | avtab_cache_destroy(); |
| 2066 | ebitmap_cache_destroy(); | 2067 | ebitmap_cache_destroy(); |
| 2068 | hashtab_cache_destroy(); | ||
| 2067 | goto out; | 2069 | goto out; |
| 2068 | } | 2070 | } |
| 2069 | 2071 | ||
| @@ -2075,6 +2077,7 @@ int security_load_policy(void *data, size_t len) | |||
| 2075 | policydb_destroy(&policydb); | 2077 | policydb_destroy(&policydb); |
| 2076 | avtab_cache_destroy(); | 2078 | avtab_cache_destroy(); |
| 2077 | ebitmap_cache_destroy(); | 2079 | ebitmap_cache_destroy(); |
| 2080 | hashtab_cache_destroy(); | ||
| 2078 | goto out; | 2081 | goto out; |
| 2079 | } | 2082 | } |
| 2080 | 2083 | ||
| @@ -2083,6 +2086,7 @@ int security_load_policy(void *data, size_t len) | |||
| 2083 | policydb_destroy(&policydb); | 2086 | policydb_destroy(&policydb); |
| 2084 | avtab_cache_destroy(); | 2087 | avtab_cache_destroy(); |
| 2085 | ebitmap_cache_destroy(); | 2088 | ebitmap_cache_destroy(); |
| 2089 | hashtab_cache_destroy(); | ||
| 2086 | goto out; | 2090 | goto out; |
| 2087 | } | 2091 | } |
| 2088 | 2092 | ||
diff --git a/security/selinux/ss/services.h b/security/selinux/ss/services.h index 3d9fa9556b4f..356bdd36cf6d 100644 --- a/security/selinux/ss/services.h +++ b/security/selinux/ss/services.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * Implementation of the security services. | 3 | * Implementation of the security services. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 6ae08efc5ae7..5be31b7af225 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Implementation of the SID table type. | 3 | * Implementation of the SID table type. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index de5d0ea583d2..a1a1d2617b6f 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * A security identifier table (sidtab) is a hash table | 3 | * A security identifier table (sidtab) is a hash table |
| 3 | * of security context structures indexed by SID value. | 4 | * of security context structures indexed by SID value. |
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index d1a6745849a7..dc2ce94165d3 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * Implementation of the symbol table type. | 3 | * Implementation of the symbol table type. |
| 3 | * | 4 | * |
diff --git a/security/selinux/ss/symtab.h b/security/selinux/ss/symtab.h index 0bc12d587d3a..d75fcafe7281 100644 --- a/security/selinux/ss/symtab.h +++ b/security/selinux/ss/symtab.h | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 1 | /* | 2 | /* |
| 2 | * A symbol table (symtab) maintains associations between symbol | 3 | * A symbol table (symtab) maintains associations between symbol |
| 3 | * strings and datum values. The type of the datum values | 4 | * strings and datum values. The type of the datum values |
