1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 21da177e4SLinus Torvalds /* 3ee1a84fdSOndrej Mosnacek * A security identifier table (sidtab) is a lookup table 41da177e4SLinus Torvalds * of security context structures indexed by SID value. 51da177e4SLinus Torvalds * 6ee1a84fdSOndrej Mosnacek * Original author: Stephen Smalley, <sds@tycho.nsa.gov> 7ee1a84fdSOndrej Mosnacek * Author: Ondrej Mosnacek, <omosnacek@gmail.com> 8ee1a84fdSOndrej Mosnacek * 9ee1a84fdSOndrej Mosnacek * Copyright (C) 2018 Red Hat, Inc. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds #ifndef _SS_SIDTAB_H_ 121da177e4SLinus Torvalds #define _SS_SIDTAB_H_ 131da177e4SLinus Torvalds 14ee1a84fdSOndrej Mosnacek #include <linux/spinlock_types.h> 15ee1a84fdSOndrej Mosnacek #include <linux/log2.h> 16*66f8e2f0SJeff Vander Stoep #include <linux/hashtable.h> 17ee1a84fdSOndrej Mosnacek 181da177e4SLinus Torvalds #include "context.h" 191da177e4SLinus Torvalds 20ee1a84fdSOndrej Mosnacek struct sidtab_entry_leaf { 21*66f8e2f0SJeff Vander Stoep u32 sid; 22ee1a84fdSOndrej Mosnacek struct context context; 23*66f8e2f0SJeff Vander Stoep struct hlist_node list; 241da177e4SLinus Torvalds }; 251da177e4SLinus Torvalds 26ee1a84fdSOndrej Mosnacek struct sidtab_node_inner; 27ee1a84fdSOndrej Mosnacek struct sidtab_node_leaf; 281da177e4SLinus Torvalds 29ee1a84fdSOndrej Mosnacek union sidtab_entry_inner { 30ee1a84fdSOndrej Mosnacek struct sidtab_node_inner *ptr_inner; 31ee1a84fdSOndrej Mosnacek struct sidtab_node_leaf *ptr_leaf; 32ee1a84fdSOndrej Mosnacek }; 33ee1a84fdSOndrej Mosnacek 34ee1a84fdSOndrej Mosnacek /* align node size to page boundary */ 35ee1a84fdSOndrej Mosnacek #define SIDTAB_NODE_ALLOC_SHIFT PAGE_SHIFT 36ee1a84fdSOndrej Mosnacek #define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE 37ee1a84fdSOndrej Mosnacek 38ee1a84fdSOndrej Mosnacek #define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size) - 1) + 1)) 39ee1a84fdSOndrej Mosnacek 40ee1a84fdSOndrej Mosnacek #define SIDTAB_INNER_SHIFT \ 41ee1a84fdSOndrej Mosnacek (SIDTAB_NODE_ALLOC_SHIFT - size_to_shift(sizeof(union sidtab_entry_inner))) 42ee1a84fdSOndrej Mosnacek #define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT) 43ee1a84fdSOndrej Mosnacek #define SIDTAB_LEAF_ENTRIES \ 44ee1a84fdSOndrej Mosnacek (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry_leaf)) 45ee1a84fdSOndrej Mosnacek 46116f21bbSOndrej Mosnacek #define SIDTAB_MAX_BITS 32 47116f21bbSOndrej Mosnacek #define SIDTAB_MAX U32_MAX 48ee1a84fdSOndrej Mosnacek /* ensure enough tree levels for SIDTAB_MAX entries */ 49ee1a84fdSOndrej Mosnacek #define SIDTAB_MAX_LEVEL \ 50ee1a84fdSOndrej Mosnacek DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \ 51ee1a84fdSOndrej Mosnacek SIDTAB_INNER_SHIFT) 52ee1a84fdSOndrej Mosnacek 53ee1a84fdSOndrej Mosnacek struct sidtab_node_leaf { 54ee1a84fdSOndrej Mosnacek struct sidtab_entry_leaf entries[SIDTAB_LEAF_ENTRIES]; 55ee1a84fdSOndrej Mosnacek }; 56ee1a84fdSOndrej Mosnacek 57ee1a84fdSOndrej Mosnacek struct sidtab_node_inner { 58ee1a84fdSOndrej Mosnacek union sidtab_entry_inner entries[SIDTAB_INNER_ENTRIES]; 59ee1a84fdSOndrej Mosnacek }; 601da177e4SLinus Torvalds 6124ed7fdaSOndrej Mosnacek struct sidtab_isid_entry { 6224ed7fdaSOndrej Mosnacek int set; 63*66f8e2f0SJeff Vander Stoep struct sidtab_entry_leaf leaf; 6424ed7fdaSOndrej Mosnacek }; 6524ed7fdaSOndrej Mosnacek 66ee1a84fdSOndrej Mosnacek struct sidtab_convert_params { 67ee1a84fdSOndrej Mosnacek int (*func)(struct context *oldc, struct context *newc, void *args); 68ee1a84fdSOndrej Mosnacek void *args; 69ee1a84fdSOndrej Mosnacek struct sidtab *target; 70ee1a84fdSOndrej Mosnacek }; 71ee1a84fdSOndrej Mosnacek 72*66f8e2f0SJeff Vander Stoep #define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS 73*66f8e2f0SJeff Vander Stoep #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) 74ee1a84fdSOndrej Mosnacek 751da177e4SLinus Torvalds struct sidtab { 76116f21bbSOndrej Mosnacek /* 77116f21bbSOndrej Mosnacek * lock-free read access only for as many items as a prior read of 78116f21bbSOndrej Mosnacek * 'count' 79116f21bbSOndrej Mosnacek */ 80ee1a84fdSOndrej Mosnacek union sidtab_entry_inner roots[SIDTAB_MAX_LEVEL + 1]; 81116f21bbSOndrej Mosnacek /* 82116f21bbSOndrej Mosnacek * access atomically via {READ|WRITE}_ONCE(); only increment under 83116f21bbSOndrej Mosnacek * spinlock 84116f21bbSOndrej Mosnacek */ 85116f21bbSOndrej Mosnacek u32 count; 86116f21bbSOndrej Mosnacek /* access only under spinlock */ 87ee1a84fdSOndrej Mosnacek struct sidtab_convert_params *convert; 881da177e4SLinus Torvalds spinlock_t lock; 8924ed7fdaSOndrej Mosnacek 9024ed7fdaSOndrej Mosnacek /* index == SID - 1 (no entry for SECSID_NULL) */ 9124ed7fdaSOndrej Mosnacek struct sidtab_isid_entry isids[SECINITSID_NUM]; 92*66f8e2f0SJeff Vander Stoep 93*66f8e2f0SJeff Vander Stoep /* Hash table for fast reverse context-to-sid lookups. */ 94*66f8e2f0SJeff Vander Stoep DECLARE_HASHTABLE(context_to_sid, SIDTAB_HASH_BITS); 951da177e4SLinus Torvalds }; 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds int sidtab_init(struct sidtab *s); 9824ed7fdaSOndrej Mosnacek int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context); 991da177e4SLinus Torvalds struct context *sidtab_search(struct sidtab *s, u32 sid); 10012b29f34SStephen Smalley struct context *sidtab_search_force(struct sidtab *s, u32 sid); 1011da177e4SLinus Torvalds 102ee1a84fdSOndrej Mosnacek int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); 1031da177e4SLinus Torvalds 10424ed7fdaSOndrej Mosnacek int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds void sidtab_destroy(struct sidtab *s); 1071da177e4SLinus Torvalds 108*66f8e2f0SJeff Vander Stoep int sidtab_hash_stats(struct sidtab *sidtab, char *page); 109*66f8e2f0SJeff Vander Stoep 1101da177e4SLinus Torvalds #endif /* _SS_SIDTAB_H_ */ 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds 113