diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-23 14:21:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-23 14:21:04 -0400 |
commit | 5825a95fe92566ada2292a65de030850b5cff1da (patch) | |
tree | 8e210a297844f6e07e0acb6ee793036a2c692976 | |
parent | 3c6a6910a81eae3566bb5fef6ea0f624382595e6 (diff) | |
parent | 15322a0d90b6fd62ae8f22e5b87f735c3fdfeff7 (diff) |
Merge tag 'selinux-pr-20190917' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore:
- Add LSM hooks, and SELinux access control hooks, for dnotify,
fanotify, and inotify watches. This has been discussed with both the
LSM and fs/notify folks and everybody is good with these new hooks.
- The LSM stacking changes missed a few calls to current_security() in
the SELinux code; we fix those and remove current_security() for
good.
- Improve our network object labeling cache so that we always return
the object's label, even when under memory pressure. Previously we
would return an error if we couldn't allocate a new cache entry, now
we always return the label even if we can't create a new cache entry
for it.
- Convert the sidtab atomic_t counter to a normal u32 with
READ/WRITE_ONCE() and memory barrier protection.
- A few patches to policydb.c to clean things up (remove forward
declarations, long lines, bad variable names, etc)
* tag 'selinux-pr-20190917' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
lsm: remove current_security()
selinux: fix residual uses of current_security() for the SELinux blob
selinux: avoid atomic_t usage in sidtab
fanotify, inotify, dnotify, security: add security hook for fs notifications
selinux: always return a secid from the network caches if we find one
selinux: policydb - rename type_val_to_struct_array
selinux: policydb - fix some checkpatch.pl warnings
selinux: shuffle around policydb.c to get rid of forward declarations
-rw-r--r-- | fs/notify/dnotify/dnotify.c | 15 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 19 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 14 | ||||
-rw-r--r-- | include/linux/cred.h | 1 | ||||
-rw-r--r-- | include/linux/lsm_hooks.h | 9 | ||||
-rw-r--r-- | include/linux/security.h | 10 | ||||
-rw-r--r-- | security/security.c | 6 | ||||
-rw-r--r-- | security/selinux/hooks.c | 49 | ||||
-rw-r--r-- | security/selinux/include/classmap.h | 5 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 20 | ||||
-rw-r--r-- | security/selinux/netif.c | 31 | ||||
-rw-r--r-- | security/selinux/netnode.c | 30 | ||||
-rw-r--r-- | security/selinux/netport.c | 24 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 402 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 6 | ||||
-rw-r--r-- | security/selinux/ss/sidtab.c | 48 | ||||
-rw-r--r-- | security/selinux/ss/sidtab.h | 19 |
18 files changed, 403 insertions, 307 deletions
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index c03758c91481..7a42c2ebe28d 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/sched/signal.h> | 13 | #include <linux/sched/signal.h> |
14 | #include <linux/dnotify.h> | 14 | #include <linux/dnotify.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/security.h> | ||
16 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/fdtable.h> | 19 | #include <linux/fdtable.h> |
@@ -279,6 +280,17 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
279 | goto out_err; | 280 | goto out_err; |
280 | } | 281 | } |
281 | 282 | ||
283 | /* | ||
284 | * convert the userspace DN_* "arg" to the internal FS_* | ||
285 | * defined in fsnotify | ||
286 | */ | ||
287 | mask = convert_arg(arg); | ||
288 | |||
289 | error = security_path_notify(&filp->f_path, mask, | ||
290 | FSNOTIFY_OBJ_TYPE_INODE); | ||
291 | if (error) | ||
292 | goto out_err; | ||
293 | |||
282 | /* expect most fcntl to add new rather than augment old */ | 294 | /* expect most fcntl to add new rather than augment old */ |
283 | dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL); | 295 | dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL); |
284 | if (!dn) { | 296 | if (!dn) { |
@@ -293,9 +305,6 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) | |||
293 | goto out_err; | 305 | goto out_err; |
294 | } | 306 | } |
295 | 307 | ||
296 | /* convert the userspace DN_* "arg" to the internal FS_* defines in fsnotify */ | ||
297 | mask = convert_arg(arg); | ||
298 | |||
299 | /* set up the new_fsn_mark and new_dn_mark */ | 308 | /* set up the new_fsn_mark and new_dn_mark */ |
300 | new_fsn_mark = &new_dn_mark->fsn_mark; | 309 | new_fsn_mark = &new_dn_mark->fsn_mark; |
301 | fsnotify_init_mark(new_fsn_mark, dnotify_group); | 310 | fsnotify_init_mark(new_fsn_mark, dnotify_group); |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 91006f47e420..8508ab575017 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
@@ -528,7 +528,8 @@ static const struct file_operations fanotify_fops = { | |||
528 | }; | 528 | }; |
529 | 529 | ||
530 | static int fanotify_find_path(int dfd, const char __user *filename, | 530 | static int fanotify_find_path(int dfd, const char __user *filename, |
531 | struct path *path, unsigned int flags) | 531 | struct path *path, unsigned int flags, __u64 mask, |
532 | unsigned int obj_type) | ||
532 | { | 533 | { |
533 | int ret; | 534 | int ret; |
534 | 535 | ||
@@ -567,8 +568,15 @@ static int fanotify_find_path(int dfd, const char __user *filename, | |||
567 | 568 | ||
568 | /* you can only watch an inode if you have read permissions on it */ | 569 | /* you can only watch an inode if you have read permissions on it */ |
569 | ret = inode_permission(path->dentry->d_inode, MAY_READ); | 570 | ret = inode_permission(path->dentry->d_inode, MAY_READ); |
571 | if (ret) { | ||
572 | path_put(path); | ||
573 | goto out; | ||
574 | } | ||
575 | |||
576 | ret = security_path_notify(path, mask, obj_type); | ||
570 | if (ret) | 577 | if (ret) |
571 | path_put(path); | 578 | path_put(path); |
579 | |||
572 | out: | 580 | out: |
573 | return ret; | 581 | return ret; |
574 | } | 582 | } |
@@ -947,6 +955,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
947 | __kernel_fsid_t __fsid, *fsid = NULL; | 955 | __kernel_fsid_t __fsid, *fsid = NULL; |
948 | u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS; | 956 | u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS; |
949 | unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS; | 957 | unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS; |
958 | unsigned int obj_type; | ||
950 | int ret; | 959 | int ret; |
951 | 960 | ||
952 | pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", | 961 | pr_debug("%s: fanotify_fd=%d flags=%x dfd=%d pathname=%p mask=%llx\n", |
@@ -961,8 +970,13 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
961 | 970 | ||
962 | switch (mark_type) { | 971 | switch (mark_type) { |
963 | case FAN_MARK_INODE: | 972 | case FAN_MARK_INODE: |
973 | obj_type = FSNOTIFY_OBJ_TYPE_INODE; | ||
974 | break; | ||
964 | case FAN_MARK_MOUNT: | 975 | case FAN_MARK_MOUNT: |
976 | obj_type = FSNOTIFY_OBJ_TYPE_VFSMOUNT; | ||
977 | break; | ||
965 | case FAN_MARK_FILESYSTEM: | 978 | case FAN_MARK_FILESYSTEM: |
979 | obj_type = FSNOTIFY_OBJ_TYPE_SB; | ||
966 | break; | 980 | break; |
967 | default: | 981 | default: |
968 | return -EINVAL; | 982 | return -EINVAL; |
@@ -1030,7 +1044,8 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, | |||
1030 | goto fput_and_out; | 1044 | goto fput_and_out; |
1031 | } | 1045 | } |
1032 | 1046 | ||
1033 | ret = fanotify_find_path(dfd, pathname, &path, flags); | 1047 | ret = fanotify_find_path(dfd, pathname, &path, flags, |
1048 | (mask & ALL_FSNOTIFY_EVENTS), obj_type); | ||
1034 | if (ret) | 1049 | if (ret) |
1035 | goto fput_and_out; | 1050 | goto fput_and_out; |
1036 | 1051 | ||
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 0b815178126e..107537a543fd 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/poll.h> | 30 | #include <linux/poll.h> |
31 | #include <linux/wait.h> | 31 | #include <linux/wait.h> |
32 | #include <linux/memcontrol.h> | 32 | #include <linux/memcontrol.h> |
33 | #include <linux/security.h> | ||
33 | 34 | ||
34 | #include "inotify.h" | 35 | #include "inotify.h" |
35 | #include "../fdinfo.h" | 36 | #include "../fdinfo.h" |
@@ -331,7 +332,8 @@ static const struct file_operations inotify_fops = { | |||
331 | /* | 332 | /* |
332 | * find_inode - resolve a user-given path to a specific inode | 333 | * find_inode - resolve a user-given path to a specific inode |
333 | */ | 334 | */ |
334 | static int inotify_find_inode(const char __user *dirname, struct path *path, unsigned flags) | 335 | static int inotify_find_inode(const char __user *dirname, struct path *path, |
336 | unsigned int flags, __u64 mask) | ||
335 | { | 337 | { |
336 | int error; | 338 | int error; |
337 | 339 | ||
@@ -340,8 +342,15 @@ static int inotify_find_inode(const char __user *dirname, struct path *path, uns | |||
340 | return error; | 342 | return error; |
341 | /* you can only watch an inode if you have read permissions on it */ | 343 | /* you can only watch an inode if you have read permissions on it */ |
342 | error = inode_permission(path->dentry->d_inode, MAY_READ); | 344 | error = inode_permission(path->dentry->d_inode, MAY_READ); |
345 | if (error) { | ||
346 | path_put(path); | ||
347 | return error; | ||
348 | } | ||
349 | error = security_path_notify(path, mask, | ||
350 | FSNOTIFY_OBJ_TYPE_INODE); | ||
343 | if (error) | 351 | if (error) |
344 | path_put(path); | 352 | path_put(path); |
353 | |||
345 | return error; | 354 | return error; |
346 | } | 355 | } |
347 | 356 | ||
@@ -733,7 +742,8 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, | |||
733 | if (mask & IN_ONLYDIR) | 742 | if (mask & IN_ONLYDIR) |
734 | flags |= LOOKUP_DIRECTORY; | 743 | flags |= LOOKUP_DIRECTORY; |
735 | 744 | ||
736 | ret = inotify_find_inode(pathname, &path, flags); | 745 | ret = inotify_find_inode(pathname, &path, flags, |
746 | (mask & IN_ALL_EVENTS)); | ||
737 | if (ret) | 747 | if (ret) |
738 | goto fput_and_out; | 748 | goto fput_and_out; |
739 | 749 | ||
diff --git a/include/linux/cred.h b/include/linux/cred.h index f7a30e0099be..18639c069263 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
@@ -386,7 +386,6 @@ static inline void put_cred(const struct cred *_cred) | |||
386 | #define current_fsgid() (current_cred_xxx(fsgid)) | 386 | #define current_fsgid() (current_cred_xxx(fsgid)) |
387 | #define current_cap() (current_cred_xxx(cap_effective)) | 387 | #define current_cap() (current_cred_xxx(cap_effective)) |
388 | #define current_user() (current_cred_xxx(user)) | 388 | #define current_user() (current_cred_xxx(user)) |
389 | #define current_security() (current_cred_xxx(security)) | ||
390 | 389 | ||
391 | extern struct user_namespace init_user_ns; | 390 | extern struct user_namespace init_user_ns; |
392 | #ifdef CONFIG_USER_NS | 391 | #ifdef CONFIG_USER_NS |
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index df1318d85f7d..3fced5824aee 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h | |||
@@ -339,6 +339,9 @@ | |||
339 | * Check for permission to change root directory. | 339 | * Check for permission to change root directory. |
340 | * @path contains the path structure. | 340 | * @path contains the path structure. |
341 | * Return 0 if permission is granted. | 341 | * Return 0 if permission is granted. |
342 | * @path_notify: | ||
343 | * Check permissions before setting a watch on events as defined by @mask, | ||
344 | * on an object at @path, whose type is defined by @obj_type. | ||
342 | * @inode_readlink: | 345 | * @inode_readlink: |
343 | * Check the permission to read the symbolic link. | 346 | * Check the permission to read the symbolic link. |
344 | * @dentry contains the dentry structure for the file link. | 347 | * @dentry contains the dentry structure for the file link. |
@@ -1535,7 +1538,9 @@ union security_list_options { | |||
1535 | int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); | 1538 | int (*path_chown)(const struct path *path, kuid_t uid, kgid_t gid); |
1536 | int (*path_chroot)(const struct path *path); | 1539 | int (*path_chroot)(const struct path *path); |
1537 | #endif | 1540 | #endif |
1538 | 1541 | /* Needed for inode based security check */ | |
1542 | int (*path_notify)(const struct path *path, u64 mask, | ||
1543 | unsigned int obj_type); | ||
1539 | int (*inode_alloc_security)(struct inode *inode); | 1544 | int (*inode_alloc_security)(struct inode *inode); |
1540 | void (*inode_free_security)(struct inode *inode); | 1545 | void (*inode_free_security)(struct inode *inode); |
1541 | int (*inode_init_security)(struct inode *inode, struct inode *dir, | 1546 | int (*inode_init_security)(struct inode *inode, struct inode *dir, |
@@ -1860,6 +1865,8 @@ struct security_hook_heads { | |||
1860 | struct hlist_head path_chown; | 1865 | struct hlist_head path_chown; |
1861 | struct hlist_head path_chroot; | 1866 | struct hlist_head path_chroot; |
1862 | #endif | 1867 | #endif |
1868 | /* Needed for inode based modules as well */ | ||
1869 | struct hlist_head path_notify; | ||
1863 | struct hlist_head inode_alloc_security; | 1870 | struct hlist_head inode_alloc_security; |
1864 | struct hlist_head inode_free_security; | 1871 | struct hlist_head inode_free_security; |
1865 | struct hlist_head inode_init_security; | 1872 | struct hlist_head inode_init_security; |
diff --git a/include/linux/security.h b/include/linux/security.h index 5f7441abbf42..ace6fdb604f9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -259,7 +259,8 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, | |||
259 | struct qstr *name, | 259 | struct qstr *name, |
260 | const struct cred *old, | 260 | const struct cred *old, |
261 | struct cred *new); | 261 | struct cred *new); |
262 | 262 | int security_path_notify(const struct path *path, u64 mask, | |
263 | unsigned int obj_type); | ||
263 | int security_inode_alloc(struct inode *inode); | 264 | int security_inode_alloc(struct inode *inode); |
264 | void security_inode_free(struct inode *inode); | 265 | void security_inode_free(struct inode *inode); |
265 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 266 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
@@ -387,7 +388,6 @@ int security_ismaclabel(const char *name); | |||
387 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | 388 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); |
388 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); | 389 | int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); |
389 | void security_release_secctx(char *secdata, u32 seclen); | 390 | void security_release_secctx(char *secdata, u32 seclen); |
390 | |||
391 | void security_inode_invalidate_secctx(struct inode *inode); | 391 | void security_inode_invalidate_secctx(struct inode *inode); |
392 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); | 392 | int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); |
393 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); | 393 | int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); |
@@ -621,6 +621,12 @@ static inline int security_move_mount(const struct path *from_path, | |||
621 | return 0; | 621 | return 0; |
622 | } | 622 | } |
623 | 623 | ||
624 | static inline int security_path_notify(const struct path *path, u64 mask, | ||
625 | unsigned int obj_type) | ||
626 | { | ||
627 | return 0; | ||
628 | } | ||
629 | |||
624 | static inline int security_inode_alloc(struct inode *inode) | 630 | static inline int security_inode_alloc(struct inode *inode) |
625 | { | 631 | { |
626 | return 0; | 632 | return 0; |
diff --git a/security/security.c b/security/security.c index 250ee2d76406..25ee5c75551f 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -870,6 +870,12 @@ int security_move_mount(const struct path *from_path, const struct path *to_path | |||
870 | return call_int_hook(move_mount, 0, from_path, to_path); | 870 | return call_int_hook(move_mount, 0, from_path, to_path); |
871 | } | 871 | } |
872 | 872 | ||
873 | int security_path_notify(const struct path *path, u64 mask, | ||
874 | unsigned int obj_type) | ||
875 | { | ||
876 | return call_int_hook(path_notify, 0, path, mask, obj_type); | ||
877 | } | ||
878 | |||
873 | int security_inode_alloc(struct inode *inode) | 879 | int security_inode_alloc(struct inode *inode) |
874 | { | 880 | { |
875 | int rc = lsm_inode_alloc(inode); | 881 | int rc = lsm_inode_alloc(inode); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 74dd46de01b6..9625b99e677f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -89,6 +89,8 @@ | |||
89 | #include <linux/kernfs.h> | 89 | #include <linux/kernfs.h> |
90 | #include <linux/stringhash.h> /* for hashlen_string() */ | 90 | #include <linux/stringhash.h> /* for hashlen_string() */ |
91 | #include <uapi/linux/mount.h> | 91 | #include <uapi/linux/mount.h> |
92 | #include <linux/fsnotify.h> | ||
93 | #include <linux/fanotify.h> | ||
92 | 94 | ||
93 | #include "avc.h" | 95 | #include "avc.h" |
94 | #include "objsec.h" | 96 | #include "objsec.h" |
@@ -3275,6 +3277,50 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name) | |||
3275 | return -EACCES; | 3277 | return -EACCES; |
3276 | } | 3278 | } |
3277 | 3279 | ||
3280 | static int selinux_path_notify(const struct path *path, u64 mask, | ||
3281 | unsigned int obj_type) | ||
3282 | { | ||
3283 | int ret; | ||
3284 | u32 perm; | ||
3285 | |||
3286 | struct common_audit_data ad; | ||
3287 | |||
3288 | ad.type = LSM_AUDIT_DATA_PATH; | ||
3289 | ad.u.path = *path; | ||
3290 | |||
3291 | /* | ||
3292 | * Set permission needed based on the type of mark being set. | ||
3293 | * Performs an additional check for sb watches. | ||
3294 | */ | ||
3295 | switch (obj_type) { | ||
3296 | case FSNOTIFY_OBJ_TYPE_VFSMOUNT: | ||
3297 | perm = FILE__WATCH_MOUNT; | ||
3298 | break; | ||
3299 | case FSNOTIFY_OBJ_TYPE_SB: | ||
3300 | perm = FILE__WATCH_SB; | ||
3301 | ret = superblock_has_perm(current_cred(), path->dentry->d_sb, | ||
3302 | FILESYSTEM__WATCH, &ad); | ||
3303 | if (ret) | ||
3304 | return ret; | ||
3305 | break; | ||
3306 | case FSNOTIFY_OBJ_TYPE_INODE: | ||
3307 | perm = FILE__WATCH; | ||
3308 | break; | ||
3309 | default: | ||
3310 | return -EINVAL; | ||
3311 | } | ||
3312 | |||
3313 | /* blocking watches require the file:watch_with_perm permission */ | ||
3314 | if (mask & (ALL_FSNOTIFY_PERM_EVENTS)) | ||
3315 | perm |= FILE__WATCH_WITH_PERM; | ||
3316 | |||
3317 | /* watches on read-like events need the file:watch_reads permission */ | ||
3318 | if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE)) | ||
3319 | perm |= FILE__WATCH_READS; | ||
3320 | |||
3321 | return path_has_perm(current_cred(), path, perm); | ||
3322 | } | ||
3323 | |||
3278 | /* | 3324 | /* |
3279 | * Copy the inode security context value to the user. | 3325 | * Copy the inode security context value to the user. |
3280 | * | 3326 | * |
@@ -3403,7 +3449,7 @@ static int selinux_inode_copy_up_xattr(const char *name) | |||
3403 | static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, | 3449 | static int selinux_kernfs_init_security(struct kernfs_node *kn_dir, |
3404 | struct kernfs_node *kn) | 3450 | struct kernfs_node *kn) |
3405 | { | 3451 | { |
3406 | const struct task_security_struct *tsec = current_security(); | 3452 | const struct task_security_struct *tsec = selinux_cred(current_cred()); |
3407 | u32 parent_sid, newsid, clen; | 3453 | u32 parent_sid, newsid, clen; |
3408 | int rc; | 3454 | int rc; |
3409 | char *context; | 3455 | char *context; |
@@ -6818,6 +6864,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
6818 | LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid), | 6864 | LSM_HOOK_INIT(inode_getsecid, selinux_inode_getsecid), |
6819 | LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), | 6865 | LSM_HOOK_INIT(inode_copy_up, selinux_inode_copy_up), |
6820 | LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), | 6866 | LSM_HOOK_INIT(inode_copy_up_xattr, selinux_inode_copy_up_xattr), |
6867 | LSM_HOOK_INIT(path_notify, selinux_path_notify), | ||
6821 | 6868 | ||
6822 | LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security), | 6869 | LSM_HOOK_INIT(kernfs_init_security, selinux_kernfs_init_security), |
6823 | 6870 | ||
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 201f7e588a29..32e9b03be3dd 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h | |||
@@ -7,7 +7,8 @@ | |||
7 | 7 | ||
8 | #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ | 8 | #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ |
9 | "rename", "execute", "quotaon", "mounton", "audit_access", \ | 9 | "rename", "execute", "quotaon", "mounton", "audit_access", \ |
10 | "open", "execmod" | 10 | "open", "execmod", "watch", "watch_mount", "watch_sb", \ |
11 | "watch_with_perm", "watch_reads" | ||
11 | 12 | ||
12 | #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ | 13 | #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ |
13 | "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ | 14 | "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ |
@@ -60,7 +61,7 @@ struct security_class_mapping secclass_map[] = { | |||
60 | { "filesystem", | 61 | { "filesystem", |
61 | { "mount", "remount", "unmount", "getattr", | 62 | { "mount", "remount", "unmount", "getattr", |
62 | "relabelfrom", "relabelto", "associate", "quotamod", | 63 | "relabelfrom", "relabelto", "associate", "quotamod", |
63 | "quotaget", NULL } }, | 64 | "quotaget", "watch", NULL } }, |
64 | { "file", | 65 | { "file", |
65 | { COMMON_FILE_PERMS, | 66 | { COMMON_FILE_PERMS, |
66 | "execute_no_trans", "entrypoint", NULL } }, | 67 | "execute_no_trans", "entrypoint", NULL } }, |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 91c5395dd20c..586b7abd0aa7 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -37,16 +37,6 @@ struct task_security_struct { | |||
37 | u32 sockcreate_sid; /* fscreate SID */ | 37 | u32 sockcreate_sid; /* fscreate SID */ |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* | ||
41 | * get the subjective security ID of the current task | ||
42 | */ | ||
43 | static inline u32 current_sid(void) | ||
44 | { | ||
45 | const struct task_security_struct *tsec = current_security(); | ||
46 | |||
47 | return tsec->sid; | ||
48 | } | ||
49 | |||
50 | enum label_initialized { | 40 | enum label_initialized { |
51 | LABEL_INVALID, /* invalid or not initialized */ | 41 | LABEL_INVALID, /* invalid or not initialized */ |
52 | LABEL_INITIALIZED, /* initialized */ | 42 | LABEL_INITIALIZED, /* initialized */ |
@@ -185,4 +175,14 @@ static inline struct ipc_security_struct *selinux_ipc( | |||
185 | return ipc->security + selinux_blob_sizes.lbs_ipc; | 175 | return ipc->security + selinux_blob_sizes.lbs_ipc; |
186 | } | 176 | } |
187 | 177 | ||
178 | /* | ||
179 | * get the subjective security ID of the current task | ||
180 | */ | ||
181 | static inline u32 current_sid(void) | ||
182 | { | ||
183 | const struct task_security_struct *tsec = selinux_cred(current_cred()); | ||
184 | |||
185 | return tsec->sid; | ||
186 | } | ||
187 | |||
188 | #endif /* _SELINUX_OBJSEC_H_ */ | 188 | #endif /* _SELINUX_OBJSEC_H_ */ |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 9cb83eeee1d9..e40fecd73752 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
@@ -132,9 +132,9 @@ static void sel_netif_destroy(struct sel_netif *netif) | |||
132 | */ | 132 | */ |
133 | static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) | 133 | static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) |
134 | { | 134 | { |
135 | int ret; | 135 | int ret = 0; |
136 | struct sel_netif *netif; | 136 | struct sel_netif *netif; |
137 | struct sel_netif *new = NULL; | 137 | struct sel_netif *new; |
138 | struct net_device *dev; | 138 | struct net_device *dev; |
139 | 139 | ||
140 | /* NOTE: we always use init's network namespace since we don't | 140 | /* NOTE: we always use init's network namespace since we don't |
@@ -151,32 +151,27 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid) | |||
151 | netif = sel_netif_find(ns, ifindex); | 151 | netif = sel_netif_find(ns, ifindex); |
152 | if (netif != NULL) { | 152 | if (netif != NULL) { |
153 | *sid = netif->nsec.sid; | 153 | *sid = netif->nsec.sid; |
154 | ret = 0; | ||
155 | goto out; | 154 | goto out; |
156 | } | 155 | } |
157 | new = kzalloc(sizeof(*new), GFP_ATOMIC); | 156 | |
158 | if (new == NULL) { | 157 | ret = security_netif_sid(&selinux_state, dev->name, sid); |
159 | ret = -ENOMEM; | ||
160 | goto out; | ||
161 | } | ||
162 | ret = security_netif_sid(&selinux_state, dev->name, &new->nsec.sid); | ||
163 | if (ret != 0) | ||
164 | goto out; | ||
165 | new->nsec.ns = ns; | ||
166 | new->nsec.ifindex = ifindex; | ||
167 | ret = sel_netif_insert(new); | ||
168 | if (ret != 0) | 158 | if (ret != 0) |
169 | goto out; | 159 | goto out; |
170 | *sid = new->nsec.sid; | 160 | new = kzalloc(sizeof(*new), GFP_ATOMIC); |
161 | if (new) { | ||
162 | new->nsec.ns = ns; | ||
163 | new->nsec.ifindex = ifindex; | ||
164 | new->nsec.sid = *sid; | ||
165 | if (sel_netif_insert(new)) | ||
166 | kfree(new); | ||
167 | } | ||
171 | 168 | ||
172 | out: | 169 | out: |
173 | spin_unlock_bh(&sel_netif_lock); | 170 | spin_unlock_bh(&sel_netif_lock); |
174 | dev_put(dev); | 171 | dev_put(dev); |
175 | if (unlikely(ret)) { | 172 | if (unlikely(ret)) |
176 | pr_warn("SELinux: failure in %s(), unable to determine network interface label (%d)\n", | 173 | pr_warn("SELinux: failure in %s(), unable to determine network interface label (%d)\n", |
177 | __func__, ifindex); | 174 | __func__, ifindex); |
178 | kfree(new); | ||
179 | } | ||
180 | return ret; | 175 | return ret; |
181 | } | 176 | } |
182 | 177 | ||
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index cae1fcaffd1a..9ab84efa46c7 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -189,9 +189,9 @@ static void sel_netnode_insert(struct sel_netnode *node) | |||
189 | */ | 189 | */ |
190 | static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) | 190 | static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) |
191 | { | 191 | { |
192 | int ret = -ENOMEM; | 192 | int ret; |
193 | struct sel_netnode *node; | 193 | struct sel_netnode *node; |
194 | struct sel_netnode *new = NULL; | 194 | struct sel_netnode *new; |
195 | 195 | ||
196 | spin_lock_bh(&sel_netnode_lock); | 196 | spin_lock_bh(&sel_netnode_lock); |
197 | node = sel_netnode_find(addr, family); | 197 | node = sel_netnode_find(addr, family); |
@@ -200,38 +200,36 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid) | |||
200 | spin_unlock_bh(&sel_netnode_lock); | 200 | spin_unlock_bh(&sel_netnode_lock); |
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | |||
203 | new = kzalloc(sizeof(*new), GFP_ATOMIC); | 204 | new = kzalloc(sizeof(*new), GFP_ATOMIC); |
204 | if (new == NULL) | ||
205 | goto out; | ||
206 | switch (family) { | 205 | switch (family) { |
207 | case PF_INET: | 206 | case PF_INET: |
208 | ret = security_node_sid(&selinux_state, PF_INET, | 207 | ret = security_node_sid(&selinux_state, PF_INET, |
209 | addr, sizeof(struct in_addr), sid); | 208 | addr, sizeof(struct in_addr), sid); |
210 | new->nsec.addr.ipv4 = *(__be32 *)addr; | 209 | if (new) |
210 | new->nsec.addr.ipv4 = *(__be32 *)addr; | ||
211 | break; | 211 | break; |
212 | case PF_INET6: | 212 | case PF_INET6: |
213 | ret = security_node_sid(&selinux_state, PF_INET6, | 213 | ret = security_node_sid(&selinux_state, PF_INET6, |
214 | addr, sizeof(struct in6_addr), sid); | 214 | addr, sizeof(struct in6_addr), sid); |
215 | new->nsec.addr.ipv6 = *(struct in6_addr *)addr; | 215 | if (new) |
216 | new->nsec.addr.ipv6 = *(struct in6_addr *)addr; | ||
216 | break; | 217 | break; |
217 | default: | 218 | default: |
218 | BUG(); | 219 | BUG(); |
219 | ret = -EINVAL; | 220 | ret = -EINVAL; |
220 | } | 221 | } |
221 | if (ret != 0) | 222 | if (ret == 0 && new) { |
222 | goto out; | 223 | new->nsec.family = family; |
223 | 224 | new->nsec.sid = *sid; | |
224 | new->nsec.family = family; | 225 | sel_netnode_insert(new); |
225 | new->nsec.sid = *sid; | 226 | } else |
226 | sel_netnode_insert(new); | 227 | kfree(new); |
227 | 228 | ||
228 | out: | ||
229 | spin_unlock_bh(&sel_netnode_lock); | 229 | spin_unlock_bh(&sel_netnode_lock); |
230 | if (unlikely(ret)) { | 230 | if (unlikely(ret)) |
231 | pr_warn("SELinux: failure in %s(), unable to determine network node label\n", | 231 | pr_warn("SELinux: failure in %s(), unable to determine network node label\n", |
232 | __func__); | 232 | __func__); |
233 | kfree(new); | ||
234 | } | ||
235 | return ret; | 233 | return ret; |
236 | } | 234 | } |
237 | 235 | ||
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index 364b6d5b8968..3f8b2c0458c8 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
@@ -137,9 +137,9 @@ static void sel_netport_insert(struct sel_netport *port) | |||
137 | */ | 137 | */ |
138 | static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) | 138 | static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) |
139 | { | 139 | { |
140 | int ret = -ENOMEM; | 140 | int ret; |
141 | struct sel_netport *port; | 141 | struct sel_netport *port; |
142 | struct sel_netport *new = NULL; | 142 | struct sel_netport *new; |
143 | 143 | ||
144 | spin_lock_bh(&sel_netport_lock); | 144 | spin_lock_bh(&sel_netport_lock); |
145 | port = sel_netport_find(protocol, pnum); | 145 | port = sel_netport_find(protocol, pnum); |
@@ -148,25 +148,23 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) | |||
148 | spin_unlock_bh(&sel_netport_lock); | 148 | spin_unlock_bh(&sel_netport_lock); |
149 | return 0; | 149 | return 0; |
150 | } | 150 | } |
151 | new = kzalloc(sizeof(*new), GFP_ATOMIC); | 151 | |
152 | if (new == NULL) | ||
153 | goto out; | ||
154 | ret = security_port_sid(&selinux_state, protocol, pnum, sid); | 152 | ret = security_port_sid(&selinux_state, protocol, pnum, sid); |
155 | if (ret != 0) | 153 | if (ret != 0) |
156 | goto out; | 154 | goto out; |
157 | 155 | new = kzalloc(sizeof(*new), GFP_ATOMIC); | |
158 | new->psec.port = pnum; | 156 | if (new) { |
159 | new->psec.protocol = protocol; | 157 | new->psec.port = pnum; |
160 | new->psec.sid = *sid; | 158 | new->psec.protocol = protocol; |
161 | sel_netport_insert(new); | 159 | new->psec.sid = *sid; |
160 | sel_netport_insert(new); | ||
161 | } | ||
162 | 162 | ||
163 | out: | 163 | out: |
164 | spin_unlock_bh(&sel_netport_lock); | 164 | spin_unlock_bh(&sel_netport_lock); |
165 | if (unlikely(ret)) { | 165 | if (unlikely(ret)) |
166 | pr_warn("SELinux: failure in %s(), unable to determine network port label\n", | 166 | pr_warn("SELinux: failure in %s(), unable to determine network port label\n", |
167 | __func__); | 167 | __func__); |
168 | kfree(new); | ||
169 | } | ||
170 | return ret; | 168 | return ret; |
171 | } | 169 | } |
172 | 170 | ||
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f8efaa9f647c..1260f5fb766e 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -177,6 +177,195 @@ static struct policydb_compat_info *policydb_lookup_compat(int version) | |||
177 | } | 177 | } |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * The following *_destroy functions are used to | ||
181 | * free any memory allocated for each kind of | ||
182 | * symbol data in the policy database. | ||
183 | */ | ||
184 | |||
185 | static int perm_destroy(void *key, void *datum, void *p) | ||
186 | { | ||
187 | kfree(key); | ||
188 | kfree(datum); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static int common_destroy(void *key, void *datum, void *p) | ||
193 | { | ||
194 | struct common_datum *comdatum; | ||
195 | |||
196 | kfree(key); | ||
197 | if (datum) { | ||
198 | comdatum = datum; | ||
199 | hashtab_map(comdatum->permissions.table, perm_destroy, NULL); | ||
200 | hashtab_destroy(comdatum->permissions.table); | ||
201 | } | ||
202 | kfree(datum); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static void constraint_expr_destroy(struct constraint_expr *expr) | ||
207 | { | ||
208 | if (expr) { | ||
209 | ebitmap_destroy(&expr->names); | ||
210 | if (expr->type_names) { | ||
211 | ebitmap_destroy(&expr->type_names->types); | ||
212 | ebitmap_destroy(&expr->type_names->negset); | ||
213 | kfree(expr->type_names); | ||
214 | } | ||
215 | kfree(expr); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static int cls_destroy(void *key, void *datum, void *p) | ||
220 | { | ||
221 | struct class_datum *cladatum; | ||
222 | struct constraint_node *constraint, *ctemp; | ||
223 | struct constraint_expr *e, *etmp; | ||
224 | |||
225 | kfree(key); | ||
226 | if (datum) { | ||
227 | cladatum = datum; | ||
228 | hashtab_map(cladatum->permissions.table, perm_destroy, NULL); | ||
229 | hashtab_destroy(cladatum->permissions.table); | ||
230 | constraint = cladatum->constraints; | ||
231 | while (constraint) { | ||
232 | e = constraint->expr; | ||
233 | while (e) { | ||
234 | etmp = e; | ||
235 | e = e->next; | ||
236 | constraint_expr_destroy(etmp); | ||
237 | } | ||
238 | ctemp = constraint; | ||
239 | constraint = constraint->next; | ||
240 | kfree(ctemp); | ||
241 | } | ||
242 | |||
243 | constraint = cladatum->validatetrans; | ||
244 | while (constraint) { | ||
245 | e = constraint->expr; | ||
246 | while (e) { | ||
247 | etmp = e; | ||
248 | e = e->next; | ||
249 | constraint_expr_destroy(etmp); | ||
250 | } | ||
251 | ctemp = constraint; | ||
252 | constraint = constraint->next; | ||
253 | kfree(ctemp); | ||
254 | } | ||
255 | kfree(cladatum->comkey); | ||
256 | } | ||
257 | kfree(datum); | ||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static int role_destroy(void *key, void *datum, void *p) | ||
262 | { | ||
263 | struct role_datum *role; | ||
264 | |||
265 | kfree(key); | ||
266 | if (datum) { | ||
267 | role = datum; | ||
268 | ebitmap_destroy(&role->dominates); | ||
269 | ebitmap_destroy(&role->types); | ||
270 | } | ||
271 | kfree(datum); | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static int type_destroy(void *key, void *datum, void *p) | ||
276 | { | ||
277 | kfree(key); | ||
278 | kfree(datum); | ||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static int user_destroy(void *key, void *datum, void *p) | ||
283 | { | ||
284 | struct user_datum *usrdatum; | ||
285 | |||
286 | kfree(key); | ||
287 | if (datum) { | ||
288 | usrdatum = datum; | ||
289 | ebitmap_destroy(&usrdatum->roles); | ||
290 | ebitmap_destroy(&usrdatum->range.level[0].cat); | ||
291 | ebitmap_destroy(&usrdatum->range.level[1].cat); | ||
292 | ebitmap_destroy(&usrdatum->dfltlevel.cat); | ||
293 | } | ||
294 | kfree(datum); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int sens_destroy(void *key, void *datum, void *p) | ||
299 | { | ||
300 | struct level_datum *levdatum; | ||
301 | |||
302 | kfree(key); | ||
303 | if (datum) { | ||
304 | levdatum = datum; | ||
305 | if (levdatum->level) | ||
306 | ebitmap_destroy(&levdatum->level->cat); | ||
307 | kfree(levdatum->level); | ||
308 | } | ||
309 | kfree(datum); | ||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int cat_destroy(void *key, void *datum, void *p) | ||
314 | { | ||
315 | kfree(key); | ||
316 | kfree(datum); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | ||
321 | { | ||
322 | common_destroy, | ||
323 | cls_destroy, | ||
324 | role_destroy, | ||
325 | type_destroy, | ||
326 | user_destroy, | ||
327 | cond_destroy_bool, | ||
328 | sens_destroy, | ||
329 | cat_destroy, | ||
330 | }; | ||
331 | |||
332 | static int filenametr_destroy(void *key, void *datum, void *p) | ||
333 | { | ||
334 | struct filename_trans *ft = key; | ||
335 | |||
336 | kfree(ft->name); | ||
337 | kfree(key); | ||
338 | kfree(datum); | ||
339 | cond_resched(); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int range_tr_destroy(void *key, void *datum, void *p) | ||
344 | { | ||
345 | struct mls_range *rt = datum; | ||
346 | |||
347 | kfree(key); | ||
348 | ebitmap_destroy(&rt->level[0].cat); | ||
349 | ebitmap_destroy(&rt->level[1].cat); | ||
350 | kfree(datum); | ||
351 | cond_resched(); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static void ocontext_destroy(struct ocontext *c, int i) | ||
356 | { | ||
357 | if (!c) | ||
358 | return; | ||
359 | |||
360 | context_destroy(&c->context[0]); | ||
361 | context_destroy(&c->context[1]); | ||
362 | if (i == OCON_ISID || i == OCON_FS || | ||
363 | i == OCON_NETIF || i == OCON_FSUSE) | ||
364 | kfree(c->u.name); | ||
365 | kfree(c); | ||
366 | } | ||
367 | |||
368 | /* | ||
180 | * Initialize the role table. | 369 | * Initialize the role table. |
181 | */ | 370 | */ |
182 | static int roles_init(struct policydb *p) | 371 | static int roles_init(struct policydb *p) |
@@ -250,6 +439,7 @@ static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2) | |||
250 | static u32 rangetr_hash(struct hashtab *h, const void *k) | 439 | static u32 rangetr_hash(struct hashtab *h, const void *k) |
251 | { | 440 | { |
252 | const struct range_trans *key = k; | 441 | const struct range_trans *key = k; |
442 | |||
253 | return (key->source_type + (key->target_type << 3) + | 443 | return (key->source_type + (key->target_type << 3) + |
254 | (key->target_class << 5)) & (h->size - 1); | 444 | (key->target_class << 5)) & (h->size - 1); |
255 | } | 445 | } |
@@ -272,8 +462,6 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2) | |||
272 | return v; | 462 | return v; |
273 | } | 463 | } |
274 | 464 | ||
275 | static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap); | ||
276 | |||
277 | /* | 465 | /* |
278 | * Initialize a policy database structure. | 466 | * Initialize a policy database structure. |
279 | */ | 467 | */ |
@@ -301,7 +489,8 @@ static int policydb_init(struct policydb *p) | |||
301 | if (rc) | 489 | if (rc) |
302 | goto out; | 490 | goto out; |
303 | 491 | ||
304 | p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10)); | 492 | p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, |
493 | (1 << 10)); | ||
305 | if (!p->filename_trans) { | 494 | if (!p->filename_trans) { |
306 | rc = -ENOMEM; | 495 | rc = -ENOMEM; |
307 | goto out; | 496 | goto out; |
@@ -399,7 +588,7 @@ static int type_index(void *key, void *datum, void *datap) | |||
399 | || typdatum->bounds > p->p_types.nprim) | 588 | || typdatum->bounds > p->p_types.nprim) |
400 | return -EINVAL; | 589 | return -EINVAL; |
401 | p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key; | 590 | p->sym_val_to_name[SYM_TYPES][typdatum->value - 1] = key; |
402 | p->type_val_to_struct_array[typdatum->value - 1] = typdatum; | 591 | p->type_val_to_struct[typdatum->value - 1] = typdatum; |
403 | } | 592 | } |
404 | 593 | ||
405 | return 0; | 594 | return 0; |
@@ -477,9 +666,9 @@ static void hash_eval(struct hashtab *h, const char *hash_name) | |||
477 | struct hashtab_info info; | 666 | struct hashtab_info info; |
478 | 667 | ||
479 | hashtab_stat(h, &info); | 668 | hashtab_stat(h, &info); |
480 | pr_debug("SELinux: %s: %d entries and %d/%d buckets used, " | 669 | pr_debug("SELinux: %s: %d entries and %d/%d buckets used, longest chain length %d\n", |
481 | "longest chain length %d\n", hash_name, h->nel, | 670 | hash_name, h->nel, info.slots_used, h->size, |
482 | info.slots_used, h->size, info.max_chain_len); | 671 | info.max_chain_len); |
483 | } | 672 | } |
484 | 673 | ||
485 | static void symtab_hash_eval(struct symtab *s) | 674 | static void symtab_hash_eval(struct symtab *s) |
@@ -541,10 +730,10 @@ static int policydb_index(struct policydb *p) | |||
541 | if (!p->user_val_to_struct) | 730 | if (!p->user_val_to_struct) |
542 | return -ENOMEM; | 731 | return -ENOMEM; |
543 | 732 | ||
544 | p->type_val_to_struct_array = kvcalloc(p->p_types.nprim, | 733 | p->type_val_to_struct = kvcalloc(p->p_types.nprim, |
545 | sizeof(*p->type_val_to_struct_array), | 734 | sizeof(*p->type_val_to_struct), |
546 | GFP_KERNEL); | 735 | GFP_KERNEL); |
547 | if (!p->type_val_to_struct_array) | 736 | if (!p->type_val_to_struct) |
548 | return -ENOMEM; | 737 | return -ENOMEM; |
549 | 738 | ||
550 | rc = cond_init_bool_indexes(p); | 739 | rc = cond_init_bool_indexes(p); |
@@ -568,193 +757,6 @@ out: | |||
568 | } | 757 | } |
569 | 758 | ||
570 | /* | 759 | /* |
571 | * The following *_destroy functions are used to | ||
572 | * free any memory allocated for each kind of | ||
573 | * symbol data in the policy database. | ||
574 | */ | ||
575 | |||
576 | static int perm_destroy(void *key, void *datum, void *p) | ||
577 | { | ||
578 | kfree(key); | ||
579 | kfree(datum); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int common_destroy(void *key, void *datum, void *p) | ||
584 | { | ||
585 | struct common_datum *comdatum; | ||
586 | |||
587 | kfree(key); | ||
588 | if (datum) { | ||
589 | comdatum = datum; | ||
590 | hashtab_map(comdatum->permissions.table, perm_destroy, NULL); | ||
591 | hashtab_destroy(comdatum->permissions.table); | ||
592 | } | ||
593 | kfree(datum); | ||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | static void constraint_expr_destroy(struct constraint_expr *expr) | ||
598 | { | ||
599 | if (expr) { | ||
600 | ebitmap_destroy(&expr->names); | ||
601 | if (expr->type_names) { | ||
602 | ebitmap_destroy(&expr->type_names->types); | ||
603 | ebitmap_destroy(&expr->type_names->negset); | ||
604 | kfree(expr->type_names); | ||
605 | } | ||
606 | kfree(expr); | ||
607 | } | ||
608 | } | ||
609 | |||
610 | static int cls_destroy(void *key, void *datum, void *p) | ||
611 | { | ||
612 | struct class_datum *cladatum; | ||
613 | struct constraint_node *constraint, *ctemp; | ||
614 | struct constraint_expr *e, *etmp; | ||
615 | |||
616 | kfree(key); | ||
617 | if (datum) { | ||
618 | cladatum = datum; | ||
619 | hashtab_map(cladatum->permissions.table, perm_destroy, NULL); | ||
620 | hashtab_destroy(cladatum->permissions.table); | ||
621 | constraint = cladatum->constraints; | ||
622 | while (constraint) { | ||
623 | e = constraint->expr; | ||
624 | while (e) { | ||
625 | etmp = e; | ||
626 | e = e->next; | ||
627 | constraint_expr_destroy(etmp); | ||
628 | } | ||
629 | ctemp = constraint; | ||
630 | constraint = constraint->next; | ||
631 | kfree(ctemp); | ||
632 | } | ||
633 | |||
634 | constraint = cladatum->validatetrans; | ||
635 | while (constraint) { | ||
636 | e = constraint->expr; | ||
637 | while (e) { | ||
638 | etmp = e; | ||
639 | e = e->next; | ||
640 | constraint_expr_destroy(etmp); | ||
641 | } | ||
642 | ctemp = constraint; | ||
643 | constraint = constraint->next; | ||
644 | kfree(ctemp); | ||
645 | } | ||
646 | kfree(cladatum->comkey); | ||
647 | } | ||
648 | kfree(datum); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int role_destroy(void *key, void *datum, void *p) | ||
653 | { | ||
654 | struct role_datum *role; | ||
655 | |||
656 | kfree(key); | ||
657 | if (datum) { | ||
658 | role = datum; | ||
659 | ebitmap_destroy(&role->dominates); | ||
660 | ebitmap_destroy(&role->types); | ||
661 | } | ||
662 | kfree(datum); | ||
663 | return 0; | ||
664 | } | ||
665 | |||
666 | static int type_destroy(void *key, void *datum, void *p) | ||
667 | { | ||
668 | kfree(key); | ||
669 | kfree(datum); | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static int user_destroy(void *key, void *datum, void *p) | ||
674 | { | ||
675 | struct user_datum *usrdatum; | ||
676 | |||
677 | kfree(key); | ||
678 | if (datum) { | ||
679 | usrdatum = datum; | ||
680 | ebitmap_destroy(&usrdatum->roles); | ||
681 | ebitmap_destroy(&usrdatum->range.level[0].cat); | ||
682 | ebitmap_destroy(&usrdatum->range.level[1].cat); | ||
683 | ebitmap_destroy(&usrdatum->dfltlevel.cat); | ||
684 | } | ||
685 | kfree(datum); | ||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | static int sens_destroy(void *key, void *datum, void *p) | ||
690 | { | ||
691 | struct level_datum *levdatum; | ||
692 | |||
693 | kfree(key); | ||
694 | if (datum) { | ||
695 | levdatum = datum; | ||
696 | if (levdatum->level) | ||
697 | ebitmap_destroy(&levdatum->level->cat); | ||
698 | kfree(levdatum->level); | ||
699 | } | ||
700 | kfree(datum); | ||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | static int cat_destroy(void *key, void *datum, void *p) | ||
705 | { | ||
706 | kfree(key); | ||
707 | kfree(datum); | ||
708 | return 0; | ||
709 | } | ||
710 | |||
711 | static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | ||
712 | { | ||
713 | common_destroy, | ||
714 | cls_destroy, | ||
715 | role_destroy, | ||
716 | type_destroy, | ||
717 | user_destroy, | ||
718 | cond_destroy_bool, | ||
719 | sens_destroy, | ||
720 | cat_destroy, | ||
721 | }; | ||
722 | |||
723 | static int filenametr_destroy(void *key, void *datum, void *p) | ||
724 | { | ||
725 | struct filename_trans *ft = key; | ||
726 | kfree(ft->name); | ||
727 | kfree(key); | ||
728 | kfree(datum); | ||
729 | cond_resched(); | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static int range_tr_destroy(void *key, void *datum, void *p) | ||
734 | { | ||
735 | struct mls_range *rt = datum; | ||
736 | kfree(key); | ||
737 | ebitmap_destroy(&rt->level[0].cat); | ||
738 | ebitmap_destroy(&rt->level[1].cat); | ||
739 | kfree(datum); | ||
740 | cond_resched(); | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static void ocontext_destroy(struct ocontext *c, int i) | ||
745 | { | ||
746 | if (!c) | ||
747 | return; | ||
748 | |||
749 | context_destroy(&c->context[0]); | ||
750 | context_destroy(&c->context[1]); | ||
751 | if (i == OCON_ISID || i == OCON_FS || | ||
752 | i == OCON_NETIF || i == OCON_FSUSE) | ||
753 | kfree(c->u.name); | ||
754 | kfree(c); | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * Free any memory allocated by a policy database structure. | 760 | * Free any memory allocated by a policy database structure. |
759 | */ | 761 | */ |
760 | void policydb_destroy(struct policydb *p) | 762 | void policydb_destroy(struct policydb *p) |
@@ -777,7 +779,7 @@ void policydb_destroy(struct policydb *p) | |||
777 | kfree(p->class_val_to_struct); | 779 | kfree(p->class_val_to_struct); |
778 | kfree(p->role_val_to_struct); | 780 | kfree(p->role_val_to_struct); |
779 | kfree(p->user_val_to_struct); | 781 | kfree(p->user_val_to_struct); |
780 | kvfree(p->type_val_to_struct_array); | 782 | kvfree(p->type_val_to_struct); |
781 | 783 | ||
782 | avtab_destroy(&p->te_avtab); | 784 | avtab_destroy(&p->te_avtab); |
783 | 785 | ||
@@ -1722,7 +1724,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) | |||
1722 | return -EINVAL; | 1724 | return -EINVAL; |
1723 | } | 1725 | } |
1724 | 1726 | ||
1725 | upper = p->type_val_to_struct_array[upper->bounds - 1]; | 1727 | upper = p->type_val_to_struct[upper->bounds - 1]; |
1726 | BUG_ON(!upper); | 1728 | BUG_ON(!upper); |
1727 | 1729 | ||
1728 | if (upper->attribute) { | 1730 | if (upper->attribute) { |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index fcc6366b447f..162d0e79b85b 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -253,7 +253,7 @@ struct policydb { | |||
253 | struct class_datum **class_val_to_struct; | 253 | struct class_datum **class_val_to_struct; |
254 | struct role_datum **role_val_to_struct; | 254 | struct role_datum **role_val_to_struct; |
255 | struct user_datum **user_val_to_struct; | 255 | struct user_datum **user_val_to_struct; |
256 | struct type_datum **type_val_to_struct_array; | 256 | struct type_datum **type_val_to_struct; |
257 | 257 | ||
258 | /* type enforcement access vectors and transitions */ | 258 | /* type enforcement access vectors and transitions */ |
259 | struct avtab te_avtab; | 259 | struct avtab te_avtab; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index d61563a3695e..3a29e7c24ba9 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -542,13 +542,13 @@ static void type_attribute_bounds_av(struct policydb *policydb, | |||
542 | struct type_datum *target; | 542 | struct type_datum *target; |
543 | u32 masked = 0; | 543 | u32 masked = 0; |
544 | 544 | ||
545 | source = policydb->type_val_to_struct_array[scontext->type - 1]; | 545 | source = policydb->type_val_to_struct[scontext->type - 1]; |
546 | BUG_ON(!source); | 546 | BUG_ON(!source); |
547 | 547 | ||
548 | if (!source->bounds) | 548 | if (!source->bounds) |
549 | return; | 549 | return; |
550 | 550 | ||
551 | target = policydb->type_val_to_struct_array[tcontext->type - 1]; | 551 | target = policydb->type_val_to_struct[tcontext->type - 1]; |
552 | BUG_ON(!target); | 552 | BUG_ON(!target); |
553 | 553 | ||
554 | memset(&lo_avd, 0, sizeof(lo_avd)); | 554 | memset(&lo_avd, 0, sizeof(lo_avd)); |
@@ -891,7 +891,7 @@ int security_bounded_transition(struct selinux_state *state, | |||
891 | 891 | ||
892 | index = new_context->type; | 892 | index = new_context->type; |
893 | while (true) { | 893 | while (true) { |
894 | type = policydb->type_val_to_struct_array[index - 1]; | 894 | type = policydb->type_val_to_struct[index - 1]; |
895 | BUG_ON(!type); | 895 | BUG_ON(!type); |
896 | 896 | ||
897 | /* not bounded anymore */ | 897 | /* not bounded anymore */ |
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 1f0a6eaa2d6a..7d49994e8d5f 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/atomic.h> | 15 | #include <asm/barrier.h> |
16 | #include "flask.h" | 16 | #include "flask.h" |
17 | #include "security.h" | 17 | #include "security.h" |
18 | #include "sidtab.h" | 18 | #include "sidtab.h" |
@@ -23,14 +23,14 @@ int sidtab_init(struct sidtab *s) | |||
23 | 23 | ||
24 | memset(s->roots, 0, sizeof(s->roots)); | 24 | memset(s->roots, 0, sizeof(s->roots)); |
25 | 25 | ||
26 | /* max count is SIDTAB_MAX so valid index is always < SIDTAB_MAX */ | ||
26 | for (i = 0; i < SIDTAB_RCACHE_SIZE; i++) | 27 | for (i = 0; i < SIDTAB_RCACHE_SIZE; i++) |
27 | atomic_set(&s->rcache[i], -1); | 28 | s->rcache[i] = SIDTAB_MAX; |
28 | 29 | ||
29 | for (i = 0; i < SECINITSID_NUM; i++) | 30 | for (i = 0; i < SECINITSID_NUM; i++) |
30 | s->isids[i].set = 0; | 31 | s->isids[i].set = 0; |
31 | 32 | ||
32 | atomic_set(&s->count, 0); | 33 | s->count = 0; |
33 | |||
34 | s->convert = NULL; | 34 | s->convert = NULL; |
35 | 35 | ||
36 | spin_lock_init(&s->lock); | 36 | spin_lock_init(&s->lock); |
@@ -130,14 +130,12 @@ static struct context *sidtab_do_lookup(struct sidtab *s, u32 index, int alloc) | |||
130 | 130 | ||
131 | static struct context *sidtab_lookup(struct sidtab *s, u32 index) | 131 | static struct context *sidtab_lookup(struct sidtab *s, u32 index) |
132 | { | 132 | { |
133 | u32 count = (u32)atomic_read(&s->count); | 133 | /* read entries only after reading count */ |
134 | u32 count = smp_load_acquire(&s->count); | ||
134 | 135 | ||
135 | if (index >= count) | 136 | if (index >= count) |
136 | return NULL; | 137 | return NULL; |
137 | 138 | ||
138 | /* read entries after reading count */ | ||
139 | smp_rmb(); | ||
140 | |||
141 | return sidtab_do_lookup(s, index, 0); | 139 | return sidtab_do_lookup(s, index, 0); |
142 | } | 140 | } |
143 | 141 | ||
@@ -210,10 +208,10 @@ static int sidtab_find_context(union sidtab_entry_inner entry, | |||
210 | static void sidtab_rcache_update(struct sidtab *s, u32 index, u32 pos) | 208 | static void sidtab_rcache_update(struct sidtab *s, u32 index, u32 pos) |
211 | { | 209 | { |
212 | while (pos > 0) { | 210 | while (pos > 0) { |
213 | atomic_set(&s->rcache[pos], atomic_read(&s->rcache[pos - 1])); | 211 | WRITE_ONCE(s->rcache[pos], READ_ONCE(s->rcache[pos - 1])); |
214 | --pos; | 212 | --pos; |
215 | } | 213 | } |
216 | atomic_set(&s->rcache[0], (int)index); | 214 | WRITE_ONCE(s->rcache[0], index); |
217 | } | 215 | } |
218 | 216 | ||
219 | static void sidtab_rcache_push(struct sidtab *s, u32 index) | 217 | static void sidtab_rcache_push(struct sidtab *s, u32 index) |
@@ -227,14 +225,14 @@ static int sidtab_rcache_search(struct sidtab *s, struct context *context, | |||
227 | u32 i; | 225 | u32 i; |
228 | 226 | ||
229 | for (i = 0; i < SIDTAB_RCACHE_SIZE; i++) { | 227 | for (i = 0; i < SIDTAB_RCACHE_SIZE; i++) { |
230 | int v = atomic_read(&s->rcache[i]); | 228 | u32 v = READ_ONCE(s->rcache[i]); |
231 | 229 | ||
232 | if (v < 0) | 230 | if (v >= SIDTAB_MAX) |
233 | continue; | 231 | continue; |
234 | 232 | ||
235 | if (context_cmp(sidtab_do_lookup(s, (u32)v, 0), context)) { | 233 | if (context_cmp(sidtab_do_lookup(s, v, 0), context)) { |
236 | sidtab_rcache_update(s, (u32)v, i); | 234 | sidtab_rcache_update(s, v, i); |
237 | *index = (u32)v; | 235 | *index = v; |
238 | return 0; | 236 | return 0; |
239 | } | 237 | } |
240 | } | 238 | } |
@@ -245,8 +243,7 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context, | |||
245 | u32 *index) | 243 | u32 *index) |
246 | { | 244 | { |
247 | unsigned long flags; | 245 | unsigned long flags; |
248 | u32 count = (u32)atomic_read(&s->count); | 246 | u32 count, count_locked, level, pos; |
249 | u32 count_locked, level, pos; | ||
250 | struct sidtab_convert_params *convert; | 247 | struct sidtab_convert_params *convert; |
251 | struct context *dst, *dst_convert; | 248 | struct context *dst, *dst_convert; |
252 | int rc; | 249 | int rc; |
@@ -255,11 +252,10 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context, | |||
255 | if (rc == 0) | 252 | if (rc == 0) |
256 | return 0; | 253 | return 0; |
257 | 254 | ||
255 | /* read entries only after reading count */ | ||
256 | count = smp_load_acquire(&s->count); | ||
258 | level = sidtab_level_from_count(count); | 257 | level = sidtab_level_from_count(count); |
259 | 258 | ||
260 | /* read entries after reading count */ | ||
261 | smp_rmb(); | ||
262 | |||
263 | pos = 0; | 259 | pos = 0; |
264 | rc = sidtab_find_context(s->roots[level], &pos, count, level, | 260 | rc = sidtab_find_context(s->roots[level], &pos, count, level, |
265 | context, index); | 261 | context, index); |
@@ -272,7 +268,7 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context, | |||
272 | spin_lock_irqsave(&s->lock, flags); | 268 | spin_lock_irqsave(&s->lock, flags); |
273 | 269 | ||
274 | convert = s->convert; | 270 | convert = s->convert; |
275 | count_locked = (u32)atomic_read(&s->count); | 271 | count_locked = s->count; |
276 | level = sidtab_level_from_count(count_locked); | 272 | level = sidtab_level_from_count(count_locked); |
277 | 273 | ||
278 | /* if count has changed before we acquired the lock, then catch up */ | 274 | /* if count has changed before we acquired the lock, then catch up */ |
@@ -320,7 +316,7 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context, | |||
320 | } | 316 | } |
321 | 317 | ||
322 | /* at this point we know the insert won't fail */ | 318 | /* at this point we know the insert won't fail */ |
323 | atomic_set(&convert->target->count, count + 1); | 319 | convert->target->count = count + 1; |
324 | } | 320 | } |
325 | 321 | ||
326 | if (context->len) | 322 | if (context->len) |
@@ -331,9 +327,7 @@ static int sidtab_reverse_lookup(struct sidtab *s, struct context *context, | |||
331 | *index = count; | 327 | *index = count; |
332 | 328 | ||
333 | /* write entries before writing new count */ | 329 | /* write entries before writing new count */ |
334 | smp_wmb(); | 330 | smp_store_release(&s->count, count + 1); |
335 | |||
336 | atomic_set(&s->count, count + 1); | ||
337 | 331 | ||
338 | rc = 0; | 332 | rc = 0; |
339 | out_unlock: | 333 | out_unlock: |
@@ -423,7 +417,7 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params) | |||
423 | return -EBUSY; | 417 | return -EBUSY; |
424 | } | 418 | } |
425 | 419 | ||
426 | count = (u32)atomic_read(&s->count); | 420 | count = s->count; |
427 | level = sidtab_level_from_count(count); | 421 | level = sidtab_level_from_count(count); |
428 | 422 | ||
429 | /* allocate last leaf in the new sidtab (to avoid race with | 423 | /* allocate last leaf in the new sidtab (to avoid race with |
@@ -436,7 +430,7 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params) | |||
436 | } | 430 | } |
437 | 431 | ||
438 | /* set count in case no new entries are added during conversion */ | 432 | /* set count in case no new entries are added during conversion */ |
439 | atomic_set(¶ms->target->count, count); | 433 | params->target->count = count; |
440 | 434 | ||
441 | /* enable live convert of new entries */ | 435 | /* enable live convert of new entries */ |
442 | s->convert = params; | 436 | s->convert = params; |
diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index bbd5c0d1f3bd..1f4763141aa1 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h | |||
@@ -40,8 +40,8 @@ union sidtab_entry_inner { | |||
40 | #define SIDTAB_LEAF_ENTRIES \ | 40 | #define SIDTAB_LEAF_ENTRIES \ |
41 | (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry_leaf)) | 41 | (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry_leaf)) |
42 | 42 | ||
43 | #define SIDTAB_MAX_BITS 31 /* limited to INT_MAX due to atomic_t range */ | 43 | #define SIDTAB_MAX_BITS 32 |
44 | #define SIDTAB_MAX (((u32)1 << SIDTAB_MAX_BITS) - 1) | 44 | #define SIDTAB_MAX U32_MAX |
45 | /* ensure enough tree levels for SIDTAB_MAX entries */ | 45 | /* ensure enough tree levels for SIDTAB_MAX entries */ |
46 | #define SIDTAB_MAX_LEVEL \ | 46 | #define SIDTAB_MAX_LEVEL \ |
47 | DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \ | 47 | DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \ |
@@ -69,13 +69,22 @@ struct sidtab_convert_params { | |||
69 | #define SIDTAB_RCACHE_SIZE 3 | 69 | #define SIDTAB_RCACHE_SIZE 3 |
70 | 70 | ||
71 | struct sidtab { | 71 | struct sidtab { |
72 | /* | ||
73 | * lock-free read access only for as many items as a prior read of | ||
74 | * 'count' | ||
75 | */ | ||
72 | union sidtab_entry_inner roots[SIDTAB_MAX_LEVEL + 1]; | 76 | union sidtab_entry_inner roots[SIDTAB_MAX_LEVEL + 1]; |
73 | atomic_t count; | 77 | /* |
78 | * access atomically via {READ|WRITE}_ONCE(); only increment under | ||
79 | * spinlock | ||
80 | */ | ||
81 | u32 count; | ||
82 | /* access only under spinlock */ | ||
74 | struct sidtab_convert_params *convert; | 83 | struct sidtab_convert_params *convert; |
75 | spinlock_t lock; | 84 | spinlock_t lock; |
76 | 85 | ||
77 | /* reverse lookup cache */ | 86 | /* reverse lookup cache - access atomically via {READ|WRITE}_ONCE() */ |
78 | atomic_t rcache[SIDTAB_RCACHE_SIZE]; | 87 | u32 rcache[SIDTAB_RCACHE_SIZE]; |
79 | 88 | ||
80 | /* index == SID - 1 (no entry for SECSID_NULL) */ | 89 | /* index == SID - 1 (no entry for SECSID_NULL) */ |
81 | struct sidtab_isid_entry isids[SECINITSID_NUM]; | 90 | struct sidtab_isid_entry isids[SECINITSID_NUM]; |