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 20d97bd23cSOndrej Mosnacek struct sidtab_entry { 2166f8e2f0SJeff Vander Stoep u32 sid; 22225621c9SOndrej Mosnacek u32 hash; 23ee1a84fdSOndrej Mosnacek struct context context; 24d97bd23cSOndrej Mosnacek #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 25d97bd23cSOndrej Mosnacek struct sidtab_str_cache __rcu *cache; 26d97bd23cSOndrej Mosnacek #endif 2766f8e2f0SJeff Vander Stoep struct hlist_node list; 281da177e4SLinus Torvalds }; 291da177e4SLinus Torvalds 30ee1a84fdSOndrej Mosnacek union sidtab_entry_inner { 31ee1a84fdSOndrej Mosnacek struct sidtab_node_inner *ptr_inner; 32ee1a84fdSOndrej Mosnacek struct sidtab_node_leaf *ptr_leaf; 33ee1a84fdSOndrej Mosnacek }; 34ee1a84fdSOndrej Mosnacek 35ee1a84fdSOndrej Mosnacek /* align node size to page boundary */ 36ee1a84fdSOndrej Mosnacek #define SIDTAB_NODE_ALLOC_SHIFT PAGE_SHIFT 37ee1a84fdSOndrej Mosnacek #define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE 38ee1a84fdSOndrej Mosnacek 39ee1a84fdSOndrej Mosnacek #define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size) - 1) + 1)) 40ee1a84fdSOndrej Mosnacek 41ee1a84fdSOndrej Mosnacek #define SIDTAB_INNER_SHIFT \ 42ee1a84fdSOndrej Mosnacek (SIDTAB_NODE_ALLOC_SHIFT - size_to_shift(sizeof(union sidtab_entry_inner))) 43ee1a84fdSOndrej Mosnacek #define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT) 44ee1a84fdSOndrej Mosnacek #define SIDTAB_LEAF_ENTRIES \ 45d97bd23cSOndrej Mosnacek (SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry)) 46ee1a84fdSOndrej Mosnacek 47116f21bbSOndrej Mosnacek #define SIDTAB_MAX_BITS 32 48116f21bbSOndrej Mosnacek #define SIDTAB_MAX U32_MAX 49ee1a84fdSOndrej Mosnacek /* ensure enough tree levels for SIDTAB_MAX entries */ 50ee1a84fdSOndrej Mosnacek #define SIDTAB_MAX_LEVEL \ 51ee1a84fdSOndrej Mosnacek DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \ 52ee1a84fdSOndrej Mosnacek SIDTAB_INNER_SHIFT) 53ee1a84fdSOndrej Mosnacek 54ee1a84fdSOndrej Mosnacek struct sidtab_node_leaf { 55d97bd23cSOndrej Mosnacek struct sidtab_entry entries[SIDTAB_LEAF_ENTRIES]; 56ee1a84fdSOndrej Mosnacek }; 57ee1a84fdSOndrej Mosnacek 58ee1a84fdSOndrej Mosnacek struct sidtab_node_inner { 59ee1a84fdSOndrej Mosnacek union sidtab_entry_inner entries[SIDTAB_INNER_ENTRIES]; 60ee1a84fdSOndrej Mosnacek }; 611da177e4SLinus Torvalds 6224ed7fdaSOndrej Mosnacek struct sidtab_isid_entry { 6324ed7fdaSOndrej Mosnacek int set; 64d97bd23cSOndrej Mosnacek struct sidtab_entry entry; 6524ed7fdaSOndrej Mosnacek }; 6624ed7fdaSOndrej Mosnacek 67ee1a84fdSOndrej Mosnacek struct sidtab_convert_params { 68ee1a84fdSOndrej Mosnacek int (*func)(struct context *oldc, struct context *newc, void *args); 69ee1a84fdSOndrej Mosnacek void *args; 70ee1a84fdSOndrej Mosnacek struct sidtab *target; 71ee1a84fdSOndrej Mosnacek }; 72ee1a84fdSOndrej Mosnacek 7366f8e2f0SJeff Vander Stoep #define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS 7466f8e2f0SJeff Vander Stoep #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) 75ee1a84fdSOndrej Mosnacek 761da177e4SLinus Torvalds struct sidtab { 77116f21bbSOndrej Mosnacek /* 78116f21bbSOndrej Mosnacek * lock-free read access only for as many items as a prior read of 79116f21bbSOndrej Mosnacek * 'count' 80116f21bbSOndrej Mosnacek */ 81ee1a84fdSOndrej Mosnacek union sidtab_entry_inner roots[SIDTAB_MAX_LEVEL + 1]; 82116f21bbSOndrej Mosnacek /* 83116f21bbSOndrej Mosnacek * access atomically via {READ|WRITE}_ONCE(); only increment under 84116f21bbSOndrej Mosnacek * spinlock 85116f21bbSOndrej Mosnacek */ 86116f21bbSOndrej Mosnacek u32 count; 87116f21bbSOndrej Mosnacek /* access only under spinlock */ 88ee1a84fdSOndrej Mosnacek struct sidtab_convert_params *convert; 891da177e4SLinus Torvalds spinlock_t lock; 9024ed7fdaSOndrej Mosnacek 91d97bd23cSOndrej Mosnacek #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 92d97bd23cSOndrej Mosnacek /* SID -> context string cache */ 93d97bd23cSOndrej Mosnacek u32 cache_free_slots; 94d97bd23cSOndrej Mosnacek struct list_head cache_lru_list; 95d97bd23cSOndrej Mosnacek spinlock_t cache_lock; 96d97bd23cSOndrej Mosnacek #endif 97d97bd23cSOndrej Mosnacek 9824ed7fdaSOndrej Mosnacek /* index == SID - 1 (no entry for SECSID_NULL) */ 9924ed7fdaSOndrej Mosnacek struct sidtab_isid_entry isids[SECINITSID_NUM]; 10066f8e2f0SJeff Vander Stoep 10166f8e2f0SJeff Vander Stoep /* Hash table for fast reverse context-to-sid lookups. */ 10266f8e2f0SJeff Vander Stoep DECLARE_HASHTABLE(context_to_sid, SIDTAB_HASH_BITS); 1031da177e4SLinus Torvalds }; 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds int sidtab_init(struct sidtab *s); 10624ed7fdaSOndrej Mosnacek int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context); 107d97bd23cSOndrej Mosnacek struct sidtab_entry *sidtab_search_entry(struct sidtab *s, u32 sid); 108d97bd23cSOndrej Mosnacek struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid); 109d97bd23cSOndrej Mosnacek 110d97bd23cSOndrej Mosnacek static inline struct context *sidtab_search(struct sidtab *s, u32 sid) 111d97bd23cSOndrej Mosnacek { 112d97bd23cSOndrej Mosnacek struct sidtab_entry *entry = sidtab_search_entry(s, sid); 113d97bd23cSOndrej Mosnacek 114d97bd23cSOndrej Mosnacek return entry ? &entry->context : NULL; 115d97bd23cSOndrej Mosnacek } 116d97bd23cSOndrej Mosnacek 117d97bd23cSOndrej Mosnacek static inline struct context *sidtab_search_force(struct sidtab *s, u32 sid) 118d97bd23cSOndrej Mosnacek { 119d97bd23cSOndrej Mosnacek struct sidtab_entry *entry = sidtab_search_entry_force(s, sid); 120d97bd23cSOndrej Mosnacek 121d97bd23cSOndrej Mosnacek return entry ? &entry->context : NULL; 122d97bd23cSOndrej Mosnacek } 1231da177e4SLinus Torvalds 124ee1a84fdSOndrej Mosnacek int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); 1251da177e4SLinus Torvalds 126*02a52c5cSStephen Smalley void sidtab_cancel_convert(struct sidtab *s); 127*02a52c5cSStephen Smalley 12824ed7fdaSOndrej Mosnacek int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds void sidtab_destroy(struct sidtab *s); 1311da177e4SLinus Torvalds 13266f8e2f0SJeff Vander Stoep int sidtab_hash_stats(struct sidtab *sidtab, char *page); 13366f8e2f0SJeff Vander Stoep 134d97bd23cSOndrej Mosnacek #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 135d97bd23cSOndrej Mosnacek void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry, 136d97bd23cSOndrej Mosnacek const char *str, u32 str_len); 137d97bd23cSOndrej Mosnacek int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, 138d97bd23cSOndrej Mosnacek char **out, u32 *out_len); 139d97bd23cSOndrej Mosnacek #else 140d97bd23cSOndrej Mosnacek static inline void sidtab_sid2str_put(struct sidtab *s, 141d97bd23cSOndrej Mosnacek struct sidtab_entry *entry, 142d97bd23cSOndrej Mosnacek const char *str, u32 str_len) 143d97bd23cSOndrej Mosnacek { 144d97bd23cSOndrej Mosnacek } 145d97bd23cSOndrej Mosnacek static inline int sidtab_sid2str_get(struct sidtab *s, 146d97bd23cSOndrej Mosnacek struct sidtab_entry *entry, 147d97bd23cSOndrej Mosnacek char **out, u32 *out_len) 148d97bd23cSOndrej Mosnacek { 149d97bd23cSOndrej Mosnacek return -ENOENT; 150d97bd23cSOndrej Mosnacek } 151d97bd23cSOndrej Mosnacek #endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */ 152d97bd23cSOndrej Mosnacek 1531da177e4SLinus Torvalds #endif /* _SS_SIDTAB_H_ */ 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds 156