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> 1666f8e2f0SJeff Vander Stoep #include <linux/hashtable.h> 17ee1a84fdSOndrej Mosnacek 181da177e4SLinus Torvalds #include "context.h" 191da177e4SLinus Torvalds 20*d97bd23cSOndrej Mosnacek struct sidtab_entry { 2166f8e2f0SJeff Vander Stoep u32 sid; 22ee1a84fdSOndrej Mosnacek struct context context; 23*d97bd23cSOndrej Mosnacek #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 24*d97bd23cSOndrej Mosnacek struct sidtab_str_cache __rcu *cache; 25*d97bd23cSOndrej Mosnacek #endif 2666f8e2f0SJeff Vander Stoep struct hlist_node list; 271da177e4SLinus Torvalds }; 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 \ 44*d97bd23cSOndrej Mosnacek (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry)) 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 { 54*d97bd23cSOndrej Mosnacek struct sidtab_entry 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*d97bd23cSOndrej Mosnacek struct sidtab_entry entry; 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 7266f8e2f0SJeff Vander Stoep #define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS 7366f8e2f0SJeff 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 90*d97bd23cSOndrej Mosnacek #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 91*d97bd23cSOndrej Mosnacek /* SID -> context string cache */ 92*d97bd23cSOndrej Mosnacek u32 cache_free_slots; 93*d97bd23cSOndrej Mosnacek struct list_head cache_lru_list; 94*d97bd23cSOndrej Mosnacek spinlock_t cache_lock; 95*d97bd23cSOndrej Mosnacek #endif 96*d97bd23cSOndrej Mosnacek 9724ed7fdaSOndrej Mosnacek /* index == SID - 1 (no entry for SECSID_NULL) */ 9824ed7fdaSOndrej Mosnacek struct sidtab_isid_entry isids[SECINITSID_NUM]; 9966f8e2f0SJeff Vander Stoep 10066f8e2f0SJeff Vander Stoep /* Hash table for fast reverse context-to-sid lookups. */ 10166f8e2f0SJeff Vander Stoep DECLARE_HASHTABLE(context_to_sid, SIDTAB_HASH_BITS); 1021da177e4SLinus Torvalds }; 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds int sidtab_init(struct sidtab *s); 10524ed7fdaSOndrej Mosnacek int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context); 106*d97bd23cSOndrej Mosnacek struct sidtab_entry *sidtab_search_entry(struct sidtab *s, u32 sid); 107*d97bd23cSOndrej Mosnacek struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid); 108*d97bd23cSOndrej Mosnacek 109*d97bd23cSOndrej Mosnacek static inline struct context *sidtab_search(struct sidtab *s, u32 sid) 110*d97bd23cSOndrej Mosnacek { 111*d97bd23cSOndrej Mosnacek struct sidtab_entry *entry = sidtab_search_entry(s, sid); 112*d97bd23cSOndrej Mosnacek 113*d97bd23cSOndrej Mosnacek return entry ? &entry->context : NULL; 114*d97bd23cSOndrej Mosnacek } 115*d97bd23cSOndrej Mosnacek 116*d97bd23cSOndrej Mosnacek static inline struct context *sidtab_search_force(struct sidtab *s, u32 sid) 117*d97bd23cSOndrej Mosnacek { 118*d97bd23cSOndrej Mosnacek struct sidtab_entry *entry = sidtab_search_entry_force(s, sid); 119*d97bd23cSOndrej Mosnacek 120*d97bd23cSOndrej Mosnacek return entry ? &entry->context : NULL; 121*d97bd23cSOndrej Mosnacek } 1221da177e4SLinus Torvalds 123ee1a84fdSOndrej Mosnacek int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); 1241da177e4SLinus Torvalds 12524ed7fdaSOndrej Mosnacek int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds void sidtab_destroy(struct sidtab *s); 1281da177e4SLinus Torvalds 12966f8e2f0SJeff Vander Stoep int sidtab_hash_stats(struct sidtab *sidtab, char *page); 13066f8e2f0SJeff Vander Stoep 131*d97bd23cSOndrej Mosnacek #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 132*d97bd23cSOndrej Mosnacek void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, 133*d97bd23cSOndrej Mosnacek const char *str, u32 str_len); 134*d97bd23cSOndrej Mosnacek int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, 135*d97bd23cSOndrej Mosnacek char **out, u32 *out_len); 136*d97bd23cSOndrej Mosnacek #else 137*d97bd23cSOndrej Mosnacek static inline void sidtab_sid2str_put(struct sidtab *s, 138*d97bd23cSOndrej Mosnacek struct sidtab_entry *entry, 139*d97bd23cSOndrej Mosnacek const char *str, u32 str_len) 140*d97bd23cSOndrej Mosnacek { 141*d97bd23cSOndrej Mosnacek } 142*d97bd23cSOndrej Mosnacek static inline int sidtab_sid2str_get(struct sidtab *s, 143*d97bd23cSOndrej Mosnacek struct sidtab_entry *entry, 144*d97bd23cSOndrej Mosnacek char **out, u32 *out_len) 145*d97bd23cSOndrej Mosnacek { 146*d97bd23cSOndrej Mosnacek return -ENOENT; 147*d97bd23cSOndrej Mosnacek } 148*d97bd23cSOndrej Mosnacek #endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */ 149*d97bd23cSOndrej Mosnacek 1501da177e4SLinus Torvalds #endif /* _SS_SIDTAB_H_ */ 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvalds 153