Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/security/selinux/ss/sidtab.h
26436 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
/*
3
* A security identifier table (sidtab) is a lookup table
4
* of security context structures indexed by SID value.
5
*
6
* Original author: Stephen Smalley, <[email protected]>
7
* Author: Ondrej Mosnacek, <[email protected]>
8
*
9
* Copyright (C) 2018 Red Hat, Inc.
10
*/
11
12
#ifndef _SS_SIDTAB_H_
13
#define _SS_SIDTAB_H_
14
15
#include <linux/spinlock_types.h>
16
#include <linux/log2.h>
17
#include <linux/hashtable.h>
18
19
#include "context.h"
20
21
struct sidtab_entry {
22
u32 sid;
23
u32 hash;
24
struct context context;
25
#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
26
struct sidtab_str_cache __rcu *cache;
27
#endif
28
struct hlist_node list;
29
};
30
31
union sidtab_entry_inner {
32
struct sidtab_node_inner *ptr_inner;
33
struct sidtab_node_leaf *ptr_leaf;
34
};
35
36
/* align node size to page boundary */
37
#define SIDTAB_NODE_ALLOC_SHIFT PAGE_SHIFT
38
#define SIDTAB_NODE_ALLOC_SIZE PAGE_SIZE
39
40
#define size_to_shift(size) ((size) == 1 ? 1 : (const_ilog2((size)-1) + 1))
41
42
#define SIDTAB_INNER_SHIFT \
43
(SIDTAB_NODE_ALLOC_SHIFT - \
44
size_to_shift(sizeof(union sidtab_entry_inner)))
45
#define SIDTAB_INNER_ENTRIES ((size_t)1 << SIDTAB_INNER_SHIFT)
46
#define SIDTAB_LEAF_ENTRIES \
47
(SIDTAB_NODE_ALLOC_SIZE / sizeof(struct sidtab_entry))
48
49
#define SIDTAB_MAX_BITS 32
50
#define SIDTAB_MAX U32_MAX
51
/* ensure enough tree levels for SIDTAB_MAX entries */
52
#define SIDTAB_MAX_LEVEL \
53
DIV_ROUND_UP(SIDTAB_MAX_BITS - size_to_shift(SIDTAB_LEAF_ENTRIES), \
54
SIDTAB_INNER_SHIFT)
55
56
struct sidtab_node_leaf {
57
struct sidtab_entry entries[SIDTAB_LEAF_ENTRIES];
58
};
59
60
struct sidtab_node_inner {
61
union sidtab_entry_inner entries[SIDTAB_INNER_ENTRIES];
62
};
63
64
struct sidtab_isid_entry {
65
int set;
66
struct sidtab_entry entry;
67
};
68
69
struct sidtab_convert_params {
70
struct convert_context_args *args;
71
struct sidtab *target;
72
};
73
74
#define SIDTAB_HASH_BITS CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS
75
#define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS)
76
77
struct sidtab {
78
/*
79
* lock-free read access only for as many items as a prior read of
80
* 'count'
81
*/
82
union sidtab_entry_inner roots[SIDTAB_MAX_LEVEL + 1];
83
/*
84
* access atomically via {READ|WRITE}_ONCE(); only increment under
85
* spinlock
86
*/
87
u32 count;
88
/* access only under spinlock */
89
struct sidtab_convert_params *convert;
90
bool frozen;
91
spinlock_t lock;
92
93
#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
94
/* SID -> context string cache */
95
u32 cache_free_slots;
96
struct list_head cache_lru_list;
97
spinlock_t cache_lock;
98
#endif
99
100
/* index == SID - 1 (no entry for SECSID_NULL) */
101
struct sidtab_isid_entry isids[SECINITSID_NUM];
102
103
/* Hash table for fast reverse context-to-sid lookups. */
104
DECLARE_HASHTABLE(context_to_sid, SIDTAB_HASH_BITS);
105
};
106
107
int sidtab_init(struct sidtab *s);
108
int sidtab_set_initial(struct sidtab *s, u32 sid, struct context *context);
109
struct sidtab_entry *sidtab_search_entry(struct sidtab *s, u32 sid);
110
struct sidtab_entry *sidtab_search_entry_force(struct sidtab *s, u32 sid);
111
112
static inline struct context *sidtab_search(struct sidtab *s, u32 sid)
113
{
114
struct sidtab_entry *entry = sidtab_search_entry(s, sid);
115
116
return entry ? &entry->context : NULL;
117
}
118
119
static inline struct context *sidtab_search_force(struct sidtab *s, u32 sid)
120
{
121
struct sidtab_entry *entry = sidtab_search_entry_force(s, sid);
122
123
return entry ? &entry->context : NULL;
124
}
125
126
int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params);
127
128
void sidtab_cancel_convert(struct sidtab *s);
129
130
void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags)
131
__acquires(&s->lock);
132
void sidtab_freeze_end(struct sidtab *s, unsigned long *flags)
133
__releases(&s->lock);
134
135
int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid);
136
137
void sidtab_destroy(struct sidtab *s);
138
139
int sidtab_hash_stats(struct sidtab *sidtab, char *page);
140
141
#if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0
142
void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry,
143
const char *str, u32 str_len);
144
int sidtab_sid2str_get(struct sidtab *s, struct sidtab_entry *entry, char **out,
145
u32 *out_len);
146
#else
147
static inline void sidtab_sid2str_put(struct sidtab *s,
148
struct sidtab_entry *entry,
149
const char *str, u32 str_len)
150
{
151
}
152
static inline int sidtab_sid2str_get(struct sidtab *s,
153
struct sidtab_entry *entry, char **out,
154
u32 *out_len)
155
{
156
return -ENOENT;
157
}
158
#endif /* CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 */
159
160
#endif /* _SS_SIDTAB_H_ */
161
162